一级缓存
Mybatis在默认情况下,仅开启了一级缓存,即SqlSession级别的缓存,也称为本地缓存。
举个例子:
@Test
public void test01(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.queryUserById(1);
User user2 = mapper.queryUserById(1);
System.out.println("user1 = user2?"+(user1==user2)); //这里输出结果为true,说明user2直接是从缓存里拿的
sqlSession.close();
}
此时,user1 == user2 返回的结果是true (说明地址空间都一样,指向同一个对象)
缓存失效的情况:
- 根据不同参数查询不同的内容
- 当执行增、删、改操作时,缓存会刷新,使得原本的缓存内容发生变化,这是因为增删可能会改变原来的数据,缓存当然要发生变化。
- 查询不同的Mapper
- 清除缓存(sqlSession.clearCache())
二级缓存
二级缓存需要手动开启和配置,他是基于namespace级别的缓存(接口级别)
要启用二级缓存,只需要在SQL映射文件中添加如下代码:
<cache/>
这个语句的效果如下:
- 映射文件中所有select语句的结果将会被缓存
- 映射文件中所有insert , update , delete语句会刷新缓存
- 缓存会使用LRU(least recently use)算法来清除不需要的缓存
- 缓存不会定时进行刷新(也就是说没有刷新间隔)
- 缓存会保存列表或对象(无论查询方法返回哪种)的1024个引用
- 缓存会被视为读/写缓存,这意味着获取到的对象不是共享的,可以安全地被调用者修改,而不干扰其他调用者或者线程所做的潜在修改
这些缓存的属性也可以修改:
<cache
eviction = "FIFO"
flushInterval = "60000"
size = "512"
readOnly = "true"
/>
eviction表示清除策略(
FIFO : 先进先出,按照对象引入缓存的顺序来清除它们
LRU(默认):最近最少使用,移除最长时间不被使用的对象
SOFT: 软引用,基于垃圾回收器状态和软引用规则移除对象
WEAK:弱引用,更积极地基于垃圾回收器状态和弱引用规则移除对象
)
flushInterval表示刷新间隔时间(60s)
size表示最多可存储结果对象或列表引用的多少
readOnly表示返回的对象是只读的
但这还不行,还需要在mybatis-config.xml总配置文件中显示地开启全局缓存(其实默认是开启的):
<settings>
<setting name="chacheEnabled" value="true" />
</settings>
【注意】
- 二级缓存在一级缓存失效时才会生效
- 最好将使用缓存的pojo类序列化
- 缓存顺序:二级缓存 --> 一级缓存 --> 数据库