Mybatis一二级缓存原理

133 阅读2分钟

前言

Mybatis中的一级缓存和二级缓存在使用中是非常频繁的,但是一般使用时都不太关注底层原理,导致在面试或者工作中遇到一些问题不知道怎么解决。

1、一级缓存

先讲概念,什么是一级缓存,缓存的等级是根据靠近数据库底层的距离来划分的,比如一级缓存就是距离数据库最近的,二级缓存相对一级缓存要更远一些,因此,查询的时候是先查询二级,再查询一级。缓存层级如图:

image.png

一级缓存实现类所在的位置是org.apache.ibatis.executor.BaseExecutor#query()

image.png 这里便是从一级缓存查询数据,如果查询不到则继续从数据库查询,这里一个很重要的内容就是cacheKey,cacheKey包含的内容如下:

image.png 1、当前statement的id编号
2、BoundSql的offset偏移量
3、BoundSql的条数
4、Sql语句
5、sql中所有参数的名称和值

一级缓存的数据是什么时候放进去的?

当然是查询的时候了,源码如下:

image.png

2、二级缓存

二级缓存相对于一级缓存是一个更外层的缓存装置,他可以选择和第三方容器结合,也可以单独存在。二级缓存的查询是在org.apache.ibatis.executor.CachingExecutor#query()中实现的。

image.png

配置开启二级缓存:

<settings>
  <!-- 打印sql日志 -->
  <setting name="logImpl" value="STDOUT_LOGGING" />
  <!-- 开启二级缓存 -->
  <setting name="cacheEnabled" value="true"/>
</settings>

Mapper文件中添加二级缓存标识

image.png

实体对象一定要实现Serializable image.png 二级缓存的使用:

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());

  }
}

测试结果:

image.png

从图中可以看到二级缓存已经生效了。那么二级缓存的数据是什么时候塞入的呢?根据源码可以看出是查询出来的时候就已经塞入了。

image.png

TransactionalCacheManager主要用于事务控制中的缓存处理,它能够管理缓存的创建、销毁、清空等操作。在实现中,TransactionalCacheManager利用了事务的特性,将缓存和事务绑定在一起,保证了在同一事务中的所有操作都能正确地访问到缓存。

TransactionalCacheManager有多种实现方式,包括PerpetualCache、SoftCache、LruCache等。根据不同的使用场景,可以选择不同的实现方式以达到最佳的性能和效果。上图使用的是PerpetualCache实现的二级缓存。