一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情。
1、前言
MyBatis 内置了一个强大的事务性查询缓存机制,可以非常方便地配置和定制。默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:
<cache/>
在进行配置的时候还会分为一级缓存和二级缓存:
一级缓存:线程级别的缓存,是本地缓存,sqlSession级别的缓存
二级缓存:全局范围的缓存,不止局限于当前会话
2、 一级缓存的使用
一级缓存是sqlsession级别的缓存,默认是存在的。比如:我发送两个相同的查询请求,但是sql语句却只执行了一次,也就是说第一次查询的时候已经将结果进行了缓存。
@Test
public void test() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> list = mapper.selectUsers();//第一次查询
for (User user : list) {
System.out.println(user);
}
List<User> list2 = mapper.selectUsers();//第二次查询,从缓存中取数据
for (User user : list2) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
注:一级缓存可能会失效,比如下面几种情况
2.1 开启多个sqlsession
因为一级缓存是sqlSession级别的缓存,所以程序中只要开启了多个sqlsession
,一级缓存就会失效
@Test
public void test02(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> list = mapper.selectUsers();
for (User user : list) {
System.out.println(user);
}
System.out.println("================================");
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserDao mapper2 = sqlSession2.getMapper(UserDao.class);
List<Emp> list2 = mapper2.selectUsers();
for (User user : list2) {
System.out.println(user);
}
sqlSession.close();
sqlSession2.close();
}
2.2 手动清空缓存
两次查询的过程中,通过sqlSession.clearCache();
清空缓存,缓存就失效了。
2.3 参数原因
执行查询的SQL语句的过程中,如果参数不一致,也会造成缓存失效。
2.4 数据修改
执行第一次查询后,如果数据修改了,那么缓存也会失效。
3、二级缓存
二级缓存是全局作用域缓存,默认关闭,需要手动进行配置。
Mybatis提供二级缓存的接口以及实现,缓存实现的时候要求实体类实现Serializable
接口,二级缓存在sqlSession关闭或提交之后才会生效。
3.1 使用缓存
以下三个步骤,缺一不可。
3.1.1 开启二级缓存
在全局配置文件中,通过如下配置,开启二级缓存
<setting name="cacheEnabled" value="true"/>
3.1.2 添加<cache/>
标签
在需要使用二级缓存的映射文件增加 <cache/>
标签,如一级缓存一样。