Mybatis学习笔记(四) 其他相关概念(好多有用的工具)

①日志

由于写代码的过程中,有很多时候需要输出调试信息,然后平时我们使用system.out.println的时候就会很麻烦,又不知道是哪个类出了问题、哪个线程出来的,也没办法把关闭调试信息,只能一条条删。

那么! 就有个第三方的日志工具Log4j(不是mybatis自带),开启日志! 知道执行了哪些sql语句,以便进行调试:

首先要准备一个log4j.properties,这里面是日志的配置信息,具体的语义在上一篇专门的log4j学习笔记里面写好啦,这里的具体语句作用也写在了代码注释上面!

# Global logging configuration
log4j.rootLogger=ERROR, stdout #产生日志的级别的ERROR,输出到stdout,这个stdout会设置
# MyBatis logging configuration...
log4j.logger.com.how2java=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender   #stdout就是给他输出到控制台
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n  #这是输出到控制台的格式,分别是 %5p 输出的优先级为5  %t是输出那个线程 %m是输出代码中指定的信息,也就是我们的sql,%n是换行

然后运行我们的测试类就可以看到效果:

里面有我们只想的sql语句,还有各种参数,不要太直白好吧!

②事务管理

之前咱也学过事务的概念。

就是处于同一事务的事情! 要么全都一起成功,要么全都失败,保持一个一致性。

要注意的是,数据库的类型必须的innodb的方式才会支持事务(之前用的myisam更快,但是不支持事务,也不支持外键)

开启innodb之后,执行这段代码:

由于事务的关系就会因为插入的第二段字符串太长了,导致插入的第一条数据也失败。这样就保证了数据的安全。(应该是session.commit之后才是这个事务的提交)

package com.how2java;
   
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.List;
 
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
 
import com.how2java.mapper.CategoryMapper;
import com.how2java.pojo.Category;
   
public class TestMybatis {
   
    public static void main(String[] args) throws IOException, SQLException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
 
        CategoryMapper mapper = session.getMapper(CategoryMapper.class);
  
        Category c1 = new Category();
        c1.setName("长度够短的名称");
        mapper.add(c1);
         
        Category c2 = new Category();
        c2.setName("超过最大长度30的名称超过最大长度30的名称超过最大长度30的名称超过最大长度30的名称超过最大长度30的名称超过最大长度30的名称");
        mapper.add(c2);       
 
        listAll(mapper);
        session.commit();
        session.close();
   
    }
  
    private static void listAll(CategoryMapper mapper) {
        List<Category> cs = mapper.list();
        for (Category c : cs) {
            System.out.println(c.getName());
        }
    }
}

③延迟加载

就是昨天咱写的数据库一对多的情况的时候,是实现了category对product的一对多。

然后咱在查询category的时候,有时候并不会用上product集合,但是!mybatis也会给我们一并的把product加载了,这就会浪费资源。

所谓延迟加载呢,就是说我们查询category,ok,那么我就只把category给你处理好,只有当你在调用product对应的查询的时候才会去动product,节省了资源!

设置方法,在mybatis-config.xml中设置开启延迟加载:

<settings> 
         <!-- 打开延迟加载的开关 --> 
         <setting name="lazyLoadingEnabled" value="true" /> 
         <!-- 将积极加载改为消息加载即按需加载 --> 
         <setting name="aggressiveLazyLoading" value="false"/> 
    </settings> 

就行啦。

④分页

咱在之前写j2ee项目的时候也实现过,通过参数start和count,设置sql语句

select * from   category_ limit start,count

就可以实现分页查询的功能。

那么mybatis里面也是这样。

xml方式:

在xml中把category的list方法改一下

改成:

<select id="listCategory" resultType="Category">
    select * from category_
    <if test="start!=null and count !=null">
        limit #{start} , #{count}
    </if>
</select>

然后在使用的时候用Map装一下参数params就行了。

注解方式:

这才是新学到的东西哈哈。

在CategoryMapper新加一个方法

@Select("select * from category_ limit #{start},#{count}")
public List<Category> listByPage(@Param("start") int start,@Param("count") int count);

用@param的方式传参,在使用的时候都不用map,直接传就行了。

⑤PAGEHELPER

在github上面的大佬写的 mybatis分页插件,分页的开发再也不用我们自己烦恼了。

在导入了包之后,

在mybatis-config.xml中加上一句:

<plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
             
        </plugin>
    </plugins>

表示开启pagehelper插件

然后就只需要在执行查询的语句之前 加上一句:

PageHelper.offsetPage(0, 5);

就可以了,再调用查询语句就只会显示前五个了,和上一步分页中的效果是一样的。

还有功能就是 获取总数:

PageInfo pageInfo = new PageInfo<>(cs);

哈哈字面意思,分页的信息都在里面了,里面有获取总数啥的方法。

⑥一级缓存

就是在同一个sqlsession当中, 两次相同的查询不会再次去调用sql语句,而是在一级缓存中有查询结果了。

* 一级缓存失效情况(没有使用到当前一级缓存的情况,效果就是,还需要再向数据库发出查询):

* 1、sqlSession不同。

* 2、sqlSession相同,查询条件不同.(当前一级缓存中还没有这个数据)

* 3、sqlSession相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响)

* 4、sqlSession相同,手动清除了一级缓存(缓存清空)

⑦二级缓存

相比一级缓存,二级缓存的范围要大点。在同一个SqlSessionFactory中,都不用重新调用sql了

在之前的 延迟加载的mybatis-config.xml中的settings中加上一句:

<setting name="cacheEnabled" value="true"/>

表示支持二级缓存

然后在Category.xml中增加 <cache/>,表示移动category对象的二级缓存

然后在pojo中的Category实现序列化接口

package com.how2java.pojo;
  
import java.io.Serializable;
import java.util.List;
  
public class Category implements Serializable{
    private int id;
    private String name;
    List<Product> products;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Product> getProducts() {
        return products;
    }
    public void setProducts(List<Product> products) {
        this.products = products;
    }
    @Override
    public String toString() {
        return "Category [id=" + id + ", name=" + name + "]";
    }
      
}

⑧单纯的MYBATIS整合C3P0数据库连接池

启动c3p0数据库连接池,在高并发的时候有性能优化。

需要的操作,导入jar包,然后新建一个C3P0DataSourceFactory类继承UnpooledDataSourceFactory,然后指定dataSource 为ComboPooledDataSource。
这个ComboPooledDataSource就是c3p0的数据源。

package org.mybatis.c3p0;
 
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
 
import com.mchange.v2.c3p0.ComboPooledDataSource;
 
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory{
     
        public C3P0DataSourceFactory(){
     
           this.dataSource =new ComboPooledDataSource();
     
        }
     
    }

然后在mybatis-config.xml中,把DataSource的type从POOLED改成type="org.mybatis.c3p0.C3P0DataSourceFactory"的数据源:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
      <package name="com.how2java.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>

<!--             <dataSource type="POOLED"> -->
<!--                 <property name="driver" value="com.mysql.jdbc.Driver"/> -->
<!--                 <property name="url" value="jdbc:mysql://localhost:3306/how2java?characterEncoding=UTF-8"/> -->
<!--                 <property name="username" value="root"/> -->
<!--                 <property name="password" value="admin"/> -->
<!--             </dataSource> -->
            
			<dataSource type="org.mybatis.c3p0.C3P0DataSourceFactory">
                  <property name="driverClass" value="com.mysql.jdbc.Driver" />     
                  <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/how2java?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true&amp;failOverReadOnly=false"/>    
                  <property name="user" value="root" />    
                  <property name="password" value="admin" />
                  <!-- 连接池初始化大小为3 -->
                  <property name="initialPoolSize" value="3"/>
                  <!-- 连接池最大为10 -->
                  <property name="maxPoolSize" value="10"/>
                  <!-- 连接池最小为3 -->
                  <property name="minPoolSize" value="3"/>
                  <!-- 连接池在无空闲连接可用时一次性最多创建的新数据库连接数  -->
                  <property name="acquireIncrement" value="5"/>
                  <!-- 连接的最大空闲时间,如果超过这个时间(秒),某个数据库连接还没有被使用,则会断开掉这个连接。如果为0,则永远不会断开连接,即回收此连接 -->
                  <property name="maxIdleTime" value="30"/>

                  <!-- 最大的Statement数量 -->
                  <property name="maxStatements" value="500"/>
                  <!-- 每个连接启动的最大Statement数量 -->
                  <property name="maxStatementsPerConnection" value="50"/>
                  <!-- 同时运行的线程数 -->
                  <property name="numHelperThreads" value="5"/>
           </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/how2java/pojo/Category.xml"/>
    </mappers>
</configuration>

c3p0就能顺利运行了,在高并发的情况下能体现其性能优势。

⑨逆向工程

之前学习都是先吧pojo、mapper、xml写好了,然后去创建对应的表结构,而逆向工程的方式,就是在我们数据库中创建好了表的前提下,逆向的帮我们把pojo、mapper、xml创建出来。

这样就很方便了,还不用自己去写CRUD那些sql语句,提高效率,减少出错。

配置过程:

先导入包,然后在src目录下面创建一个generatorConfig.xml文件,

这个文件要做的事情有:

1、设置数据库连接的账号密码

2、指定pojo、mapper、xml生成的包名

3、指定表名以及表名对应的类名

4、使用自增长键

<property name="my.isgen.usekeys" value="true"/>

<generatedKey column="id" sqlStatement="JDBC"/>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!--数据库驱动-->
    <!--
        如果IDE(eclipse或者idea) 项目里导入了jar包,那么就不需要配置了jar包的绝对路径了
         <classPathEntry    location="e:/project/mybatis/lib/mysql-connector-java-5.0.8-bin.jar"/>
    -->
    <context id="DB2Tables"    targetRuntime="MyBatis3">
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="false"/>
        </commentGenerator>
        <!--数据库链接地址账号密码-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost/how2java" userId="root" password="admin">
        </jdbcConnection>
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!--生成Model类存放位置-->
        <javaModelGenerator targetPackage="com.how2java.pojo" targetProject="src">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!--生成映射文件存放位置-->
        <sqlMapGenerator targetPackage="com.how2java.pojo" targetProject="src">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!--生成Dao类存放位置-->
         
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.how2java.mapper" targetProject="src">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!--生成对应表及类名-->
        <table tableName="category_" domainObjectName="Category" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>       
        </table>
<!--         <table tableName="product_" domainObjectName="Product" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> -->
    </context>
</generatorConfiguration>

然后运行:

package com.how2java;
 
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
 
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
 
public class TestMybatisGenerator {
 
    public static void main(String[] args) throws Exception {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        InputStream is= TestMybatisGenerator.class.getClassLoader().getResource("generatorConfig.xml").openStream();
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(is);
        is.close();
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
        System.out.println("生成代码成功,刷新项目,查看文件,然后执行TestMybatis.java");
         
    }
}

这样就生成好了对应东西啦,但是要注意的是:

1、

加载中

2、

mybatis-config.xml需要自己创建

3、

在查询的时候需要借助CategoryExample查询

比如执行一次模糊查询:

package com.how2java;
 
import java.io.InputStream;
import java.util.List;
 
//import com.how2java.mapper.CategoryMapper;
 
//import com.how2java.pojo.Category;
//import com.how2java.pojo.CategoryExample;
//import com.how2java.mapper.CategoryMapper;
//import com.how2java.pojo.CategoryExample;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 
import com.how2java.mapper.CategoryMapper;
import com.how2java.pojo.Category;
import com.how2java.pojo.CategoryExample;
 
public class TestMybatis {
    public static void main(String args[]) throws Exception {
        System.out.println("先运行TestMybatisGenerator创建mapper,pojo,xml 等文件,然后取消import里被注释的,以及接下来的注释,并执行代码");
 
//
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();
 
        CategoryExample example = new CategoryExample();
        example.createCriteria().andNameLike("%9%");
        CategoryMapper mapper = session.getMapper(CategoryMapper.class);
        List<Category> cs= mapper.selectByExample(example);
 
        for (Category c : cs) {
            System.out.println(c.getName());
        }
 
    }
}

mybatis的内容告一段落哈哈哈,明天整新知识啦。

学习网站:https://how2j.cn/p/5027

发布了82 篇原创文章 · 获赞 21 · 访问量 7931

猜你喜欢

转载自blog.csdn.net/qq_41658124/article/details/104994150