缓存

功能

提高查询效率,减少数据库压力。当缓存中有结果时将不再查询数据库。

用途

用于查询,适合查询较多的场合。

注意

insert、update、delete都会使缓存失效。或超时失效

一级缓存

作用

缓存是一个map

SqlSession会将statementIdparamsrowBounds作为key,结果为value。

执行查询时会先判断cache总是否有本次的key。存在且未超时,直接返回value;若不存在,则将本次key和value存入cache,并返回value

作用域

SqlSession(实际由Executor存储并管理),不能跨Session共享

生命周期

创建SqlSession对象时,会创建缓存Executor
调用clearCache或增删改时,会清空缓存
SqlSession关闭时,缓存Executor也关闭

失效

调用clearCache清空一级缓存

脏数据

多个session之间缓存可能不同,形成脏数据

可以设置一级缓存为statement级别,每次查询都将清除一级缓存

设置

MyBatis默认开启一级缓存,且无法关闭

使用

默认已经使用

二级缓存

作用

跨session共享缓存

查询语句执行流程为:二级缓存 ⇋ 一级缓存 ⇋ 数据库

作用域

namespace(实际由CachingExecutor装饰器维护,根据配置选用不同的Executor执行)

设置

全局总开关

settings中有cacheEnable属性,用于配置全局缓存是否开启,默认值为true

1
<setting name="cacheEnabled" value="true"/>

全局配置

MyBatis默认没有开启二级缓存,需要在mapper配置文件中添加cache配置或使用@CacheNamespace注解

https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache

配置该mapper缓存策略为FIFO,刷新时间为60秒,缓存元素为512个,只读

1
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

脏数据

当多表连接时MapperAB,缓存会保存在MapperAB,但通过MapperB更新单表的数据只会清空B的缓存,对MapperAB没有影响,这时,MapperAB将读取脏数据

解决方法

在MapperB内通过<cache-ref namespace="MapperA"/>使两个Mapper使用同一缓存(或使用@CacheNamespaceRef注解)

使用

查询后必须commit才会将结果加入二级缓存

session1查询后未提交,则二级缓存没有保存该结果,session2将查询数据库

缺点

  • 二级缓存没有一级缓存效率高
  • 多表操作时,二级缓存会产生脏数据