这样理解 MyBatis缓存机制,真香!

你好,我是猿java

为了提高数据访问的性能,MyBatis 采用了一级缓存和二级缓存的缓存机制,那么它们是如何工作的?这篇文章,我们将详细介绍这两种缓存机制及其工作原理、配置方式和使用场景。

首先,看一张原理图:

接着,我们来详细地分析它们。

1. 一级缓存

一级缓存(也叫本地缓存)是 MyBatis 默认开启的,是基于 SqlSession 级别的缓存。也就是说,在同一个 SqlSession 中,对于相同的查询,如果参数相同,MyBatis 会从一级缓存中直接获取数据,而不会再去执行数据库查询。

1.1 特点

  • 作用范围 :同一个 SqlSession 实例。
  • 默认开启:无需额外配置。
  • 清空时机
    • 执行 insertupdatedelete 操作时,一级缓存会被清空。
    • 调用 SqlSession.clearCache() 方法手动清空。

1.2 工作原理

当使用同一个 SqlSession 执行相同的 SQL 查询时,MyBatis 会先检查一级缓存是否存在对应的查询结果。如果存在,则直接返回缓存中的结果;如果不存在,则执行数据库查询并将结果放入一级缓存。

使用示例

java 复制代码
try (SqlSession session = sqlSessionFactory.openSession()) {
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user1 = mapper.getUserById(1); // 查询数据库,结果存入一级缓存
    User user2 = mapper.getUserById(1); // 从一级缓存中获取结果
    // user1 和 user2 指向同一个对象
}

2. 二级缓存(全局缓存)

二级缓存是基于 namespace(通常对应于 Mapper 接口)的缓存,作用范围超出了 SqlSession,同一个 mapper 的多个 SqlSession 共享一级缓存之外的缓存。二级缓存需要显式开启和配置。

2.1 特点

  • 作用范围 :同一个 Mapper 的所有 SqlSession 实例。
  • 默认关闭:需要在配置文件中手动开启。
  • 缓存实现:需要配置缓存实现类,如 MyBatis 自带的缓存或第三方缓存(例如 Ehcache、Redis)。
  • 序列化 :二级缓存中的对象需要序列化,以支持跨 SqlSession 共享。

2.2 启用步骤

  1. 全局配置 :在全局配置文件 mybatis-config.xml 中开启二级缓存。
xml 复制代码
<configuration>
  <settings>
      <setting name="cacheEnabled" value="true"/>
  </settings>
  ...
</configuration>
  1. Mapper 配置 :在每个需要使用二级缓存的 Mapper XML 文件中配置 <cache> 标签。
xml 复制代码
<mapper namespace="com.example.mapper.UserMapper">
  <cache/>
  <!-- SQL 语句定义 -->
</mapper>

或者使用自定义缓存实现:

xml 复制代码
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  1. 映射接口注解:可以通过注解方式配置缓存(适用于 MyBatis 3.2 及以上版本)。
java 复制代码
@CacheNamespace
public interface UserMapper {
  // 方法定义
}

2.3 缓存清理策略

MyBatis 二级缓存使用的是基于读写的缓存策略,当涉及数据修改操作(insertupdatedelete)时,会清理相关 Mapper 的二级缓存,以保证数据一致性。

使用示例

java 复制代码
// 第一个 SqlSession
try (SqlSession session1 = sqlSessionFactory.openSession()) {
    UserMapper mapper1 = session1.getMapper(UserMapper.class);
    User user1 = mapper1.getUserById(1); // 查询数据库,结果存入一级和二级缓存
    session1.commit();
}

// 第二个 SqlSession
try (SqlSession session2 = sqlSessionFactory.openSession()) {
    UserMapper mapper2 = session2.getMapper(UserMapper.class);
    User user2 = mapper2.getUserById(1); // 从二级缓存中获取结果
}

3. 缓存的高级配置

3.1 缓存刷新策略

可以通过 <cache> 标签的属性来配置缓存的刷新策略,如:

  • eviction:指定缓存的清理策略(默认 LRU 策略)。
  • flushInterval:指定缓存刷新时间间隔(单位:毫秒)。
  • size:指定缓存的大小。
  • readOnly:指定缓存是否为只读。

示例:

xml 复制代码
<cache
    eviction="FIFO"
    flushInterval="60000"
    size="512"
    readOnly="true"/>

3.2 使用第三方缓存

MyBatis 支持集成多种第三方缓存,如 Ehcache、Redis、Hazelcast 等。以 Ehcache 为例,配置步骤如下:

  1. 添加依赖
xml 复制代码
<dependency>
  <groupId>org.mybatis.caches</groupId>
  <artifactId>mybatis-ehcache</artifactId>
  <version>1.2.1</version>
</dependency>
<dependency>
  <groupId>net.sf.ehcache</groupId>
  <artifactId>ehcache</artifactId>
  <version>2.10.6</version>
</dependency>
  1. 配置 Mapper
xml 复制代码
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  1. 配置 Ehcache

创建 ehcache.xml 文件,配置缓存策略。

xml 复制代码
<ehcache>
    <cache name="com.example.mapper.UserMapper"
           maxEntriesLocalHeap="1000"
           eternal="false"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"
           overflowToDisk="false"/>
</ehcache>

4. 缓存使用注意事项

  1. 数据一致性:使用二级缓存时,需要确保缓存与数据库的数据一致性,特别是在分布式环境下,推荐使用分布式缓存解决方案。
  2. 对象可序列化 :二级缓存中的对象需要实现 Serializable 接口,以支持缓存的序列化和反序列化。
  3. 避免缓存穿透:对高频率的查询,可以适当配置缓存,从而减少数据库的压力。
  4. 缓存命中率:合理设计查询语句和缓存策略,提升缓存的命中率,优化性能。

5. 总结

本文,我们详细地介绍了 MyBatis 的缓存策略,包括一级缓存适用于单次请求中的重复查询,而二级缓存适用于跨请求的共享缓存。在实际应用中,应根据具体业务需求和系统架构,选择合适的缓存策略和实现方式,以达到最佳的性能优化效果。

6. 学习交流

如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。

相关推荐
AI人H哥会Java40 分钟前
【Spring】Spring的模块架构与生态圈—Spring MVC与Spring WebFlux
java·开发语言·后端·spring·架构
毕设资源大全1 小时前
基于SpringBoot+html+vue实现的林业产品推荐系统【源码+文档+数据库文件+包部署成功+答疑解惑问到会为止】
java·数据库·vue.js·spring boot·后端·mysql·html
Watermelon_Mr1 小时前
Spring(三)-SpringWeb-概述、特点、搭建、运行流程、组件、接受请求、获取请求数据、特殊处理、拦截器
java·后端·spring
eternal__day2 小时前
数据结构十大排序之(冒泡,快排,并归)
java·数据结构·算法
唐墨1232 小时前
golang自定义MarshalJSON、UnmarshalJSON 原理和技巧
开发语言·后端·golang
凡人的AI工具箱2 小时前
每天40分玩转Django:Django测试
数据库·人工智能·后端·python·django·sqlite
qyq12 小时前
Django框架与ORM框架
后端·python·django
Theodore_10223 小时前
3 需求分析
java·开发语言·算法·java-ee·软件工程·需求分析·需求
小笨猪-3 小时前
统⼀服务⼊⼝-Gateway
java·spring cloud·微服务·gateway
深耕AI3 小时前
在Excel中绘制ActiveX控件:解决文本编辑框定位问题
java·前端·excel