当前位置: 首页 > article >正文

13. 说说 MyBatis 的缓存机制?

MyBatis 提供了一级缓存和二级缓存两种缓存机制,用于提高应用程序的性能,减少数据库的访问次数。缓存机制是 MyBatis 的一个重要特性,通过缓存可以在一定程度上减少对数据库的访问,从而提高查询性能。

1. 一级缓存(Local Cache)

作用范围:一级缓存是 MyBatis 默认开启的缓存机制,作用于 SqlSession 级别。

特点

  • 生命周期:一级缓存的生命周期与 SqlSession 相同。在同一个 SqlSession 中执行多次相同的查询(条件相同),如果缓存中已经存在结果,则直接返回缓存中的结果,而不再向数据库发送查询请求。

  • 存储方式:一级缓存是基于 PerpetualCache 和 HashMap 实现的,存储查询结果的键值对,键为 SQL 语句的字符串及其参数,值为查询结果。

  • 失效条件:在 SqlSession 中,如果执行了 INSERTUPDATEDELETE 操作,一级缓存会被清空,确保数据的一致性。另外,手动清空缓存或关闭 SqlSession 也会使一级缓存失效。

示例

SqlSession session = sqlSessionFactory.openSession();
User user1 = session.selectOne("selectUserById", 1); // 从数据库查询
User user2 = session.selectOne("selectUserById", 1); // 从一级缓存中获取结果

2. 二级缓存(Global Cache)

作用范围:二级缓存是 MyBatis 的全局缓存机制,作用于 Mapper 映射器级别。即同一个 Mapper 映射器中的查询结果可以被不同的 SqlSession 实例共享。

特点

  • 默认关闭:二级缓存默认是关闭的,需要在配置文件或 Mapper 文件中显式开启。

  • SqlSession:二级缓存是跨 SqlSession 的,多个 SqlSession 可以共享同一个 Mapper 中的缓存数据。

  • 存储方式:二级缓存也是基于 PerpetualCache 实现的,并且需要将缓存对象序列化,因此缓存对象必须实现 Serializable 接口。

  • 失效条件:当执行 INSERTUPDATEDELETE 等修改操作时,二级缓存会被清空。同时,事务提交后,查询结果才会写入二级缓存。

启用二级缓存

  1. 在 MyBatis 全局配置文件中启用二级缓存

    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
  2. 在具体的 Mapper 文件中配置二级缓存

    <mapper namespace="com.example.mapper.UserMapper">
        <!-- 启用二级缓存 -->
        <cache />
        
        <select id="selectUserById" resultType="User">
            SELECT * FROM user WHERE id = #{id}
        </select>
    </mapper>

示例

// 第一次查询,结果存入二级缓存
try (SqlSession session1 = sqlSessionFactory.openSession()) {
    UserMapper mapper1 = session1.getMapper(UserMapper.class);
    User user1 = mapper1.selectUserById(1);
}
​
// 第二次查询,不同的 SqlSession 实例,结果从二级缓存中获取
try (SqlSession session2 = sqlSessionFactory.openSession()) {
    UserMapper mapper2 = session2.getMapper(UserMapper.class);
    User user2 = mapper2.selectUserById(1);
}

3. 一级缓存与二级缓存的比较

特性一级缓存二级缓存
作用范围SqlSession 级别Mapper 映射器级别,跨 SqlSession
默认状态默认开启默认关闭
缓存生命周期SqlSession 相同Mapper 相同
缓存失效SqlSession 执行写操作时清空Mapper 执行写操作时清空
缓存共享不同的 SqlSession 之间不共享不同的 SqlSession 之间共享

4. 配置和管理二级缓存

MyBatis 提供了多种方式来配置和管理二级缓存:

  • 缓存策略:可以通过 <cache> 标签的 eviction 属性配置缓存回收策略。默认使用 LRU(最近最少使用),其他选项包括 FIFO(先进先出)、SOFT(软引用)、WEAK(弱引用)。

  • 刷新间隔:通过 flushInterval 属性配置缓存的刷新间隔。默认情况下不会自动刷新,可以设置为毫秒级的刷新间隔。

  • 缓存大小:通过 size 属性设置缓存的最大对象数量。

  • 只读模式:通过 readOnly 属性设置缓存是否为只读模式。只读模式下,缓存中的对象在缓存期间不可修改,适合提高并发性能。

示例配置

<cache 
    eviction="FIFO" 
    flushInterval="60000"  <!-- 缓存60秒刷新一次 -->
    size="512"              <!-- 缓存中最多保存512个对象 -->
    readOnly="true"         <!-- 只读缓存,提升并发性能 -->
/>

5. 使用注意事项

  • 事务管理:二级缓存和事务管理紧密相关,只有在事务提交后,查询结果才会存入二级缓存。如果事务回滚,缓存不会更新。

  • 对象序列化:由于二级缓存需要将对象序列化,所有被缓存的对象必须实现 Serializable 接口。

  • 一致性问题:二级缓存会在更新数据时失效,但在高并发情况下,可能会有短暂的缓存不一致问题,需要根据实际情况权衡缓存带来的性能提升与一致性问题。

6. 总结

  • 一级缓存:每个 SqlSession 维护自己的一级缓存,默认开启,不同 SqlSession 之间不共享。适用于单个会话内重复查询的场景。

  • 二级缓存:二级缓存是跨 SqlSession 的全局缓存,默认关闭,需要手动开启和配置。适用于多次会话之间需要共享查询结果的场景。

通过合理配置 MyBatis 的一级和二级缓存,可以显著提升应用程序的性能,特别是在读多写少的场景中,缓存机制可以有效减少数据库访问次数,提升查询效率。


http://www.kler.cn/news/294509.html

相关文章:

  • MySQL 数据库管理与操作指南
  • 自定义view中常用到哪些方法作用分别是什么
  • 专栏前言-WooYun漏洞库环境搭建
  • Java详解String 字符串类以及String内存原理、StringBuilder类、StringJoiner类(附有代码+案例)
  • MASt3R:从3D的角度来实现图像匹配(更新中)
  • 前端工程化2:从0-1的eslint插件开发教程
  • 基于Prometheus 和K8S kubernetes 构建 搭建监控告警系统
  • 单点登录:cas单点登录实现原理浅析
  • 【Vue】状态管理模式Vuex
  • 通信工程学习:什么是AM标准调幅
  • [情商-13]:语言的艺术:何为真实和真相,所谓真相,就是别人想让你知道的真相!洞察谎言与真相!
  • Redis在登录接口中实现token时间的自适应增长
  • mysql5.6根据经纬度查询距离
  • 亚马逊测评深度解析:如何安全高效提升产品销量和好评
  • HTB-Pennyworth(cve查询 和 exp使用)
  • 《征服数据结构》差分数组
  • 【K8S实践笔记】Kubernetes Dashboard v2.7.0 的安装与配置(2)
  • 【Windows】【C++】【Udp】 udp通信协议详解和示例
  • 力扣 797. 所有可能路径【DFS】
  • 尚品汇-商品上下架完善(更新ES)、延迟消息(四十四)
  • CSDN文章无水印转成PDF
  • 【数据结构入门】排序算法之交换排序与归并排序
  • UE5.3_跟一个插件—Socket.IO Client
  • 【爬虫软件】小红薯评论区采集工具
  • 目标检测-RT-DETR
  • 抖音发布Unity小游戏的errorMsg: native build failed
  • 【人工智能学习笔记】1_人工智能基础
  • 【redis】数据量庞大时的应对策略
  • 从源码角度分析 Kotlin by lazy 的实现
  • 固态硬盘装系统有必要分区吗?