笔记:mybatis的一二级缓存

11 篇文章 0 订阅

mybatis一级缓存默认开启

一级缓存只是相对于同一个SqlSession而言。所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL。

1.例如:

    @Test
    public void testUnit() {
        System.out.println(employeeMapper.selectById(7369));
        System.out.println(employeeMapper.selectById(7369).getDepartment());
        System.out.println("------------------------------------------");
        System.out.println(employeeMapper.selectById(7369));
        System.out.println(employeeMapper.selectById(7369).getDepartment());
    }

2.结果:

2020-03-29 19:26:02,228 [main] DEBUG [lz.cn.mapper.EmployeeMapper.selectById] - ==>  Preparing: select e.EMPNO, e.ENAME, e.JOB, e.MGR, e.HIREDATE, e.SAL, e.COMM, e.DEPTNO, d.DEPTNO D_DEPTNO, d.DNAME D_DNAME, d.LOC D_LOC from EMPLOYEE E,DEPARTMENT D where E.DEPTNO = D.DEPTNO and E.EMPNO=? 
2020-03-29 19:26:02,571 [main] DEBUG [lz.cn.mapper.EmployeeMapper.selectById] - ==> Parameters: 7369(Integer)
2020-03-29 19:26:02,712 [main] DEBUG [lz.cn.mapper.EmployeeMapper.selectById] - <==      Total: 1
Employee{empno=7369, ename='FIRST', job='JAVA', mgr=7369, hiredate=Fri Sep 27 18:17:07 CST 2019, sal=4000.0, comm=100.0, deptno=10}
部门{deptno=10, dname='ACCOUNTING', loction='null'}
------------------------------------------
Employee{empno=7369, ename='FIRST', job='JAVA', mgr=7369, hiredate=Fri Sep 27 18:17:07 CST 2019, sal=4000.0, comm=100.0, deptno=10}
部门{deptno=10, dname='ACCOUNTING', loction='null'}

如结果所示,sql语句只输出了一次,同一个sqlSession中只执行了一次查询。

3.一级缓存的生命周期

  • 创建一个新的SqlSession对象后,SqlSession对象中会有一个新的Executor对象。Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。
  • 如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用。
  • SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用
  • SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用

二级缓存开启步骤:

MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能。

二级缓存是在SqlSessionFactory层面上的,默认是不开启的,二级缓存的开席需要进行配置,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。 也就是要求实现Serializable接口。

配置方法

要求实现Serializable接口。

1.在mybatis的配置文件中添加

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

2.在mapper中添加:

    <!--二级缓存开启-->
    <cache eviction="LRU"
           flushInterval="60000"
           size="1024"
           readOnly="true"/>

cache 标签有多个属性:

  • eviction:缓存回收策略
    • LRU - 最近最少回收,移除最长时间不被使用的对象
    • FIFO - 先进先出,按照缓存进入的顺序来移除它们
    • SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象
    • WEAK - 弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象
  • flushInterval:缓存刷新间隔,缓存多长时间刷新一次,默认不清空,设置一个毫秒值
  • readOnly:是否只读;true 只读,MyBatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改MyBatis 为了加快获取数据,直接就会将数据在缓存中的引用交给用户。不安全,速度快。读写(默认):MyBatis 觉得数据可能会被修改
  • size:缓存存放多少个元素

3.test测试

		SqlSessionFactory sqlSessionFactory = null;

		/*第一个sqlSession*/
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmployeeMapper employeeMapper1 = sqlSession.getMapper(EmployeeMapper.class);
        System.out.println(employeeMapper1.selectById(8133));
        sqlSession.close();

        /*第二个sqlSession*/
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        EmployeeMapper employeeMapper2 = sqlSession2.getMapper(EmployeeMapper.class);
        System.out.println(employeeMapper2.selectById(8133));
        sqlSession2.close();

        /*第三个sqlSession*/
        SqlSession sqlSession3 = sqlSessionFactory.openSession();
        EmployeeMapper employeeMapper3 = sqlSession3.getMapper(EmployeeMapper.class);
        System.out.println(employeeMapper3.selectById(8133));
        sqlSession3.close();

此处同一个sqlSessionFactory开启三个sqlSession,查询同一个员工。

4.结果显示:

2020-03-29 18:45:34,558 [main] DEBUG [com.yw.mapper.EmployeeMapper] - Cache Hit Ratio [com.yw.mapper.EmployeeMapper]: 0.0
2020-03-29 18:45:36,167 [main] DEBUG [com.yw.mapper.EmployeeMapper.selectById] - ==>  Preparing: select * from EMPLOYEE where EMPNO=? 
2020-03-29 18:45:36,355 [main] DEBUG [com.yw.mapper.EmployeeMapper.selectById] - ==> Parameters: 8133(Integer)
2020-03-29 18:45:36,464 [main] DEBUG [com.yw.mapper.EmployeeMapper.selectById] - <==      Total: 1
Employee{empno=8133, ename='employee', job='employee', mgr=7369, hiredate=Tue Oct 15 16:07:09 CST 2019, sal=500.0, comm=200.0, deptno=20}
2020-03-29 18:45:36,480 [main] DEBUG [com.yw.mapper.EmployeeMapper] - Cache Hit Ratio [com.yw.mapper.EmployeeMapper]: 0.5
Employee{empno=8133, ename='employee', job='employee', mgr=7369, hiredate=Tue Oct 15 16:07:09 CST 2019, sal=500.0, comm=200.0, deptno=20}
2020-03-29 18:45:36,480 [main] DEBUG [com.yw.mapper.EmployeeMapper] - Cache Hit Ratio [com.yw.mapper.EmployeeMapper]: 0.6666666666666666
Employee{empno=8133, ename='employee', job='employee', mgr=7369, hiredate=Tue Oct 15 16:07:09 CST 2019, sal=500.0, comm=200.0, deptno=20}
2020-03-29 18:45:36,480 [main] DEBUG [com.yw.mapper.EmployeeMapper] - Cache Hit Ratio [com.yw.mapper.EmployeeMapper]: 0.75
Employee{empno=8133, ename='employee', job='employee', mgr=7369, hiredate=Tue Oct 15 16:07:09 CST 2019, sal=500.0, comm=200.0, deptno=20}

控制台结果打印:

第一次没有缓存,命中率0.0,需要查询,有sql语句;

第二次有缓存,命中率0.5,直接从缓存中取得数据,无查询,无sql语句;(共两次命中1次)

第三次有缓存,命中率0.666,直接从缓存中取得数据,无查询,无sql语句;(共三次命中2次)

第四次有缓存,命中率0.75,直接从缓存中取得数据,无查询,无sql语句;(共四次命中3次)

5.效果

  • 所有select语句将会被缓存。
  • insert、update和delete语句会刷新缓存
  • 默认的Least Recently Used(LRU,最近最少使用的)算法来收回
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值