学习MyBatis一级缓存概念、使用、存在问题及解决方法从而确定该不该用Mybatis一级缓存和二级缓存。
一级缓存
概念
- 一次数据库会话中,执行多次查询条件完全相同的SQL,MyBatis通过一级缓存的方案优化这部分场景。
- SqlSession级别的缓存。
使用
Mybatis配置文件中配置缓存设置,开启一级缓存
- cacheEnabled=true
- localCacheScope=SESSION
原理
- 在一个
SqlSession
中,查询相同条件的查询,会查缓存 - 缓存失效:同一个session中对相同的记录进行修改操作时,该记录的缓存会失效
- 只在
SqlSession
内部共享 - 一个没有容量限定的HashMap
存在问题
- 默认的SESSION的缓存,对于不同
SqlSession
中,可能读到脏数据。 - 分布式环境下失效
如何解决存在问题
- 非分布式部署环境下,设置localCacheScope为STATEMENT
- 未提供自定义实现,无法缓存到redis等缓存中
二级缓存
概念
- namespace缓存
- 相同namespace下所有操作语句,都影响着同一个Cache
- 多个SqlSession共享
特点
- 实现了SqlSession之间的数据共享
- 粒度更细,能够到namespace级别
使用
Mybatis配置文件中配置缓存设置,开启而级缓存
- cacheEnabled=true
在mapper文件中添加cache相关标签
cache
属性
- type:cache使用类型,默认值:PerpetualCache,可以自定义实现
- eviction:回收策略,取值LRU、FIFO、SOFT、WEAK,默认值为:LRU
- size:最多缓存对象的个数
- readOnly:是否只读,若配置可读写,则需要对应的实体类能够序列化。
- blocking:若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。
cache-ref
代表引用别的命名空间的Cache配置,两个命名空间的操作使用的是同一个Cache。
属性
namespace
存在问题
- 多表查询时,对于不同namespace,维护的缓存可能不一致,会出现脏读
- 基于本地的,分布式环境无效
如何解决存在问题
- 多表查询时脏读的解决方法:多表放在同一个namespace下
- 分布式环境解决方法:使用redis实现自定义的缓存类型
一级缓存、二级缓存执行流程
优先查询二级缓存,其次查询一级缓存,最后查询数据库
用不用Mybatis缓存
一级缓存和二级缓存都存在相关问题,如果能够解决相关问题的话可以使用,只是需要人为去改造,不通用