一分钟理解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 的共享缓存,可以提升全局的查询效率。通过合理配置和管理缓存,可以优化数据库的访问性能。

相关推荐
在努力的前端小白3 小时前
Spring Boot 敏感词过滤组件实现:基于DFA算法的高效敏感词检测与替换
java·数据库·spring boot·文本处理·敏感词过滤·dfa算法·组件开发
一叶飘零_sweeeet5 小时前
从繁琐到优雅:Java Lambda 表达式全解析与实战指南
java·lambda·java8
艾伦~耶格尔6 小时前
【集合框架LinkedList底层添加元素机制】
java·开发语言·学习·面试
一只叫煤球的猫6 小时前
🕰 一个案例带你彻底搞懂延迟双删
java·后端·面试
最初的↘那颗心6 小时前
Flink Stream API 源码走读 - print()
java·大数据·hadoop·flink·实时计算
JH30737 小时前
Maven的三种项目打包方式——pom,jar,war的区别
java·maven·jar
带刺的坐椅8 小时前
轻量级流程编排框架,Solon Flow v3.5.0 发布
java·solon·workflow·flow·solon-flow
卡拉叽里呱啦8 小时前
缓存-变更事件捕捉、更新策略、本地缓存和热key问题
分布式·后端·缓存
David爱编程8 小时前
线程调度策略详解:时间片轮转 vs 优先级机制,面试常考!
java·后端
阿冲Runner9 小时前
创建一个生产可用的线程池
java·后端