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

相关推荐
liuyao_xianhui4 分钟前
优选算法_最小基因变化_bfs_C++
java·开发语言·数据结构·c++·算法·哈希算法·宽度优先
做一个AK梦6 分钟前
计算机系统概论知识点(软件设计师)
java·开发语言
m0_6125359912 分钟前
redis入门到精通
数据库·redis·缓存
東雪木23 分钟前
Java学习——一访问修饰符(public/protected/default/private)的权限控制本质
java·开发语言·学习·java面试
两点王爷44 分钟前
docker 创建和使用存储卷相关内容
java·docker·容器
boonya1 小时前
Embedding模型与向量维度动态切换完整方案
java·数据库·embedding·动态切换大模型
宁波阿成1 小时前
族谱管理系统架构分析与亮点总结
java·系统架构·vue·ruoyi-vue·族谱
刘~浪地球1 小时前
Redis 从入门到精通(三):键操作命令详解
数据库·redis·缓存
姬成韶1 小时前
BUUCTF--[RoarCTF 2019]Easy Java
java·网络安全
组合缺一1 小时前
Solon AI Harness 首次发版
java·人工智能·ai·llm·agent·solon