MyBatis缓存机制
MyBatis 提供了一级缓存和二级缓存的支持。
一级缓存
一级缓存是基于PerpetualCache 的 HashMap本地缓存;
一级缓存的作用域是SqlSession,即不同的SqlSession使用不同的缓存空间;
一级缓存的开启和关闭
- 一级缓存是默认开启的;
- 关闭一级缓存只需要在settings中设置localCacheScope为STATEMENT
导致一级缓存不命中的原因
-
一级缓存关闭;
-
一级缓存开启,但是使用了不同的SqlSession进行查询;
-
使用相同的SqlSession,但是查询条件发生了变化;
-
使用了相同的查询条件,但是两次查询之间SqlSession执行了commit、clearCache或close(关闭之后查询会报错)操作;
- 使用了相同的查询条件,但是两次查询之间SqlSession执行了insert、update或delete操作,此时无论三种标签的 flushCache 属性是否为 false,都会清空 sqlSession的缓存;
-
select标签的flushCache属性为true
清空一级缓存的操作
-
SqlSession调用commit方法;
-
SqlSession调用clearCache方法;
-
select标签的flushCache属性为true;
-
SqlSession执行了insert、update或delete操作,此时无论三种标签的 flushCache 属性是否为 false;
二级缓存
二级缓存默认也是采用 PerpetualCache,HashMap存储;
二级缓存的存储作用域为 Mapper(确切说是Namespace),即一个Mapper执行了insert、update或delete操作,不影响另外一个Mapper(不同namespace);
二级缓存可自定义存储实现,如 Ehcache、redis;
二级缓存开启后,需要对应的java Bean实现
二级缓存的开启和关闭
- settings中可设置 cachaEnable为true或false,该属性是二级缓存的总开关,如果关闭,则所有mapper的二级缓存均不生效;
- 在cachaEnable为true的情况下,在mapper文件中添加<cache/>标签即可开启二级缓存,如果没有该标签,则二级缓存不生效;
二级缓存不命中的情况
-
二级缓存未开启;
-
第一次查询之后,SqlSession未执行commit或close操作,导致该查询的二级缓存还未生效;
-
两次查询之间,mapper(同一命名空间)执行了insert、update或delete操作;
-
insert、update或delete标签的flushCache属性默认为true,此时会清除一级缓存和二级缓存;
-
insert、update或delete标签的flushCache属性为false时,不会清除二级缓存,依然清空一级缓存;
-
- select标签的flushCache属性(默认false)的值为true;
cache标签属性
-
eviction:缓存回收策略:flushInterval:缓存多长时间清空一次,默认不清空,单位毫秒 ms
- LRU——最少使用的,移除最长时间不适用的对象;
- FIFO——先进先出
- WEAK——弱引用,更积极的移除基于垃圾回收器状态和弱引用规则的对象
- SOFT——软引用,更积极的移除基于垃圾回收器状态和弱引用规则的对象
- flushInterval:缓存多久清空一次,默认不清空,时间毫秒 ms
-
readOnly:缓存是否只读
-
size:缓存觉存放元素个数,默认1024
-
type:自定义缓存的全类名