Mybatis缓存

发布时间:2024年01月17日

MyBatis 的缓存分为一级缓存和二级缓存,两者的主要目的是减少数据库的查询次数,提高应用程序的性能。

一级缓存(本地缓存)

MyBatis 默认的一级缓存是会话级别的,也就是说,只在一个 SqlSession 范围内有效。一旦会话被关闭,缓存也就消失了。

工作机制:

  • 一级缓存是基于 PerpetualCache 的哈希表,默认情况下,它只是一个简单的 HashMap 实例。
  • 当在一个 SqlSession 中执行查询,MyBatis 会将查询结果缓存起来。
  • 如果后续的查询请求(在同一个 SqlSession 中)和之前的请求完全相同,包括查询语句、参数和分页信息等,MyBatis 会直接从缓存中获取结果。

代码示例:

try (SqlSession session = sqlSessionFactory.openSession()) {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  
  // 第一次查询
  Blog blog = mapper.selectBlog(101);
  // 这里的第二次查询会直接从缓存中获取数据
  Blog sameBlog = mapper.selectBlog(101);
}

一级缓存失效场景:

  • SqlSession 不同。
  • SqlSession 相同,查询条件不同。
  • SqlSession 相同,在两次相同查询之间执行了增删改操作。
  • SqlSession 相同,但是手动清除了缓存。

二级缓存(全局缓存)

二级缓存是跨 SqlSession 的,它的生命周期不仅限于会话的持续时间,可以跨会话和映射器共享。

工作机制:

  • 二级缓存需要在配置文件中显式开启,在 mapper 文件中配置 <cache/> 标签。
  • 二级缓存可以配置多种属性,如 eviction(淘汰策略)、flushInterval(刷新间隔)、size(引用数量)等。
  • 查询结果会被缓存,并在多个 SqlSession 间共享,只要它们向同一个 Mapper 发出相同的查询请求。
  • 事务提交或会话关闭时,MyBatis 会更新二级缓存。

配置示例:

<!-- 在 mybatis-config.xml 中启用二级缓存 -->
<settings>
  <setting name="cacheEnabled" value="true"/>
</settings>

<!-- 在对应的 Mapper.xml 文件中配置二级缓存 -->
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

代码示例:
假设我们有一个 BlogMapper.xml,我们在其中启用二级缓存:

<mapper namespace="org.mybatis.example.BlogMapper">
  <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
  <!-- 其他的 SQL 映射语句 -->
</mapper>

接着,我们的 Java 代码可能如下所示:

// 第一个 SqlSession
try (SqlSession session1 = sqlSessionFactory.openSession()) {
  BlogMapper mapper1 = session1.getMapper(BlogMapper.class);
  Blog blog1 = mapper1.selectBlog(101);
  session1.commit(); // 触发二级缓存
}

// 第二个 SqlSession
try (SqlSession session2 = sqlSessionFactory.openSession()) {
  BlogMapper mapper2 = session2.getMapper(BlogMapper.class);
  // 这次查询将会走二级缓存
  Blog blog2 = mapper2.selectBlog(101);
}

二级缓存失效场景:

  • 映射语句配置了 flushCache=true(默认行为是 true)。
  • SqlSession 调用了 clearCache() 方法。
  • 事务回滚,即使之前有查询操作。
  • 对当前缓存的增删改操作将会清空缓存。

自定义缓存

可以通过自定义实现 org.apache.ibatis.cache.Cache 接口来创建自己的缓存类型,这可以让你实现诸如 Redis、Ehcache 等分布式缓存的集成。

示例代码片段:

public class MyCustomCache implements Cache {
  private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  
  // 需要实现的方法,例如 getId, getSize, putObject, getObject, removeObject, clear 等
  
  @Override
  public String getId() {
    // 缓存的唯一标识符
  }
  
  // 其他方法实现...
}
<!-- 在 Mapper.xml 文件中使用自定义缓存 -->
<cache type="org.mybatis.caches.myown.MyCustomCache"/>

在深入应用 MyBatis 缓存时,考虑缓存配置对应用程序行为的影响是关键。特别是在高并发环境中,缓存的使用可能会导致数据不一致。此外,过多地依赖缓存也可能会导致缓存穿透、缓存雪崩等问题,因此需要谨慎设计缓存的大小、过期策略和同步机制。

文章来源:https://blog.csdn.net/qq_43012298/article/details/135618784
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。