【MyBatis-7】深入理解MyBatis二级缓存:提升应用性能的利器
在现代应用开发中,数据库访问往往是性能瓶颈之一。作为Java生态中广泛使用的ORM框架,MyBatis提供了一级缓存和二级缓存机制来优化数据库访问性能。本文将深入探讨MyBatis二级缓存的工作原理、配置方式、使用场景以及最佳实践,帮助开发者充分利用这一特性提升应用性能。
1. MyBatis缓存概述
MyBatis提供了两级缓存机制:
- 一级缓存:SqlSession级别的缓存,默认开启,作用范围限于同一个SqlSession内
- 二级缓存:Mapper级别的缓存,需要手动配置,多个SqlSession可以共享
// 一级缓存示例
SqlSession session1 = sqlSessionFactory.openSession();
User user1 = session1.selectOne("getUser", 1); // 查询数据库
User user2 = session1.selectOne("getUser", 1); // 从一级缓存获取
session1.close();// 二级缓存示例
SqlSession session2 = sqlSessionFactory.openSession();
User user3 = session2.selectOne("getUser", 1); // 查询数据库
session2.close();SqlSession session3 = sqlSessionFactory.openSession();
User user4 = session3.selectOne("getUser", 1); // 从二级缓存获取
session3.close();
2. 二级缓存工作原理
2.1 缓存结构
MyBatis二级缓存采用装饰器模式设计,核心组件包括:
- Cache接口:定义了缓存的基本操作
- PerpetualCache:基础的缓存实现,使用HashMap存储
- 各种装饰器:如LruCache、FifoCache、ScheduledCache等,提供额外功能
2.2 工作流程
- 查询时先检查二级缓存
- 缓存命中则直接返回结果
- 未命中则查询数据库,并将结果存入二级缓存
- 执行insert/update/delete操作时,清空对应namespace的缓存
3. 二级缓存配置与使用
3.1 全局开启二级缓存
在mybatis-config.xml中配置:
<settings><setting name="cacheEnabled" value="true"/>
</settings>
3.2 Mapper级别配置
在Mapper XML文件中添加<cache>
标签:
<mapper namespace="com.example.mapper.UserMapper"><cache eviction="LRU"flushInterval="60000"size="1024"readOnly="true"/><select id="selectUser" resultType="User" useCache="true">SELECT * FROM user WHERE id = #{id}</select>
</mapper>
3.3 缓存属性详解
-
eviction:缓存回收策略
- LRU - 最近最少使用(默认)
- FIFO - 先进先出
- SOFT - 软引用
- WEAK - 弱引用
-
flushInterval:缓存刷新间隔(毫秒)
-
size:缓存对象数量
-
readOnly:是否只读(true/false)
3.4 注解方式配置
@CacheNamespace(eviction = LruCache.class,flushInterval = 60000,size = 1024,readWrite = true
)
public interface UserMapper {@Select("SELECT * FROM user WHERE id = #{id}")@Options(useCache = true)User selectUser(Integer id);
}
4. 二级缓存的注意事项
4.1 脏读问题
由于二级缓存是跨SqlSession的,在多表关联或分布式环境下容易出现脏读。解决方案:
- 对查询结果变化频率高的表禁用二级缓存
- 使用
<cache-ref>
让关联的Mapper共享同一个缓存空间 - 在更新操作多的场景下慎用
4.2 序列化要求
当readOnly=false时,从缓存中获取的对象是副本,要求对象必须实现Serializable接口。
4.3 缓存失效策略
MyBatis的缓存失效策略较为简单,任何修改操作都会清空整个namespace的缓存,可能导致缓存命中率下降。
5. 高级特性与集成
5.1 自定义缓存实现
MyBatis支持集成第三方缓存库,如Ehcache、Redis等:
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
5.2 缓存刷新策略
可以通过flushCache
属性控制特定语句是否刷新缓存:
<select id="selectUser" resultType="User" flushCache="false">SELECT * FROM user WHERE id = #{id}
</select><update id="updateUser" parameterType="User" flushCache="true">UPDATE user SET name=#{name} WHERE id=#{id}
</update>
5.3 局部缓存禁用
对于某些特定查询可以禁用缓存:
<select id="selectRealTimeData" resultType="Data" useCache="false">SELECT * FROM realtime_data WHERE id = #{id}
</select>
6. 性能优化建议
- 合理设置缓存大小:根据应用内存情况调整size参数
- 选择合适的回收策略:根据数据访问模式选择LRU或FIFO
- 设置适当的刷新间隔:对实时性要求高的数据设置较短的flushInterval
- 监控缓存命中率:通过日志或监控工具评估缓存效果
- 分布式环境考虑:在集群部署时使用Redis等分布式缓存实现
7. 二级缓存 vs 一级缓存
特性 | 一级缓存 | 二级缓存 |
---|---|---|
作用范围 | SqlSession级别 | Mapper级别 |
默认开启 | 是 | 需要手动配置 |
共享性 | 不共享 | 多个SqlSession共享 |
存储结构 | 内存 | 可配置(内存/外部缓存) |
生命周期 | SqlSession结束即销毁 | 可持久化 |
8. 实际应用案例
电商平台商品展示优化
<!-- 商品Mapper配置 -->
<mapper namespace="com.example.mapper.ProductMapper"><cache eviction="LRU"flushInterval="3600000" <!-- 1小时刷新 -->size="5000"readOnly="true"/><!-- 热门商品查询 --><select id="selectHotProducts" resultType="Product" useCache="true">SELECT * FROM products WHERE status = 'ACTIVE' ORDER BY sales_volume DESC LIMIT 100</select>
</mapper><!-- 商品分类Mapper -->
<mapper namespace="com.example.mapper.CategoryMapper"><cache-ref namespace="com.example.mapper.ProductMapper"/>
</mapper>
此配置将:
- 缓存热门商品数据1小时
- 商品分类与商品共享缓存空间
- 使用LRU策略管理缓存
- 只读模式提高读取性能
9. 常见问题解答
Q1:为什么我的二级缓存没有生效?
A1:请检查:
- mybatis-config.xml中cacheEnabled是否为true
- Mapper XML中是否添加了标签
- 是否在不同的SqlSession中测试
- 是否执行了更新操作导致缓存被清空
Q2:如何清空二级缓存?
A2:可以通过代码清空:
sqlSession.clearCache(); // 清空一级缓存
// 清空二级缓存需要获取对应Mapper的Cache对象
Cache cache = sqlSession.getConfiguration().getCache("com.example.mapper.UserMapper");
if (cache != null) {cache.clear();
}
Q3:二级缓存会导致内存溢出吗?
A3:如果缓存对象过多或没有合理设置size参数,确实可能导致OOM。建议:
- 合理设置size限制
- 对于大对象考虑使用SOFT/WEAK回收策略
- 监控缓存内存使用情况
10. 总结
MyBatis二级缓存是提升应用性能的有效工具,但需要根据具体业务场景合理配置。关键点包括:
- 理解二级缓存的工作原理和适用场景
- 掌握各种配置参数及其影响
- 注意缓存一致性问题
- 结合监控不断优化缓存策略
正确使用二级缓存可以显著减少数据库访问,提高系统响应速度,但过度依赖缓存也可能带来一致性问题。希望本文能帮助开发者在性能和一致性之间找到平衡点,构建高效的MyBatis应用。
相关文章:
【MyBatis-7】深入理解MyBatis二级缓存:提升应用性能的利器
在现代应用开发中,数据库访问往往是性能瓶颈之一。作为Java生态中广泛使用的ORM框架,MyBatis提供了一级缓存和二级缓存机制来优化数据库访问性能。本文将深入探讨MyBatis二级缓存的工作原理、配置方式、使用场景以及最佳实践,帮助开发者充分利…...
5.9-selcct_poll_epoll 和 reactor 的模拟实现
5.9-select_poll_epoll 本文演示 select 等 io 多路复用函数的应用方法,函数具体介绍可以参考我过去写的博客。 先绑定监听的文件描述符 int sockfd socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(struc…...
《算法导论(第4版)》阅读笔记:p17-p27
《算法导论(第4版)》学习第 10 天,p17-p27 总结,总计 11 页。 一、技术总结 1. insertion sort (1)keys The numbers to be sorted are also known as the keys(要排序的数称为key)。 第 n 次看插入排序,这次有两个地方感触比较深&#…...

软考错题集
一个有向图具有拓扑排序序列,则该图的邻接矩阵必定为()矩阵。 A.三角 B.一般 C.对称 D.稀疏矩阵的下三角或上三角部分包含非零元素,而其余部分为零。一般矩阵这个术语太过宽泛,不具体指向任何特定性 质的矩阵。对称矩阵…...

T2I-R1:通过语义级与图像 token 级协同链式思维强化图像生成
文章目录 速览摘要1 引言2 相关工作统一生成与理解的 LMM(Unified Generation and Understanding LMM.)用于大型推理模型的强化学习(Reinforcement Learning for Large Reasoning Models.)3 方法3.1 预备知识3.2 语义级与令牌级 CoT语义级 CoT(Semantic-level CoT)令牌级…...

Dockers部署oscarfonts/geoserver镜像的Geoserver
Dockers部署oscarfonts/geoserver镜像的Geoserver 说实话,最后发现要选择合适的Geoserver镜像才是关键,所以所以所以…🐷 推荐oscarfonts/geoserver的镜像! 一开始用kartoza/geoserver镜像一直提示内存不足,不过还好…...
【脑机接口临床】脑机接口手术的风险?脑机接口手术的应用场景?脑机接口手术如何实现偏瘫康复?
脑机接口的应用 通常对脑机接口感兴趣的两类人群,一类是适应症患者 ,另一类是科技爱好者。 1 意念控制外部设备 常见的外部设备有:外骨骼、机械手、辅助康复设备、电刺激设备、电脑光标、轮椅。 2 辅助偏瘫康复或辅助脊髓损伤患者意念控制…...

扩增子分析|微生物生态网络稳定性评估之鲁棒性(Robustness)和易损性(Vulnerability)在R中实现
一、引言 周集中老师团队于2021年在Nature climate change发表的文章,阐述了网络稳定性评估的原理算法,并提供了完整的代码。自此对微生物生态网络的评估具有更全面的指标,自此网络稳定性的评估广受大家欢迎。本系列将介绍网络稳定性之鲁棒性…...
Client 和 Server 的关系理解
client.py 和 server.py 是基于 MCP(Multi-Component Protocol)协议的客户端-服务端架构,二者的关系如下: 1. 角色分工 server.py:服务端,负责注册和实现各种“工具函数”(如新闻检索、情感分…...

【含文档+PPT+源码】基于微信小程序的社区便民防诈宣传系统设计与实现
项目介绍 本课程演示的是一款基于微信小程序的社区便民防诈宣传系统设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套…...
Kafka的核心组件有哪些?简要说明其作用。 (Producer、Consumer、Broker、Topic、Partition、ZooKeeper)
Kafka 核心组件解析 1. 基础架构图解 ┌─────────┐ ┌─────────┐ ┌─────────┐ │Producer │───▶ │ Broker │ ◀─── │Consumer │ └─────────┘ └─────────┘ └────────…...
Java中对象集合转换的优雅实现【实体属性范围缩小为vo】:ListUtil.convert方法详解
1.业务场景 在开发电商系统时,我们经常需要处理订单信息的展示需求。例如:订单详情页需要显示退款信息列表,而数据库中存储的RefundInfo实体类包含敏感字段,直接返回给前端存在安全风险。此时就需要将RefundInfo对象集合转换为Or…...

【MySQL】存储引擎 - ARCHIVE、BLACKHOLE、MERGE详解
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...

代码随想录第41天:图论2(岛屿系列)
一、岛屿数量(Kamacoder 99) 深度优先搜索: # 定义四个方向:右、下、左、上,用于 DFS 中四向遍历 direction [[0, 1], [1, 0], [0, -1], [-1, 0]]def dfs(grid, visited, x, y):"""对一块陆地进行深度…...
Vue插槽(Slots)详解
文章目录 1. 插槽简介1.1 什么是插槽?1.2 为什么需要插槽?1.3 插槽的基本语法 2. 默认插槽2.1 什么是默认插槽?2.2 默认插槽语法2.3 插槽默认内容2.4 默认插槽实例:创建一个卡片组件2.5 Vue 3中的默认插槽2.6 默认插槽的应用场景 …...
中国古代史1
朝代歌 三皇五帝始,尧舜禹相传。 夏商与西周,东周分两段。 春秋和战国,一统秦两汉。 三分魏蜀吴,二晋前后延。 南北朝并立,隋唐五代传。 宋元明清后,皇朝至此完。 原始社会 元谋人,170万年前…...
vue +xlsx+exceljs 导出excel文档
实现功能:分标题行导出数据过多,一个sheet表里表格条数有限制,需要分sheet显示。 步骤1:安装插件包 npm install exceljs npm install xlsx 步骤2:引用包 import XLSX from xlsx; import ExcelJS from exceljs; 步骤3&am…...
nginx之proxy_redirect应用
一、功能说明 proxy_redirect 是 Nginx 反向代理中用于修改后端返回的响应头中 Location 和 Refresh 字段的核心指令,主要解决以下问题:协议/地址透传错误:当后端返回的 Location 包含内部 IP、HTTP 协议或非标准端口时,需修正为…...
在 Flink + Kafka 实时数仓中,如何确保端到端的 Exactly-Once
在 Flink Kafka 构建实时数仓时,确保端到端的 Exactly-Once(精确一次) 需要从 数据消费(Source)、处理(Processing)、写入(Sink) 三个阶段协同设计,结合 Fli…...
Qt 中基于 spdlog 的高效日志管理方案
在开发 Qt 应用程序时,日志记录是一项至关重要的功能,它能帮助我们追踪程序的运行状态、定位错误和分析性能。本文将介绍如何在 Qt 项目中集成 spdlog 库,并封装一个简单易用的日志管理类 QtLogger,实现高效的日志记录和管理。 为什么选择 spdlog? spdlog 是一个快速、头…...

VUE CLI - 使用VUE脚手架创建前端项目工程
前言 前端从这里开始,本文将介绍如何使用VUE脚手架创建前端工程项目 1.预准备(编辑器和管理器) 编辑器:推荐使用Vscode,WebStorm,或者Hbuilder(适合刚开始练手使用),个…...
Linux 学习笔记2
Linux 学习笔记2 一、定时任务调度操作流程注意事项 二、磁盘分区与管理添加新硬盘流程磁盘管理命令 三、进程管理进程操作命令服务管理(Ubuntu) 四、注意事项 一、定时任务调度 操作流程 创建脚本 vim /path/to/script.sh # 编写脚本内容设置可执行权…...
JS DOM操作与事件处理从入门到实践
对于前端开发者来说,让静态的 HTML 页面变得生动、可交互是核心技能之一。实现这一切的关键在于理解和运用文档对象模型 (DOM) 以及 JavaScript 的事件处理机制。本文将带你深入浅出地探索 DOM 操作的奥秘,并掌握JavaScript 事件处理的方方面面。 目录 …...

Java EE初阶——初识多线程
1. 认识线程 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。 基本概念:一个进程可以包含多个线程,这些线程共享进程的资源,如内存空间、文件描述符等,但每个线程都有自己独…...

如何删除网上下载的资源后面的文字
这是我在爱给网上下载的音效资源,但是发现资源后面跟了一大段无关紧要的文本,但是修改资源名称后还是有。解决办法是打开属性然后删掉资源的标签即可。...
深入解析C++11委托构造函数:消除冗余初始化的利器
一、传统构造函数的痛点 在C11之前,当多个构造函数需要执行相同的初始化逻辑时,开发者往往面临两难选择: class DataProcessor {std::string dataPath;bool verbose;int bufferSize; public:// 基础版本DataProcessor(const std::string&am…...
Python中的事件循环是什么?事件是怎么个事件?循环是怎么个循环
在Python异步编程中,事件循环(Event Loop)是核心机制,它通过单线程实现高效的任务调度和I/O并发处理。本文将从事件的定义、循环的运行逻辑以及具体实现原理三个维度展开分析。 一、事件循环的本质:协程与任务的调度器…...

FPGA图像处理(5)------ 图片水平镜像
利用bram形成双缓冲,如下图配置所示: wr_flag 表明 buffer0写 还是 buffer1写 rd_flag 表明 buffer0读 还是 buffer1读 通过写入逻辑控制(结合wr_finish) 写哪个buffer ;写地址 进而控制ip的写使能 通过状态缓存来跳转buffer的…...
[python] 类
一 介绍 具有相同属性和行为的事物的通称,是一个抽象的概念 三要素: 类名,属性,方法 格式: class 类名: 代码块 class Pepole:name "stitchcool"def getname(self):return self.name 1.1 创建对象(实例化) 格式: 对象名 类名() p1 Pepole()…...

day21python打卡
知识点回顾: LDA线性判别PCA主成分分析t-sne降维 还有一些其他的降维方式,也就是最重要的词向量的加工,我们未来再说 作业: 自由作业:探索下什么时候用到降维?降维的主要应用?或者让ai给你出题&…...