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

相关推荐
北漂老男孩7 分钟前
Flink基于Yarn多种启动方式详解
java·大数据·flink
王蛋1117 分钟前
后端环境配置
java·spring·maven
养-乐多9 分钟前
梳理Spring Boot中三种异常处理
java·spring boot·后端
找不到、了12 分钟前
字符串和常量池的进一步研究
java·开发语言
Code哈哈笑17 分钟前
【基于SpringBoot的图书购买系统】深度讲解 分页查询用户信息,分析前后端交互的原理
java·数据库·spring boot·后端·spring·交互
kingwebo'sZone23 分钟前
sqlite的拼接字段的方法(sqlite没有convert函数)
java·数据库·sqlite
星沁城26 分钟前
212. 单词搜索 II
java·数据结构·算法·leetcode
.生产的驴38 分钟前
Vue3 数据可视化屏幕大屏适配 页面自适应 响应式 数据大屏 大屏适配
java·c++·vue.js·后端·信息可视化·前端框架·vue
龙泉寺天下行走1 小时前
《进化陷阱》--AI 生成文章 《连载 1》
java·服务器·前端
王小义笔记1 小时前
使用注解动态映射:根据实体List列表动态生成Excel文件
java·数据结构·list·excel·poi