SpringBoot下mybatis-一级、二级缓存测试及总结
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、默认开启一级缓存。一级缓存是 SqlSession 级别的。
具体什么意思测试一下。
一次事务中,同一语句调用两次,代码:
VarDateEntity varDateEntity = dateMapper.getVarDate();
System.out.println("var1 var:"+varDateEntity.getVarTime());
System.out.println("var1 not:"+varDateEntity.getNotTime());
System.out.println("var1 null:"+varDateEntity.getNullTime());
varDateEntity = dateMapper.getVarDate();
System.out.println("var2 var:"+varDateEntity.getVarTime());
System.out.println("var2 not:"+varDateEntity.getNotTime());
System.out.println("var2 null:"+varDateEntity.getNullTime());
Postman 中执行两次:
测试结果:
结论1:
同一事务中的两次查询,只查询了一次。但是两次事务中,每次均进行了一次查询;
一级缓存的 scope 默认值session;
设置为:statment 。重启 springboot 应用再次测试:
结论2:
设置mybatis.configuration.local-cache-scope=statement后,即使 xmxxxxl 语句中配置useCache="true",一级缓存均失效。
总结:
•Mybatis一级缓存的生命周期和SqlSession一致。
•Mybatis的缓存是一个粗粒度的缓存,没有更新缓存和缓存过期的概念,同时只是使用了默认的hashmap,也没有做容量上的限定。
•Mybatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,有操作数据库写的话,会引起脏数据,建议是把一级缓存的默认级别设定为
Statement,即不使用一级缓存。
二、开启二级缓存,需要进行设置。
#一级缓存状态:关闭 #
mybatis.configuration.local-cache-scope=statement
#二级缓存状态:开启 #
mybatis.configuration.cache-enabled=true
mapper定义中添加标签
cache 用来声明使用二级缓存,可以自定义属性:
•type: cache使用的类型,默认是PerpetualCache,这在一级缓存中提到过。
•eviction: 定义回收的策略,常见的有FIFO,默认LRU
•flushInterval: 配置一定时间自动刷新缓存,单位是毫秒
•size: 最多缓存对象的个数
•readOnly: 是否只读,若配置可读写,则需要对应的实体类能够序列化。
•blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。
cache-ref代表引用别的命名空间配置,使用同一个 Cache。
测试
Caused by: java.io.NotSerializableException: com.sitech.acctmgr.pub.entity.VarDateEntity
没有序列化?将VarDateEntity序列化。
public class VarDateEntity implements Serializable {
重启应用,Postman第一次SqlSession 事务调用中,两次相同的查询:
两次均调用 sql查询了数据库。
原因:同一个 SqlSession 中,在执行完毕后进行提交commit()才会进入缓存。
Postman第二次事务执行,调用相同的 sql:
使用了缓存。命中率:Cache Hit Ratio : 0.3333333333333333,为何是0.3,因为总共查询了3次,本次使用了缓存。
再次查询,命中率就会变为0.5:
总结:
二级缓存不同于一级缓存,需要使接受数据的 POJO类序列化;
同一事务中的查询信息,在事务提交之后,才会把查询数据提交缓存。
返回的缓存数据是实际缓存实例,不是拷贝,所以存在被修改的情况!!!
频繁更新的操作不建议使用。手动修改数据库表中的查询数据会出现脏读!!!
二级缓存对细粒度的数据级别的缓存实现不好,不能够单独刷新某条数据!!!方案?EhcacheCache。
以上是在 SpringBoot 中,对Mybatis的缓存的查询类测试。
关于更新类的测试结果总结:
update操作是否会刷新该namespace下的二级缓存;
Mybatis的二级缓存不适应用于映射文件中存在多表查询的情况。如何解决?使用cache-ref 引入其他关联表所载 namespace。
单应用方案:
二级缓存?业务第一次的时候做的缓存。
单独做缓存?应用启动的时候静态加载配置。业务无感知。
分布式方案:
分布式缓存redis?
使用内存数据库?
mybatis源码分析可以查看下附帖子,在很多搜索结果里面,是比较全面的。