一分钟理解Mybatis 里面的缓存机制

MyBatis 是一个流行的 Java 持久层框架,它简化了数据库操作。MyBatis 提供了强大的缓存机制,用于提升性能,减少数据库的访问次数。MyBatis 的缓存机制分为一级缓存和二级缓存。

​ 该图展示了用户通过 SqlSession 发起查询请求,SqlSession 会首先在一级缓存中查找,如果未命中,则在二级缓存中查找,最终返回查询结果的过程。

1. 一级缓存

一级缓存是 MyBatis 的默认缓存,它是 SqlSession 级别的缓存。每个 SqlSession 对象都有自己的一级缓存。查询的结果会存储在当前 SqlSession 中,如果再次执行相同的查询(在同一个 SqlSession 中),MyBatis 会直接从缓存中获取数据,而不再去访问数据库。
一级缓存的特点:
  • 作用域:SqlSession 级别,每个 SqlSession 都有自己的缓存。
  • 失效条件 :如果调用了 clearCache(),或者 SqlSession 被关闭,缓存会失效。

示例代码(一级缓存)

xml 复制代码
<!-- 配置 MyBatis 的 mapper 文件 -->
<mapper namespace="com.example.mapper.UserMapper">

    <!-- 查询用户 -->
    <select id="getUserById" resultType="com.example.model.User">
        SELECT * FROM users WHERE id = #{id}
    </select>

</mapper>
java 复制代码
// 获取 SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();

// 第一次查询,MyBatis 会从数据库中获取数据
User user1 = sqlSession.selectOne("com.example.mapper.UserMapper.getUserById", 1);

// 第二次查询,MyBatis 会从一级缓存中获取数据,而不会再去查询数据库
User user2 = sqlSession.selectOne("com.example.mapper.UserMapper.getUserById", 1);

System.out.println(user1 == user2);  // 输出 true,表示是同一个对象

sqlSession.close();  // 关闭 SqlSession,缓存清空

2. 二级缓存

​ 二级缓存是跨 SqlSession 共享的缓存。MyBatis 提供了全局共享缓存机制,它的作用范围大于一级缓存,跨越了多个 SqlSession 的生命周期。二级缓存的使用需要手动配置。

二级缓存的特点:
  • 作用范围:Mapper 映射器级别,不同的 SqlSession 之间可以共享缓存。
  • 缓存实现:默认使用的是内存缓存,也可以使用自定义缓存实现(如 Redis)。
  • 失效条件 :如果数据发生变化,比如执行了 updateinsertdelete 操作,缓存会被清空。
配置二级缓存

mybatis-config.xml 文件中,需要启用二级缓存功能,并配置缓存。

xml 复制代码
<!-- mybatis-config.xml 配置 -->
<configuration>
    <settings>
        <!-- 启用二级缓存 -->
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>

在 Mapper 配置文件中启用缓存,并配置缓存策略。

xml 复制代码
<mapper namespace="com.example.mapper.UserMapper">

    <!-- 启用二级缓存 -->
    <cache/>
    
    <select id="getUserById" resultType="com.example.model.User">
        SELECT * FROM users WHERE id = #{id}
    </select>

</mapper>

示例代码(二级缓存)

java 复制代码
// 获取 SqlSession
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();

// 第一次查询,MyBatis 会从数据库中获取数据
User user1 = sqlSession1.selectOne("com.example.mapper.UserMapper.getUserById", 1);
sqlSession1.close();

// 第二次查询,跨 SqlSession,数据会从二级缓存中获取
User user2 = sqlSession2.selectOne("com.example.mapper.UserMapper.getUserById", 1);

System.out.println(user1 == user2);  // 输出 true,表示是同一个对象(从二级缓存中获取)

sqlSession2.close();

3. 缓存的刷新和清理

MyBatis 提供了多种方式来管理缓存的刷新和清理:

  • 手动清理缓存 :可以在代码中调用 clearCache() 方法来清除缓存。
  • 执行增删改操作时自动清除缓存 :当执行 insertupdatedelete 操作时,相关的缓存会被自动清除。

4. 自定义缓存

MyBatis 允许用户实现自定义缓存。例如,可以结合 Redis 来实现分布式缓存,或者使用其他缓存框架。

自定义缓存的示例

xml 复制代码
<mapper namespace="com.example.mapper.UserMapper">

    <!-- 配置自定义缓存 -->
    <cache type="com.example.cache.RedisCache"/>

    <select id="getUserById" resultType="com.example.model.User">
        SELECT * FROM users WHERE id = #{id}
    </select>

</mapper>

RedisCache 类中,继承 MyBatis 的 Cache 接口,提供对 Redis 的操作。

总结

​ MyBatis 的缓存机制通过一级缓存和二级缓存大大提高了数据库的访问性能。一级缓存是 SqlSession 级别的缓存,适用于同一 SqlSession 中的重复查询;二级缓存是跨 SqlSession 的共享缓存,可以提升全局的查询效率。通过合理配置和管理缓存,可以优化数据库的访问性能。

相关推荐
BUG研究员_2 小时前
MQ消息丢失解决方案
java·开发语言
m0_748238782 小时前
20.<Spring图书管理系统①(登录+添加图书)>
java·后端·spring
high20114 小时前
【Java 基础】-- 设计模式
java·单例模式·设计模式
LUCIAZZZ4 小时前
Java中的设计模式违反了哪些设计原则
java·开发语言·spring boot·后端·spring·设计模式
ashane13144 小时前
设计模式说明
java
powerfulzyh5 小时前
StarRocks-fe工程在Cursor中不能识别为Java项目
java·开发语言
一点多余.5 小时前
Spring Boot 自动装配深度解析与实践指南
xml·java·spring·自动装配
WeiLai11125 小时前
面试基础--Spring Boot启动流程及源码实现
java·spring boot·分布式·后端·面试·架构
Aqua Cheng.5 小时前
字节青训营后端方向的个人总结(2025年3月4日)
java·数据结构·算法
serendipity_hky6 小时前
【easy视频 | day04】视频转码 + 稿件管理 + 服务端审核稿件
java·数据库·redis·缓存·音视频