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

11. MyBatis的一级缓存和二级缓存有什么区别?如何配置和使用二级缓存?

在 MyBatis 中,缓存机制用于减少数据库访问次数,提高应用程序性能。MyBatis 提供了两级缓存:一级缓存和二级缓存。

1. 一级缓存(Local Cache)

  • 作用范围:一级缓存作用于 SqlSession 级别。即在同一个 SqlSession 中执行相同的 SQL 查询,如果查询参数相同,MyBatis 会从缓存中直接返回结果,而不会再次查询数据库。

  • 默认开启:一级缓存是默认开启的,并且无法关闭。

  • 缓存生命周期:一级缓存的生命周期与 SqlSession 的生命周期一致。当 SqlSession 关闭后,一级缓存也随之被清空。

  • 失效条件:在 SqlSession 期间,如果执行了 INSERTUPDATEDELETE 等写操作,一级缓存将被清空,确保数据一致性。

示例

SqlSession session = sqlSessionFactory.openSession();
User user1 = session.selectOne("selectUserById", 1);
User user2 = session.selectOne("selectUserById", 1); // 第二次查询将从缓存中获取结果

在这个例子中,如果在同一个 SqlSession 中两次查询相同的 User 对象,第二次查询结果将从一级缓存中获取。

2. 二级缓存(Global Cache)

  • 作用范围:二级缓存作用于 Mapper 映射器级别。即同一个 Mapper 中执行相同的 SQL 查询,如果查询参数相同,MyBatis 会从二级缓存中直接返回结果,而不会再次查询数据库。

  • 手动配置:二级缓存默认是关闭的,需要显式配置才能开启。

  • 缓存共享:二级缓存是跨 SqlSession 的,因此不同的 SqlSession 实例可以共享同一个二级缓存。

  • 失效条件:在某个 Mapper 中执行了 INSERTUPDATEDELETE 操作,二级缓存将被清空,确保数据一致性。

示例

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

在这个例子中,即使在不同的 SqlSession 实例中,第二次查询的结果也可以从二级缓存中获取。

如何配置和使用二级缓存?

要使用 MyBatis 的二级缓存,需要进行以下配置:

1. 启用全局二级缓存

在 MyBatis 的全局配置文件(如 mybatis-config.xml)中,启用全局二级缓存支持:

<settings><setting name="cacheEnabled" value="true"/>
</settings>

默认情况下,cacheEnabled 设置为 true,表示全局启用二级缓存。

2. 在 Mapper 文件中启用二级缓存

在具体的 Mapper 文件中,通过 <cache> 标签为某个映射器启用二级缓存:

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

<cache> 标签默认配置了 LRU(Least Recently Used,最近最少使用)缓存策略、无超时清除、无缓存大小限制等默认参数。

3. 配置二级缓存的行为

你可以在 <cache> 标签中配置缓存的具体行为,如缓存策略、缓存大小、过期时间等。

常见配置选项

  • eviction:缓存回收策略,默认为 LRU(最近最少使用),其他选项包括 FIFO(先进先出)、SOFT(软引用)、WEAK(弱引用)。

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

  • size:缓存的数量,默认没有限制。

  • readOnly:是否只读,默认为 false,如果设置为 true,则提高并发性能,但所有返回的对象在缓存期间不可修改。

示例配置

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

4. 使用二级缓存的注意事项

  • 与事务管理的关系:二级缓存与事务紧密关联。只有在事务提交后,查询结果才会被存储到二级缓存中。如果事务未提交或回滚,则缓存不会更新。

  • 序列化:MyBatis 的二级缓存需要将缓存对象序列化,因此被缓存的对象必须实现 Serializable 接口。

  • 缓存失效:如前所述,当执行插入、更新或删除操作时,二级缓存会被清空,以确保数据一致性。

5. 二级缓存的使用示例

假设你有以下 Java 类和 Mapper 接口:

public class User implements Serializable {private int id;private String name;// Getters and setters
}
​
public interface UserMapper {User selectUserById(int id);
}

MyBatis 配置文件

<settings><setting name="cacheEnabled" value="true"/>
</settings>

UserMapper.xml

<mapper namespace="com.example.mapper.UserMapper"><cache /><select id="selectUserById" resultType="User">SELECT * FROM user WHERE id = #{id}</select>
</mapper>

在启用了二级缓存之后,第一次查询时 MyBatis 会从数据库中获取数据并存储到二级缓存中。第二次查询相同的数据时,MyBatis 会直接从二级缓存中获取结果,而不再访问数据库。

总结

  • 一级缓存:作用于 SqlSession 级别,默认开启,生命周期与 SqlSession 相同,主要用于减少同一个会话中重复查询的数据库访问。

  • 二级缓存:作用于 Mapper 级别,默认关闭,需要手动配置。二级缓存是跨 SqlSession 的缓存,适合在多个会话中共享查询结果。

通过合理配置和使用二级缓存,可以显著提高 MyBatis 应用的性能,特别是在读多写少的场景中,二级缓存能够有效减少数据库的压力,提高查询效率。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • redis之缓存淘汰策略
  • 『功能项目』项目优化 - 默认管线转URP【31】
  • vue如何实现路由缓存
  • 7.统一网关-Gateway
  • 解决Pynput不能在Ubuntu22.04上正常使用问题
  • 百度飞将 paddle ,实现贝叶斯神经网络 bayesue neure network bnn,aistudio公开项目 复现效果不好
  • Oracle SQL和PL/SQL中SQL%ROWCOUNT和SQL%FOUND属性
  • STM32
  • 【Linux】冯诺依曼概念以及操作系统基础概念
  • Hadoop 下载
  • 集运系统需要与哪些硬件设备集成?
  • QString如何追加字符串
  • 视频安防监控LntonAIServer安防管理平台抖动检测和过亮过暗检测
  • 电工基础知识
  • Mental-LLM——通过在线文本数据利用大型语言模型进行心理健康预测
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • co.js - 让异步代码同步化
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • JavaScript DOM 10 - 滚动
  • Java到底能干嘛?
  • js 实现textarea输入字数提示
  • laravel 用artisan创建自己的模板
  • Mithril.js 入门介绍
  • nginx 配置多 域名 + 多 https
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • Puppeteer:浏览器控制器
  • vuex 笔记整理
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 简单数学运算程序(不定期更新)
  • 嵌入式文件系统
  • 使用SAX解析XML
  • C# - 为值类型重定义相等性
  • ​Linux·i2c驱动架构​
  • ​第20课 在Android Native开发中加入新的C++类
  • # Redis 入门到精通(七)-- redis 删除策略
  • # 飞书APP集成平台-数字化落地
  • #Linux(权限管理)
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (3)选择元素——(17)练习(Exercises)
  • (LeetCode C++)盛最多水的容器
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (差分)胡桃爱原石
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (回溯) LeetCode 46. 全排列
  • (十)c52学习之旅-定时器实验
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (四)图像的%2线性拉伸
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转)负载均衡,回话保持,cookie
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET Framework .NET Core与 .NET 的区别