前言
Mybatis中的一级缓存和二级缓存在使用中是非常频繁的,但是一般使用时都不太关注底层原理,导致在面试或者工作中遇到一些问题不知道怎么解决。
1、一级缓存
先讲概念,什么是一级缓存,缓存的等级是根据靠近数据库底层的距离来划分的,比如一级缓存就是距离数据库最近的,二级缓存相对一级缓存要更远一些,因此,查询的时候是先查询二级,再查询一级。缓存层级如图:
一级缓存实现类所在的位置是org.apache.ibatis.executor.BaseExecutor#query()
这里便是从一级缓存查询数据,如果查询不到则继续从数据库查询,这里一个很重要的内容就是cacheKey,cacheKey包含的内容如下:
1、当前statement的id编号
2、BoundSql的offset偏移量
3、BoundSql的条数
4、Sql语句
5、sql中所有参数的名称和值
一级缓存的数据是什么时候放进去的?
当然是查询的时候了,源码如下:
2、二级缓存
二级缓存相对于一级缓存是一个更外层的缓存装置,他可以选择和第三方容器结合,也可以单独存在。二级缓存的查询是在org.apache.ibatis.executor.CachingExecutor#query()中实现的。
配置开启二级缓存:
<settings>
<!-- 打印sql日志 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
Mapper文件中添加二级缓存标识
实体对象一定要实现Serializable
二级缓存的使用:
public class Demo2 {
/**
* @author Chengzhi
* @date 2023-05-09
* @测试目的:测试mybatis的二级缓存
* @预期结果:
*/
@Test
public void test() throws IOException {
// 1、获取配置文件
InputStream inputStream = Resources.getResourceAsStream("com/cz/resource/mybatis-config.xml");
// 2、构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3、开启会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4、操作Mapper接口
// 6、流式查询 二、
TestCaseMapper mapper = sqlSession.getMapper(TestCaseMapper.class);
TestCase testCase = mapper.selectByPrimaryKey(1);
System.out.println(testCase.getRequest());
// 关闭一级缓存
sqlSession.close();
System.out.println("========================================================");
// 测试二级缓存
SqlSession sqlSession2 = sqlSessionFactory.openSession();
TestCaseMapper mapper2 = sqlSession2.getMapper(TestCaseMapper.class);
TestCase testCase2 = mapper2.selectByPrimaryKey(1);
System.out.println(testCase2.getRequest());
}
}
测试结果:
从图中可以看到二级缓存已经生效了。那么二级缓存的数据是什么时候塞入的呢?根据源码可以看出是查询出来的时候就已经塞入了。
TransactionalCacheManager主要用于事务控制中的缓存处理,它能够管理缓存的创建、销毁、清空等操作。在实现中,TransactionalCacheManager利用了事务的特性,将缓存和事务绑定在一起,保证了在同一事务中的所有操作都能正确地访问到缓存。
TransactionalCacheManager有多种实现方式,包括PerpetualCache、SoftCache、LruCache等。根据不同的使用场景,可以选择不同的实现方式以达到最佳的性能和效果。上图使用的是PerpetualCache实现的二级缓存。