本章主要介绍Mybatis缓存相关内容,主要有缓存策略,一级缓存,二级缓存,以及缓存是否线程安全等
通过阅读Mybatis源码,发现在二级缓存上使用了以下几种装饰器:
FifoCache:先进先出缓存淘汰策略的缓存
LoggingCache:日志能力的缓存
ScheduledCache:定时清空的缓存
BlockingCache:阻塞式缓存
SerializedCache:序列号能力的缓存
SynchronizedCache:进行同步控制的缓存
从Mybatis源码中发现,Mybatis二级缓存使用HashMap来存储缓存的数据,那问题来了,二级缓存使用HashMap会有并发安全问题吗?
答案是 不会,因为使用了SynchronizedCache装饰器。
一级缓存,二级缓存对比图:
一级缓存 | 二级缓存 | |
默认开启 | 是 | 否,需手动 mapper.xml加上<cache></cache>即可 |
线程安全 | 是 | 是 |
实现类 | PerpetualCache | HashMap |
代码入口 | CachingExecutor.query | BaseExecutor.query |
那Mybatis缓存是如何存储的呢?
Mybatis中涉及到动态SQL的原因,缓存项的key不能仅仅通过一个String来表示,所以通过CacheKey来封装缓存的key值
CacheKey可以封装多个影响缓存项的因素
判断CacheKey是否相同关键是比较两个对象的hash值是否一致
构成CacheKey的对象:
1、mapperdStatement的id
2、指定查询结果集的范围(分页信息)
3、查询所使用的SQL语句
4、用户传递给SQL语句的实际参数值
注:Mybatis自带的分页强烈不建议使用,因为是将数据全部加载到内存进行分页,会占用大量内存空间,已经失去了分页的意义
CacheKey判断是否缓存过的计算四要素:
multiplier:参与hash计算的乘数
hashcode:CacheKey的hash值,在update函数中实时计算出来的
checksum:校验和,hash值的和
count:updateList中的元素个数