7 Mybatis的缓存

缓存就相当于一个临时储存的数据,比如浏览器缓存,你访问了一个页面,会向服务器请求资源,那么你退出页面再进来,页面资源可以在本地缓存获取

缓存可以减少直接对数据库操作,提高数据库性能

Mybatis一级缓存

  • Mybatis一级缓存
    • Mybatis一级缓存时默认开启的,一级缓存是Sqlsession级别的,通过同一个Sqlsession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.selectEmpById(6);
        Emp emp1 = mapper.selectEmpById(6);
        System.out.println(emp);
        System.out.println(emp1);

DEBUG 11-07 20:00:19,623 ==>  Preparing: select * from t_emp where emp_id = ? (BaseJdbcLogger.java:135) 
DEBUG 11-07 20:00:19,647 ==> Parameters: 6(Integer) (BaseJdbcLogger.java:135) 
DEBUG 11-07 20:00:19,667 <==      Total: 1 (BaseJdbcLogger.java:135) 
Emp{empId=6, empName='小红', age=21, gender='女', dept=null}
Emp{empId=6, empName='小红', age=21, gender='女', dept=null}
		

虽然我查询了两次id为6的emp,但是sql语句只执行了一次,所一验证了mybatis的一级缓存,一级缓存是Sqlsession级别,如果你开了一个新的sqlsession,那是获取不到前一个sqlsession的缓存的

  • Mybatis一级缓存失效的四种情况
    • 不同的sqlsession对应不同的缓存
    • 同一个sqlsession但是查询的条件不同
    • 同一个sqlsession两次查询期间执行了任何一次增删改操作
      • 就是有影响了缓存的数据,数据库更新
    • 同一个sqlsession两次查询期间手动清空了缓存
      • 使用sqlsession.clearCache() 方法清空缓存

Mybatis二级缓存

Mybatis二级缓存是SqlsessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若在此执行相同的查询语句,结果就会从缓存中获取

  • 二级缓存开启条件
    • 在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为ture,不需要设置,但是你要知道有这个东西
    • 在映射文件中设置标签<cache/>
    • 二级缓存必须在Sqlsession关闭或提交或有效
      • SqlSession一级缓存,只有SqlSession关闭后才会将一级缓存提交到二级缓存,sqlsession.close()
    • 查询的数据转换的实体类类型必须实现序列化接口implements Serializable
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
        SqlSession sqlSession1 = build.openSession(true);
        SqlSession sqlSession2 = build.openSession(true);
        EmpMapper mapper = sqlSession1.getMapper(EmpMapper.class);
        Emp emp = mapper.selectEmpById(6);
        System.out.println(emp);
        sqlSession1.close();
        EmpMapper mapper1 = sqlSession2.getMapper(EmpMapper.class);
        Emp emp1 = mapper1.selectEmpById(6);
        System.out.println(emp1);
DEBUG 11-07 20:35:57,451 Cache Hit Ratio [com.cn.zt.mybatis.mappers.EmpMapper]: 0.0 (LoggingCache.java:60) 
DEBUG 11-07 20:35:57,693 ==>  Preparing: select * from t_emp where emp_id = ? (BaseJdbcLogger.java:135) 
DEBUG 11-07 20:35:57,716 ==> Parameters: 6(Integer) (BaseJdbcLogger.java:135) 
DEBUG 11-07 20:35:57,736 <==      Total: 1 (BaseJdbcLogger.java:135) 
Emp{empId=6, empName='小红', age=21, gender='女', dept=null}
WARN  11-07 20:35:57,748 As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66 (SerialFilterChecker.java:45) 
DEBUG 11-07 20:35:57,750 Cache Hit Ratio [com.cn.zt.mybatis.mappers.EmpMapper]: 0.5 (LoggingCache.java:60) 
Emp{empId=6, empName='小红', age=21, gender='女', dept=null} 

可以看到二级缓存生效了,只查询了一次,而且还显示了Cache Hit Ratio 缓存命中率

  • 二级缓存的相关配置
  • 在mapper配置文件中添加的cache标签可以设置一些属性
    • eviction属性:缓存回收策略,默认的是LRU
      • LRU (Least Recently Used) 最近最少使用的:移除最长时间不被使用的对象
      • FIFO(First in First out) 先进先出: 按对象进入缓存的顺序来移除它们
      • SOFT 软引用:移除基于垃圾回收器状态和软引用规则的对象
      • WEAK 弱引用 : 更积极移除基于垃圾收集器状态和弱引用规则的对象
    • flushInterval属性:刷新间隔,单位毫秒
      • 默认情况下不设置,没有刷新间隔,缓存仅仅调用语句时刷新(比如执行了相关的增删改操作)
    • size属性:引用数目,正整数
      • 代表缓存最多可以存储多少个对象,一般用默认
    • readOnly属性:只读,true/false
      • true:只读缓存,会给所有调用者返回缓存对象的相同实例,这写对象不能修改,因为你修改了,就改了缓存中的对象,那么这个对象就会和数据库中的数据不一致,所以不能修改,它性能高一些
      • false:读写缓存:会返回缓存对象的拷贝,这样会慢一些,但是你修改这个对象不影响缓存中的对象,安全

Mybatis缓存查询顺序

  • 先查询二级缓存,因为二级缓存范围大,它是sqlsessionFactory级别,可能会有其他程序已经查出来的数据,可以直接使用
  • 如果二级缓存没有命中,再查一级缓存
    • 这里说明一下,二级缓存中没有的不代表一级缓存没有,因为一级缓存是在sqlsession关闭后才将缓存放入二级缓存
  • 如果一级缓存也没命中,则查询数据库
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值