一、一级缓存
MyBatis的一级缓存是默认开启的,而且一级缓存无需设置即可使用。可能平时很少体验到一级缓存的功能,这是因为一级缓存会随着会话的关闭而失效。
当我们查询某条数据时,如果在这之前已经向数据库查询到了结果,那么MyBatis会将数据的缓存结果返回给我们,不会再去请求数据库,执行sql,这就是一级缓存。
一级缓存的特性:
1.一级缓存保存在sqlSession中,且只能作用于同一个sql,当sqlSession关闭时,一级缓存就会被清除
2.sqlSession相同,但是查询条件不同时,无法应用一级缓存
3.sqlSession相同,但是在查询期间执行了数据库增删改操作,一级缓存会失效
4.sqlSession相同,但是查询期间执行了清除缓存操作
一级缓存的特性决定了其应用范围非常的狭小,尤其是1、2、3特性。
二、二级缓存
二级缓存是全局缓存,它是相对于每一个namespace(命名空间)而言的,即每一个namespace(mapper)对应一个二级缓存。
二级缓存的数据来源于一级缓存,当我们关闭一个会话时,MyBatis会将一级缓存的数据提交到二级缓存,因此如果想要使用二级缓存,必须要会话关闭后才可以。
1.二级缓存的开启
全局设置:在全局配置文件里配置二级缓存,虽然二级缓存也是默认开启的,但是一般还是会显式设置一下,防止一些意外的原因(如版本更迭)产生问题。
<!-- 二级缓存设置,默认就是开启的 -->
<setting name="cacheEnabled" value="true"/>
在每一个mapper中设置开启二级缓存:
<cache eviction="LRU" flushInterval="60000" readOnly="false" size="1024"></cache>
2.二级缓存标签属性解释
eviction:
LRU:移除最长时间不被使用的对象,默认为LRU
FIFO:先进先出
SOFT:软引用:移除基于垃圾回收器状态和软引用规则的对象
WEAK: 弱引用:更积极的移除基于垃圾回收器状态和软引用规则的对象
flushInterval:缓存刷新时间,默认不清空,单位为毫秒
readOnly:缓存是否可读写
true:只读,MyBatis默认从缓存里获取的数据是只读的,不会修改,为了加快读取速度,将数据在缓存中的引用交给用户,所以不安全
false:非只读:MyBatis认为从缓存里获取的数据会被修改,所以会利用序列化与反序列化将数据克隆一份给用户,安全,但是速度慢
size:缓存存放个数;;
useCache: 作用于二级缓存,true使用,false不使用
flushCache:true清除缓存,false不清除
查询默认为false 增删改默认为true,这也是执行增删改后一级缓存失效的原因
3.注意:
1)实现二级缓存,pojo类必须实现序列化接口
2)useCache、flushCache都只作用与二级缓存,对于一级缓存没有任何影响,一般来说也不会去手动关 闭一级缓存
4.测试代码
@Test
public void testSecondLevelSession() throws IOException {
SqlSessionFactory sessionFactory = getSessionFactory();
SqlSession sqlSession1 = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
try {
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
User user1 = mapper1.selectUserById(1);
//一定要关闭会话,否则数据无法存在二级缓存
sqlSession1.close();
User user2 = mapper2.selectUserById(1);
sqlSession2.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
//sqlSession.close();
}
}