Mybatis缓存
一、一级缓存
1. 概念
- sqlsession级别的缓存,即缓存的是SQL语句
- 同一个sqlsession中执行多次查询条件相同的SQL,mybatis会提供一级缓存进行优化
2. 开启和关闭
-
开启
- 默认开启
-
关闭
<setting name="localCacheScope" value="STATEMENT"/>
3. 使用
@Test
public void method() throws IOException {
// 1.读取核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 2.获取sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
// 3.获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.获取mapper
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
// 5.调用相应的方法
Student student = mapper.getStudentById(1);
System.out.println(student);
System.out.println("----------------------------");
// 同一个sqlsession中执行相同的SQL查询,会走一级缓存
Student student1 = mapper.getStudentById(1);
System.out.println(student1);
// 6.释放资源
sqlSession.close();
in.close();
}
4. 什么时候失效
- 通过同一个SqlSession执行更新操作时,这个更新操作不仅仅指代update操作,还指插入和删除操作;
- 事务提交时会删除一级缓存;
- 事务回滚时也会删除一级缓存
5. 使用建议
平时使用MyBatis时都是和Spring结合使用的,在整个Spring容器中一般只有一个SqlSession实现类(bean默认是单例的)。而Spring一般都是主动提交事务的,所以说一级缓存经常失效。
还有就是我们也很少在一个事务范围内执行同一个SQL两遍,上面的这些原因导致我们在开发过程中很少注意到MyBatis一级缓存的存在。
不怎么用并不是说不用,作为一个合格的开发者需要对这些心知肚明,要清楚的知道MyBatis一级缓存的工作流程。
二、二级缓存
1. 概念
- mapper级别的缓存
2. 开启
-
核心配置文件:mybtis-config.xml
<setting name="cacheEnabled" value="true"/>
-
mapper
@CacheNamespace(blocking = true)
3. 使用
/**
* 二级缓存:
* 1.同一个sqlsession中,相同的SQL查询,会走缓存
* 2.中途执行了更新,则下次的SQL查询不走缓存
* 3.前面的sqlsession关闭之后,后面的sqlsession如果执行的是相同的SQL,则会走缓存
*
* @throws IOException
*/
@Test
public void method2() throws IOException {
// 1.读取核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 2.获取sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
// 3.获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.获取mapper
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
// 5.调用相应的方法
Student student = mapper.getStudentById(1);
System.out.println(student);
System.out.println("----------------------------");
// 执行更新操作:查看下面的查询是否还会走缓存
// int num = mapper.updateById(1);
// System.out.println(" num = "+num);
//
// System.out.println("----------------------------");
sqlSession.close();
// 同一个sqlsession中执行相同的SQL查询,会走一级缓存
SqlSession sqlSession1 = sqlSessionFactory.openSession();
// 4.获取mapper
StudentMapper mapper1 = sqlSession1.getMapper(StudentMapper.class);
Student student1 = mapper1.getStudentById(1);
System.out.println(student1);
// 6.释放资源
sqlSession1.close();
// sqlSession.close();
in.close();
}
4. 什么时候失效
- 二级缓存是以namespace(Mapper)为单位的,不同namespace下的操作互不影响。
- insert,update,delete操作会清空所在namespace下的全部缓存。
- 多表操作一定不要使用二级缓存,因为多表操作进行更新操作,一定会产生脏数据。
5. 使用建议
MyBatis的二级缓存实用性不是很大。一个原因就是Spring环境下,一本只有一个SqlSession,不存在sqlSession之间共享缓存;还有就是
MyBatis的缓存都不能做到分布式,所以对于MyBatis的二级缓存以了解为主。
总结
1. 一级缓存
一级缓存的本质是Executor的一个类似Map的属性;
一级缓存默认开启,将flushCache设置成true或者将全局配置localCacheScope设置成Statement可以关闭一级缓存;
在一级缓存开启的情况下,查询操作会先查询一级缓存,再查询数据库;
增删改操作和事务提交回滚操作会导致一级缓存失效;
由于Spring中事务是自动提交的,因此Spring下的MyBatis一级缓存经常失效。(但是并不表示不生效,除非你手动关闭一级缓存)
不能实现分布式。
2. 二级缓存
namesapce级别的缓存(Mapper级别或者叫做表级别的缓存),设计的主要目的是实现sqlSession之间的缓存共享;
开启二级缓存后,查询的逻辑是二级缓存->一级缓存->数据库;
insert,update,delete操作会清空所在namespace下的全部缓存;
多表查询一定不要使用二级缓存,因为多表操作进行更新操作,可能会产生脏数据。
总体来说,MyBatis的缓存功能比较鸡肋。想要使用缓存的话还是建议使用spring-cache等框架。