MyBatis中的缓存: 一级缓存和二级缓存

1: 一级缓存

//MyBatis的一级缓存,默认开启
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问。
//使一级缓存失效的四种情况:
  1) 不同的SqlSession对应不同的一级缓存。
  2) 同一个SqlSession但是查询条件不同。
  3) 同一个SqlSession两次查询期间执行了任何一次增删改操作,都会清空一级缓存,导致缓存失效。 
  4) 同一个SqlSession两次查询期间手动清空了缓存。调用了sqlSession.clearCache();
一级缓存是基于 PerpetualCache(MyBatis自带)的 HashMap 本地缓存,作用范围为 session 域内。当 session flush(刷新)或者 close(关闭)之后,该 session 中所有的 cache(缓存)就会被清空。
在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调用同一个 mapper 的方法,往往只执行一次 SQL。因为使用 SqlSession 第一次查询后,MyBatis 会将其放在缓存中,再次查询时,如果没有刷新,并且缓存没有超时的情况下,SqlSession 会取出当前缓存的数据,而不会再次发送 SQL 到数据库。
由于 SqlSession 是相互隔离的,所以如果你使用不同的 SqlSession 对象,即使调用相同的 Mapper、参数和方法,MyBatis 还是会再次发送 SQL 到数据库执行,返回结果。
/**
     * MyBatis缓存的测试
     *
     * @author 小宇宙
     * @date 2022/6/15 22:23:27
     */
@Test
public void cacheMapperTest() throws IOException {
  /*****************测试Mybatis的1级缓存*********************/
  SqlSession sqlSession = getSqlSession();
  CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);

  Student student1 = mapper.getStudentById(1);
  System.out.println(student1);
  Student student2 = mapper.getStudentById(1);
  System.out.println(student2);
}
[12:37:06.848] [DEBUG] [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [Created connection 1250442005.]
[12:37:06.852] [DEBUG] [main] [com.xyz.mybatis.mapper.CacheMapper.getStudentById] [==>  Preparing: select id, name, age, address, clazzId from demo1.student where id = ?]
[12:37:06.875] [DEBUG] [main] [com.xyz.mybatis.mapper.CacheMapper.getStudentById] [==> Parameters: 1(Integer)]
[12:37:06.898] [DEBUG] [main] [com.xyz.mybatis.mapper.CacheMapper.getStudentById] [<==      Total: 1]
Student{id=1, name='唐子尘', age=24, address='中国', clazzId=1, clazz=null}
[12:37:06.898] [DEBUG] [main] [com.xyz.mybatis.mapper.CacheMapper] [Cache Hit Ratio [com.xyz.mybatis.mapper.CacheMapper]: 0.0]
Student{id=1, name='唐子尘', age=24, address='中国', clazzId=1, clazz=null}

2: 二级缓存

//MyBatis的二级缓存, 需要手动开启
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被
缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
//二级缓存开启的条件: 
	a>在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置 
  b>在映射文件中设置标签<cache />
	c>二级缓存必须在SqlSession关闭或提交之后有效 
  d>查询的数据所转换的实体类类型必须实现序列化的接口 
//使二级缓存失效的情况: 
	两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
//缓存命中率:
  Cache Hit Ratio [com.xyz.mybatis.mapper.CacheMapper]: 0.0
//二级缓存的相关配置
  在mapper配置文件中添加的cache标签可以设置一些属性:
  1:eviction属性:缓存回收策略
      LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。
      FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。
      SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
      WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
      默认的是 LRU。
  2:flushInterval属性:
    刷新间隔,单位毫秒
    默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句(增删改语句)时刷新
  3: size属性:
    引用数目,正整数
    代表缓存最多可以存储多少个对象,太大容易导致内存溢出
  4: readOnly属性:
    只读,true/false
    true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了 很重要的性能优势。
    false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。

3: MyBatis缓存查询的顺序

先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。 
如果二级缓存没有命中,再查询一级缓存
如果一级缓存也没有命中,则查询数据库 
SqlSession关闭之后,一级缓存中的数据会写入二级缓存

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值