MyBatis 缓存
MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。
一、缓存
1. 什么是缓存?
所谓缓存,就是存在内存中的临时数据。
将用户经常查询的数据放在缓存之中,当用户需要数据时,不再需要向数据库查询,而是可以直接从内存中获取。
2. 缓存的作用
- 减少了与数据库的交互次数
- 提高了查询效率
3. 适用于缓存的数据
经常查询且不经常改变的数据
二、MyBatis 缓存
MyBatis 内置了缓存机制,它可以方便地配置和定制。
在 MyBatis 中,默认定义了一级缓存和二级缓存,并且支持自定义二级缓存。
三、缓存的开启与关闭
1. 全局开关
MyBatis 默认开启了缓存,也可以通过配置文件显式地开启缓存:
打开 mybatis-config.xml
修改内容如下:
1
2
3<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
2. 语句开关
可以在 XxxMapper.xml 的语句标签中,使用 useCache 来配置单个语句是否使用缓存。
四、一级缓存
1. 说明
- 又称为本地缓存
- 默认情况下,一级缓存自动开启
- MyBatis 会将一次 SqlSession 中查询到的数据缓存在本地,如果需要再次获取相同的数据时,无需再去查询数据库,而是直接从缓存中获取即可
- 缓存仅在 SqlSession 中有效,无法被其它 SqlSession 获取,会随着 SqlSession 的关闭而销毁
2. 示例
(1) 一个 SqlSession 中
1 |
|
观察日志输出可以注意到:只向数据库查询了一次。
虽然调用了两次 getUserListById()
方法,但两次查询在同一个 SqlSession 中,并且获取的数据相同,因此直接从缓存中获取数据,不再向数据库查询。
(2) 不同 SqlSession 中
1 |
|
观察日志输出可以注意到:向数据库查询了两次。
虽然两次查询获取的数据是相同的,但由于两次查询处在不同的 SqlSession 中,因此一级缓存无法起作用,仍然需要从数据库获取数据。
五、二级缓存
1. 说明
- 又称为全局缓存
- 基于 namespace,一个命名空间对应一个二级缓存
- 缓存在 XxxMapper 中有效
2. 启用二级缓存
在 XxxMapper.xml 中,增加内容如下:
1 |
|
3. cache 标签的属性
eviction,清除策略,可选值有:
- LRU:默认,总是移除最长时长不被使用的对象
- FIFO:按先进先出原则移除对象
- SOFT:基于垃圾回收器状态和软引用规则移除对象
- WEAK:更积极地基于垃圾收集器状态和弱引用规则移除对象
flushInterval,刷新间隔
经过该时间以后,将会自动刷新缓存
默认情况下,flushInterval 的值为 0,不自动刷新,仅在调用语句时刷新
size,指定缓存的对象数量
默认为 1024
readonly:设置缓存是否只读
- 若设置为只读,获取时会返回缓存的对象实例,实例不能被修改,性能更好
- 若设置为可读写,获取时会返回缓存的对象的拷贝,实例可以被修改,性能更差,更安全
默认为可读写
type:填入全限定类名,用于自定义缓存
4. 示例
1 |
|
虽然两次查询是在不同的 SqlSession 中,但由于二级缓存的作用域是全局,因此第二次查询可以直接从缓冲中获取,而无需向数据库查询。
5. 多个 mapper 共享缓存
正常情况下,缓存仅在 XxxMapper 中有效,如果希望在多个 Mapper 中共享缓存,可以使用 cache-ref 标签。
1 |
|
七、自定义缓存
- 在 XxxMapper.xml 中使用 cache 标签开启二级缓存
- 使用 cache 标签的 type 属性指向缓存类(自己实现或导入第三方)