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

相关推荐
sunshine22 girl4 小时前
Java学习一 环境配置2 安装和基本使用Idea
java·学习·intellij-idea
嘿嘿-666 小时前
Windows 一键使用 GPT-6 Astra:Codex CLI 配置教程
java·人工智能·windows·gpt·chatgpt·web
策案案案7 小时前
YOLO: 将AI Agents嵌入到IntelliJ IDEA
java·大数据·人工智能·笔记·yolo·microsoft·intellij-idea
努力努力再努力wz7 小时前
【Redis入门系列】从 KEYS 到 SCAN:渐进式遍历、Cursor 与位反转原理
数据库·redis·缓存
辰烨chenye8 小时前
LeetCode Hot 100 题解 · 堆篇
java·算法·leetcode
小宋10218 小时前
大模型成本怎么控制:Token统计、缓存与模型路由实战
人工智能·缓存
shehuiyuelaiyuehao9 小时前
算法29,前缀和,除自身以外的数组的乘积
java·数据结构·算法
小刘在重生~9 小时前
Java常用类|String类详解 + BigDecimal精准计算(含面试题)
java·开发语言·python
随遇而安zx9 小时前
【多线程】---JMM 与 volatile 深度解析
java·多线程