一级缓存:
一级缓存在mybatis是默认开启的;
一级缓存的作用范围只在会话级别,即会话死亡,缓存也会跟着清空
缓存清空的时机:
执行添加,修改,删除,提交,关闭会话等操作会情况SQLSession张红的一级缓存数据;
注:当没有配置连接池的时候,同一个会话里面查询两次才会使用一级缓存,这样就显得比较鸡肋
但是当我们配置了线程池以后,连接池中有一定数量的常驻会话,这些会话是会循环使用不会关闭的
所以会有第一的几率命中一级缓存,在并发高的情况下,也能减轻很多负担
二级缓存:
二级缓存是默认关闭的
二级换在整个会话级别都是有效的(也就是所有的session/namespace共享的),只要会话工厂不死,二级缓存就在;
二级缓存的使用:
- 二级缓存在使用前要开启,需要在核心配置文件的settings标签下开启;
<settings>
<!--开启懒加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--开启缓存-->
<setting name="cacheEnabled" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
- 二级缓存缓存对象必须实现序列化接口:因为二级缓存他有可能会存到本地文件中
- 核心配置文件中配置了cacheEnable还是不行的,需要在使用缓存的mapper.xml中添加标签:
<cache/>
标签或者在mapperr接口中添加注解:
@CacheNamespace
二级缓存的底层原理:
二级缓存底层是使用map集合存储键值对,sql语句为键,查询的结果为值,缓存命中后直接通过键取值,所有他的效率非常高;
二级缓存清除时机:
执行增删改的时候会清除缓存
官方文档:
二级缓存是事务性的。这意味着,当 SqlSession 完成并提交时,或是完成并回滚,但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。
效果如下:
- 映射语句文件中的所有 select 语句的结果将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
- 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
- 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
- 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
注意:
在另外一namespace中修改了当前namespace的数据时,当前namespace不能识别,下次读取的时候会直接读取缓存,这样的就会读出脏数据,
但你可能会想要在多个命名空间中共享相同的缓存配置和实例。要实现这种需求,你可以使用 cache-ref 元素来引用另一个缓存。
<cache-ref namespace="com.someone.application.data.SomeMapper"/>
在没有关联查询的时候,数据会更新到二级缓存中,再次读取的时候直接命中缓存
但是当存在二级缓存时,会再次到数据库查询出最新的数据
配置了以后两者共享缓存。
来源:CSDN
作者:纸巾哥哥
链接:https://blog.csdn.net/zhijingege/article/details/103914827