mybatis线程池、缓存与分页应用解析

内容导读

mybatis中线程池的应用

mybatis中缓存的应用

mybatis分页应用

一、mybatis中线程池的应用

线程池用于提高数据库操作的并发和性能。通过使用线程池,MyBatis 可以重用线程来执行多个查询或更新,而不是每次执行操作时都创建新的线程。

1、操作步骤

(1)创建基于SSM项目,导入mybatis、mysql及lombok依赖

(2)设置mybatis-config.xml核心配置,mysql.properties文件

(3)编写StudentMapper接口与StudentMapper.xml映射文件,别忘了在mybatis-config中登记StudentMapper.xml映射文件,否则会出现找到不类的情况。

2、案例解析

(1)创建MyTools

public class MyTools {
    //声明数据库操作的工厂对象
    private static SqlSessionFactory factory;
    //使用线程池来管理数据库操作对象SqlSession,它代替PreparedStatement对象功能
    private static ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();

    static {
        try {
            //拿到配置文件的字节流
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            //直接通过工厂构建对象生成工厂对象
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //通过线程池管理数据库操作对象
    public static SqlSession getSqlSession() {
        //从线程池拿已有的数据库操作对象
        SqlSession ss = local.get();
        //如果从线程池中取的对象为空则创建数据库操作对象
        if (ss == null) {
            //生成对象并设置数据库事务管理不自动提交
            ss = factory.openSession(false);
            //再放入线程池
            local.set(ss);
        }
        return ss;
    }
}

(2)MyTest测试类

public class MyTest {
    @Test
    public  void getCount(){//查询记录条数
        SqlSession ss = MyTools.getSqlSession();
        //生成数据库操作接口引用的对象
        StudentMapper sm = ss.getMapper(StudentMapper.class);
        //查询记录条数
        int n = sm.selectCount();
        System.out.println("条数:"+n);
    }
}

二、mybatis中缓存的应用

1、mybatis缓存简介

缓存用于单独管理的程序内存,能大大提高查询的性能。

mybatis有二级缓存:分别为一级缓存与二级缓存。

(1)一级缓存,mybatis自动打开的,是由SqlSession对象来管理

(2)二级缓存,mybatis没有自动打开,需要手动打开,是由SqlSessionFactory对象管理,针对大型项目建议打开,而且查询的实体类必须实现Serializable接口进行序列化,否则二级缓存也无效。

2、缓存手动打开步骤

在mybatis-config.xml中进行设置

<settings>
<!--打开二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>

StudentMapper.xml中设置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--映射文件对应的接口的完整路径,简称命名空间-->
<mapper namespace="com.mysoft.mapper.StuMapper">
  <!--此文件中使用二级缓存,之后的查询语句都用二级缓存-->
  <cache/>
  <select id="selectCount" resultType="int" useCache="true">
    select count(id)
    from stu;
  </select>
</mapper>  

3、单元测试,事务管理与二级缓存

public class MyTest {
    @Test
    public void getCount() {//查询记录条数
        SqlSession ss = MyTools.getSqlSession();
        //生成数据库操作接口引用的对象
        StudentMapper sm = ss.getMapper(StudentMapper.class);
        //查询记录条数
        int n = sm.selectCount();
        System.out.println("条数:" + n);
    }

    //查询所有学生记录,同时使用事务管理
    @Test
    public void selectStus() {
        SqlSession ss = null;
        try {
            //生成数据库操作对象
            ss = MyTools.getSqlSession();
            //生成数据库操作接口引用的对象
            StudentMapper sm = ss.getMapper(StudentMapper.class);
            System.out.println(sm.selectStudents());
            //(1)进行事务管理
            ss.commit();
        } catch (Exception e) {
            //(2)一旦出现异常,则将执行此处的代码,回滚恢复到初始状态
            System.err.println("回滚啦!");
            ss.rollback();
        }
    }
}

说明:当前流行在Spring boot中使用mybatis,因此,缓存的配置都在application.properties文件中进行设置。

三、mybatis分页插件

mybatis分页插件可以很方便让我们实现数据分页显示效果,提高开发效率。

3.1 pom.xml文件添加如下依赖

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>

    <artifactId>pagehelper</artifactId>

    <version>5.3.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser -->
<dependency>
    <groupId>com.github.jsqlparser</groupId>

    <artifactId>jsqlparser</artifactId>

    <version>4.0</version>

</dependency>

3.2 在Mybatis配置xml中配置拦截器插件

<plugins>
  <!-- com.github.pagehelper为PageHelper类所在包名 -->
  <plugin interceptor="com.github.pagehelper.PageHelper">
  <property name="dialect" value="mysql"/>
  <!-- 该参数默认为false -->
  <!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 -->
  <!-- 和startPage中的pageNum效果一样-->
  <property name="offsetAsPageNum" value="true"/>
   <!-- 该参数默认为false -->
   <!-- 设置为true时,使用RowBounds分页会进行count查询 -->
   <property name="rowBoundsWithCount" value="true"/>
  <!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 -->
  <!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)-->
   <property name="pageSizeZero" value="true"/>
   <!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 -->
   <!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
   <!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
    <property name="reasonable" value="true"/>
  </plugin>
</plugins>

五个参数说明:

(1)增加dialect属性,使用时必须指定该属性,可选值为oracle,mysql,mariadb,sqlite,hsqldb,postgresql,没有默认值,必须指定该属性

(2)增加offsetAsPageNum属性,默认值为false,使用默认值时不需要增加该配置,需要设为true时,需要配置该参数。当该参数设置为true时,使用RowBounds分页时,会将offset参数当成pageNum使用,可以用页码和页面大小两个参数进行分页。

(3)增加rowBoundsWithCount属性,默认值为false,使用默认值时不需要增加该配置,需要设为true时,需要配置该参数。当该参数设置为true时,使用RowBounds分页会进行count查询。

(4)增加pageSizeZero属性,默认值为false,使用默认值时不需要增加该配置,需要设为true时,需要配置该参数。当该参数设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是Page类型)。

(5)增加reasonable属性,默认值为false,使用默认值时不需要增加该配置,需要设为true时,需要配置该参数。具体作用请看上面配置文件中的注释内容。

3.3 Java代码中的应用

分页插件支持以下两种调用方式:

//第一种,RowBounds方式的调用
List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));

//第二种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.startPage(1, 10);
List<Country> list = countryMapper.selectIf(1);

在需要进行分页的Mybatis方法前,调用PageHelper.startPage静态方法即可,紧跟在这个方法后的第一个Mybatis查询方法会被进行分页。

1、分页应用一

SqlSession sqlSession = MybatisHelper.getSqlSession();
CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);
try {
    //获取第1页,10条内容,默认查询总数count
    PageHelper.startPage(1, 10);

    //紧跟着的第一个select方法会被分页
    List<Country> list = countryMapper.selectIf(1);
    assertEquals(2, list.get(0).getId());
    assertEquals(10, list.size());
    //分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>,
    //或者使用PageInfo类(下面的例子有介绍)
    assertEquals(182, ((Page) list).getTotal());
} finally {
    sqlSession.close();
}

2、分页应用二

SqlSession sqlSession = MybatisHelper.getSqlSession();
CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);
try {
    //获取第1页,10条内容,默认查询总数count
    PageHelper.startPage(1, 10);
    //紧跟着的第一个select方法会被分页
    List<Country> list = countryMapper.selectIf(1);
    //后面的不会被分页,除非再次调用PageHelper.startPage
    List<Country> list2 = countryMapper.selectIf(null);
    //list1
    assertEquals(2, list.get(0).getId());
    assertEquals(10, list.size());
    //分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>,
    //或者使用PageInfo类(下面的例子有介绍)
    assertEquals(182, ((Page) list).getTotal());
    //list2
    assertEquals(1, list2.get(0).getId());
    assertEquals(182, list2.size());
} finally {
    sqlSession.close();
}

3、分页应用三

//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);
List<Country> list = countryMapper.selectAll();
//用PageInfo对结果进行包装
PageInfo page = new PageInfo(list);
//测试PageInfo全部属性
//PageInfo包含了非常全面的分页属性
assertEquals(1, page.getPageNum());
assertEquals(10, page.getPageSize());
assertEquals(1, page.getStartRow());
assertEquals(10, page.getEndRow());
assertEquals(183, page.getTotal());
assertEquals(19, page.getPages());
assertEquals(1, page.getFirstPage());
assertEquals(8, page.getLastPage());
assertEquals(true, page.isFirstPage());
assertEquals(false, page.isLastPage());
assertEquals(false, page.isHasPreviousPage());
assertEquals(true, page.isHasNextPage());

提示:

(1)只有紧跟在PageHelper.startPage方法后的第一个Mybatis的查询方法会被分页

(2)分页插件不支持带有for update语句的分页

(3)分页插件不支持关联结果查询,可以用其它方式替代

(4)基于Spring boot框架的mybatis应用请关注其它分享

更多内容请关注本站!

  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值