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

MyBatis实战指南(七)MyBatis缓存机制

MyBatis实战指南(七)MyBatis缓存机制

  • 前言
  • 一、 为什么需要缓存?
  • 二、 MyBatis的缓存层次
  • 三、 一级缓存
    • 3.1 一级缓存(本地缓存)
    • 3.2 一级缓存的工作原理
    • 3.3 一级缓存示例
    • 3.4 一级缓存的特点
    • 3.5 一级缓存的优缺点
  • 四、 二级缓存
    • 4.1 什么是二级缓存?
    • 4.2 为什么需要二级缓存?
    • 4.3 如何配置二级缓存?
    • 4.4 自定义二级缓存配置
    • 4.5 可用的清除策略
    • 4.6 二级缓存的特点
    • 4.7 二级缓存的使用示例
  • 五、 一级缓存和二级缓存的对比表格


前言

  • 在上一篇博客中,我们深入解析了 MyBatis XML 实战的核心要点,围绕自动映射机制展开全面讲解,从字段命名匹配规则到驼峰转换配置(mapUnderscoreToCamelCase),再到自动映射行为控制(autoMappingBehavior),通过具体案例演示了如何利用 MyBatis 的自动映射能力简化对象与数据库的映射流程
  • 本篇博客将聚焦 MyBatis 的缓存优化体系,从底层原理到实战配置进行分层拆解

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的MyBatis实战指南知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12969707.html?spm=1001.2014.3001.5482


一、 为什么需要缓存?

  • 想象一下,你有一个网站,每次用户访问页面都要从数据库查询相同的数据
  • 如果这个页面每天有1000人访问,那就意味着数据库要执行1000次相同的查询。
  • 这会给数据库带来很大的压力甚至可能导致数据库崩溃

缓存就是解决这个问题的好办法。

它就像一个临时存储区,把经常访问的数据存起来,下次再需要这些数据时,直接从缓存中拿,而不需要再去访问数据库,这样可以大大提高系统性能。

二、 MyBatis的缓存层次

MyBatis有两级缓存机制:

  1. 一级缓存(本地缓存):默认开启,只在当前会话(SqlSession)中有效
  2. 二级缓存(全局缓存):需要手动配置,可以在多个会话之间共享

三、 一级缓存

3.1 一级缓存(本地缓存)

一级缓存是MyBatis的默认缓存机制,它是会话级别的缓存。这意味着:

  • 同一个SqlSession中执行相同的查询,只会执行一次数据库查询,后续查询会直接从缓存中获取结果
  • 当SqlSession关闭后,该会话的一级缓存也会被清空
  • 当执行insert、update、delete操作时,会清空当前会话的一级缓存

3.2 一级缓存的工作原理

  1. 当你执行一个查询时,MyBatis首先会在当前会话的缓存中查找是否有相同的查询结果
  2. 如果有,直接从缓存中返回结果,不再执行数据库查询
  3. 如果没有,执行数据库查询,并将结果存入缓存

3.3 一级缓存示例

// 创建第一个会话
SqlSession session1 = sqlSessionFactory.openSession();
try {// 第一次查询,会执行SQLUser user1 = session1.selectOne("selectUserById", 1);System.out.println(user1.getName());// 第二次查询相同ID,不会执行SQL,直接从缓存获取User user2 = session1.selectOne("selectUserById", 1);System.out.println(user2.getName());// 两次查询获取的是同一个对象引用System.out.println(user1 == user2); // 输出 true
} finally {session1.close();
}// 创建第二个会话
SqlSession session2 = sqlSessionFactory.openSession();
try {// 在新会话中查询相同ID,会执行SQLUser user3 = session2.selectOne("selectUserById", 1);System.out.println(user3.getName());
} finally {session2.close();
}

3.4 一级缓存的特点

  • 自动启用:不需要任何配置,默认就会使用
  • 会话隔离:不同会话之间的缓存互不影响
  • 轻量级:实现简单,开销小
  • 生命周期短:随会话关闭而清空

3.5 一级缓存的优缺点

优点

  • 实现简单,不需要额外配置
  • 减少了同一会话内的重复查询,提高了性能
  • 对应用透明,不需要修改业务代码

缺点

  • 作用域太小,仅限于当前会话
  • 不能在应用重启后保留
  • 无法在分布式环境中共享

四、 二级缓存

4.1 什么是二级缓存?

二级缓存是MyBatis的全局缓存,它可以在多个SqlSession之间共享数据。这意味着:

  • 不同的会话查询相同的数据时,可以从同一个缓存中获取
  • 应用程序重启前,缓存数据会一直存在(除非被手动刷新)
  • 适合缓存那些不经常变化、经常被查询的数据

4.2 为什么需要二级缓存?

一级缓存虽然能提高同一会话内的查询性能,但在以下场景下显得不足

  • 跨会话查询相同数据时,仍然会多次访问数据库
  • 在分布式系统中,不同服务实例无法共享缓存
  • 对于高并发系统,一级缓存的作用有限

二级缓存正是为了解决这些问题而设计的。

4.3 如何配置二级缓存?

要启用二级缓存,只需在SQL映射文件中添加<cache/>标签:

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

这行简单的配置会产生以下效果:

  • 该映射文件中所有SELECT语句的结果会被缓存
  • 所有INSERT、UPDATE、DELETE语句会刷新缓存
  • 默认使用LRU(最近最少使用)策略清除缓存
  • 最多存储1024个对象引用
  • 缓存对象可读写(返回的是对象副本)

4.4 自定义二级缓存配置

你可以通过<cache/>标签的属性来自定义缓存行为:

<cacheeviction="FIFO"                <!-- 清除策略:先进先出 -->flushInterval="60000"          <!-- 刷新间隔:60秒 -->size="512"                     <!-- 缓存大小:最多512个对象 -->readOnly="true"/>              <!-- 只读缓存:提高性能但返回共享对象 -->

4.5 可用的清除策略

MyBatis提供了四种缓存清除策略:

  1. LRU(默认):移除最长时间不被使用的对象
  2. FIFO:按对象进入缓存的顺序移除
  3. SOFT:基于JVM垃圾回收器状态和软引用规则移除
  4. WEAK:更激进的回收策略,基于弱引用规则移除

4.6 二级缓存的特点

  1. 全局共享:多个SqlSession可以共享同一个缓存
  2. 需要手动配置:默认不启用,必须在映射文件中声明
  3. 会话间隔离:每个命名空间(通常对应一个Mapper接口)有独立的缓存
  4. 事务支持:在事务提交或回滚时,缓存会被正确刷新
  5. 序列化要求:缓存对象必须实现Serializable接口

4.7 二级缓存的使用示例

// 第一个会话
SqlSession session1 = sqlSessionFactory.openSession();
try {UserMapper mapper1 = session1.getMapper(UserMapper.class);User user1 = mapper1.selectUserById(1);  // 执行SQL查询session1.commit();  // 提交事务,将结果存入二级缓存
} finally {session1.close();
}// 第二个会话
SqlSession session2 = sqlSessionFactory.openSession();
try {UserMapper mapper2 = session2.getMapper(UserMapper.class);User user2 = mapper2.selectUserById(1);  // 直接从二级缓存获取System.out.println(user2.getName());
} finally {session2.close();
}

五、 一级缓存和二级缓存的对比表格

对比维度一级缓存(本地缓存)二级缓存(全局缓存)
作用域仅在当前SqlSession会话内有效SqlSession会话共享,属于全局范围
默认状态自动启用(无需配置)需手动在Mapper文件中添加<cache/>标签启用
缓存生命周期SqlSession关闭而清空随应用重启或手动刷新才会清空
数据共享仅在当前会话内共享,不同会话间不共享同一Mapper命名空间下的所有会话共享
刷新机制执行insert/update/delete操作时自动清空当前会话缓存执行insert/update/delete操作时清空全局缓存
缓存策略配置无需配置,使用固定策略可自定义配置(清除策略、刷新间隔、缓存大小等)
缓存对象要求无特殊要求(直接引用对象)对象需实现Serializable接口(支持序列化)
性能影响开销小(轻量级,无序列化开销)存在序列化/反序列化开销,可通过readOnly优化
适用场景同一会话内的重复查询、短生命周期事务跨会话的重复查询、不常更新且频繁访问的数据
分布式支持不支持(仅单JVM内有效)原生不支持,需集成第三方缓存(如Redis、Memcached)
典型场景示例单事务内多次查询同一数据系统字典表、配置表的全局缓存

以上就是这篇博客的全部内容,下一篇我们将继续探索MyBatis的更多精彩内容。

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的MyBatis实战指南知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12969707.html?spm=1001.2014.3001.5482

非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述

相关文章:

  • Python毕业设计226—基于python+爬虫+html的豆瓣影视数据可视化系统(源代码+数据库+万字论文)
  • Linux:多线程---线程控制(线程创建线程等待线程终止)
  • AJAX、Axios 与 Fetch:现代前端数据请求技术对比
  • Linux Swap分区应该禁用吗?深入辨析其作用与性能优化
  • React 状态管理指南:Redux 原理与优化策略
  • React删除评论逻辑:1、客户端立即更新UI(乐观更新)2、后台调用删除评论API
  • Flutter setState() 状态管理详细使用指南
  • 一键实现全站多语言化:translate.js 极简集成指南,支持Vue 、React 框架。
  • 《HarmonyOSNext属性动画实战手册:让UI丝滑起舞的魔法指南》
  • 深度学习小项目合集之音频语音识别
  • 【粤语ASRTTS】粤语语音识别与合成:重塑粤语智能化标杆
  • 通过flv.js在网页中拉流进行视频播放
  • SAP RESTFUL接口方式发布SICF实现全路径
  • 【Vue】组件及组件化, 组件生命周期
  • enumerable 和 configurable 属性详解
  • 海康对接摄像头
  • Docker快速构建并启动Springboot程序,快速发布和上线/
  • 前端基础知识ES6系列 - 03(数组新增了哪些扩展)
  • 论文阅读:强化预训练
  • html打印合同模板
  • 徐州网站建设市场/2024年新闻摘抄
  • 网站建站需要什么软件/兰州seo外包公司
  • 网站开发也需要源码吗/40个免费网站推广平台
  • 高端网站开发步骤/无锡网络优化推广公司
  • 如何把做的网站与域名连接/宁波网站优化公司哪家好
  • 厦门高端网站建设公/软件培训机构哪家好