news 2026/4/16 12:05:54

第9章:MyBatis多级缓存和懒加载

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第9章:MyBatis多级缓存和懒加载

文章目录

  • 第9章:MyBatis多级缓存和懒加载
    • 一级缓存
    • 二级缓存怎么使用
    • 懒加载

第9章:MyBatis多级缓存和懒加载

一级缓存

什么是缓存?

一级缓存核心定位

  • 一级缓存是 MyBatis 内置的默认缓存机制,无需手动配置,默认开启。
  • 作用域:
    • 仅限当前SqlSession(数据库会话)
    • 不同 SqlSession 之间的缓存相互隔离。
  • 缓存介质:
  • 内存(基于HashMap存储),缓存键由Mapper ID + SQL 语句 + 参数 + 分页信息 + 环境信息组成。

核心价值:

  • 减少同一 SqlSession 内重复查询的数据库交互,提升查询性能。

  • 一级缓存生效与失效条件

    场景类型生效条件失效条件
    核心前提同一 SqlSession、相同 Mapper ID+SQL + 参数不同 SqlSession、SQL / 参数 / 分页不同
    数据库操作影响未执行增删改(insert/update/delete)操作执行增删改操作(自动清空当前 SqlSession 缓存)
    手动干预未调用clearCache()close()方法调用sqlSession.clearCache()(手动清空)、sqlSession.close()(关闭会话)
    配置影响默认配置(无特殊禁用)全局配置localCacheScope=STATEMENT(禁用一级缓存)

一级缓存工作流程

一级缓存核心特性:

@Service@Slf4jpublicclassUserService{@AutowiredprivateSqlSessionTemplatesqlSessionTemplate;/*一级缓存 有效的访问*/publicvoidfirstCache(){SqlSessionFactorysqlSessionFactory=sqlSessionTemplate.getSqlSessionFactory();SqlSessionsqlSession=sqlSessionFactory.openSession();UserMapperuserMapper=sqlSession.getMapper(UserMapper.class);Useruser=userMapper.selectById(1);log.info("第一次查询结果:{}",user);Useruser2=userMapper.selectById(1);log.info("第二次查询结果:{}",user2);log.info("两个user是否是同一个对象:{}",user==user2);sqlSession.close();}/*一级缓存 失效的访问*/publicvoidfirstCacheInvalidation(){SqlSessionFactorysqlSessionFactory=sqlSessionTemplate.getSqlSessionFactory();SqlSessionsqlSession=sqlSessionFactory.openSession();UserMapperuserMapper=sqlSession.getMapper(UserMapper.class);Useruser=userMapper.selectById(1);log.info("第一次查询结果:{}",user);/*执行 写的操作*/user.setAge(18);introws=userMapper.update(user);log.info("执行写的操作,影响行数:{}",rows);//清空缓存// sqlSession.clearCache();Useruser2=userMapper.selectById(1);log.info("第二次查询结果:{}",user2);log.info("两个user是否是同一个对象:{}",user==user2);sqlSession.close();}}

二级缓存怎么使用

核心概念界定

二级缓存核心定位

  • 二级缓存(Mapper 级缓存)是 MyBatis 的跨 SqlSession 缓存
    • 作用域为同一个 Mapper(namespace)
    • 不同 SqlSession 可共享缓存数据。
  • 缓存介质:
    • 默认内存(HashMap),支持自定义(如 Redis等第三方缓存)
  • 核心价值:
    • 减少不同 SqlSession 间重复查询的数据库交互
    • 适用于查询频率高、修改频率低的数据(如字典表、配置表)
  • 依赖条件:实体类需实现Serializable接口,需手动开启

一级缓存与二级缓存核心区别

对比维度一级缓存(SqlSession 级)二级缓存(Mapper 级)
作用域单个 SqlSession同一个 Mapper(namespace)
共享性不可跨 SqlSession 共享可跨 SqlSession 共享
开启方式默认开启,无需配置需全局配置 + Mapper 配置手动开启
实体类要求无强制序列化要求必须实现 Serializable 接口
失效触发同一 SqlSession 内增删改、clearCache ()对应 Mapper 内增删改操作、缓存过期等
适用场景单会话内重复查询多会话共享高频查询数据

二级缓存工作流程

二级缓存开启条件(三步缺一不可)

  • 全局配置开启:
    • springBoot 配置文件中设置cacheEnabled=true
  • Mapper 级开启:
    • 在 Mapper XML 中添加<cache/>标签
  • 实体类序列化:
    • 缓存的实体类必须实现java.io.Serializable接口(避免序列化异常)。

二级缓存配置详解

mybatis:configuration:cache-enabled:true# 启用二级缓存
<!-- Mapper XML 中配置二级缓存 --><mappernamespace="com.example.mapper.UserMapper"><!-- 开启二级缓存配置 --><cacheeviction="LRU"flushInterval="60000"size="512"readOnly="true"/><selectid="selectUserById"parameterType="long"resultType="User"useCache="true">SELECT * FROM user WHERE id = #{id}</select></mapper>

二级缓存属性详解表

属性可选值默认值说明
evictionLRU/FIFO/SOFT/WEAKLRU缓存回收策略
flushInterval毫秒数缓存刷新间隔
size正整数1024缓存引用数量
readOnlytrue/falsefalse是否只读
blockingtrue/falsefalse是否使用阻塞缓存

常见的缓存回收策略:

策略缩写全称策略说明
LRULeast Recently Used移除最长时间未被使用的对象(默认策略)。
FIFOFirst In First Out按对象进入缓存的顺序来移除它们。
SOFTSoft Reference基于垃圾回收器状态和软引用规则来移除对象。
WEAKWeak Reference更积极地基于垃圾收集器状态和弱引用规则移除对象。
// 使用二级缓存需要实体类实现Serializable接口@Data@NoArgsConstructor@AllArgsConstructorpublicclassUserimplementsSerializable{privateLongid;privateStringusername;privateStringemail;privateIntegerage;privateDatecreateTime;privateDateupdateTime;// 关联对象也需要序列化}
// 二级缓存服务演示@Service@Slf4jpublicclassSecondLevelCacheService{@AutowiredprivateUserMapperuserMapper;/** * 演示二级缓存跨SqlSession共享 */publicvoiddemonstrateSecondLevelCache(){Useruser1=userMapper.selectUserById(1L);log.info("SqlSession查询: {}",user1);// 重新调用方法模拟第二个SqlSession(实际应用中可能是另一个请求)log.info("=== 二级缓存演示结束 ===");}/** * 二级缓存失效场景 */publicvoiddemonstrateSecondLevelCacheInvalidation(){// 执行更新操作Useruser1=newUser();user1.setId(1L);user1.setEmail("newemail@example.com");intupdateCount=userMapper.updateUser(user1);log.info("更新影响行数: {}",updateCount);}}

懒加载

懒加载核心定位

  • 懒加载(延迟加载)是 MyBatis 关联查询的性能优化机制
    • 指查询主对象时,不立即加载关联对象
    • 而是在首次访问关联对象时才触发查询xa
  • 对立概念:
    • 立即加载(默认行为),查询主对象时同时加载所有关联对象
  • 核心价值:
    • 避免不必要的关联查询,
    • 减少数据库压力
    • 如仅需查询用户基本信息时,无需加载其所有订单
  • 适用场景:
    • 一对一、一对多、多对多关联查询,且关联数据不总是需要使用

懒加载与立即加载对比

懒加载开启条件

  • 全局配置开启延迟加载:
    • lazyLoadingEnabled=true(默认 false)
  • 关闭积极加载:
    • aggressiveLazyLoading=false
    • SpringBoot 2.x+ 已默认关闭,确保按需加载
  • 关联标签配置(可选):
    • associationcollection标签添加fetchType="lazy"(优先级高于全局配置)

懒加载配置详解

mybatis:configuration:lazy-loading-enabled:true# 开启全局懒加载aggressive-lazy-loading:false# 关闭积极加载(按需加载)map-underscore-to-camel-case:true

懒加载实战案例

<!-- 基础用户结果映射(不包含关联对象) --><resultMapid="BaseUserMap"type="com.example.entity.User"><idcolumn="user_id"property="userId"/><resultcolumn="user_name"property="userName"/><resultcolumn="card_id"property="cardId"/></resultMap><!-- 嵌套查询结果映射:使用子查询方式加载关联对象 --><resultMapid="UserWithIdCardNestedQueryMap"type="com.example.entity.User"extends="BaseUserMap"><associationproperty="idCard"column="card_id"select="com.example.mapper.IdCardMapper.selectById"javaType="com.example.entity.IdCard"fetchType="lazy"/></resultMap><!-- 嵌套查询方式:查询用户(触发子查询加载身份证) --><selectid="selectUserWithIdCardNested"resultMap="UserWithIdCardNestedQueryMap">SELECT user_id, user_name, card_id FROM t_user WHERE user_id = #{userId}</select>

懒加载最佳实践

  • 适用场景:

    • 关联数据量大,且不经常使用
    • 需要快速响应的列表查询
    • 移动端应用,减少数据传输
  • 注意事项:
    ) -->

    SELECT
    user_id,
    user_name,
    card_id
    FROM t_user
    WHERE user_id = #{userId}

懒加载最佳实践 - 适用场景: - 关联数据量大,且不经常使用 - 需要快速响应的列表查询 - 移动端应用,减少数据传输 - 注意事项: - 注意 N+1 查询问题
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 21:57:48

好写作AI:开题报告憋不出?让AI三秒给你“骨架”,你来注入灵魂!

各位对着“开题报告”空白文档&#xff0c;陷入“开头即结局”式精神内耗的同学们&#xff0c;是不是觉得&#xff1a;明明有个模糊的想法&#xff0c;可一旦要落笔写成“研究背景”、“研究意义”、“技术路线”……大脑就瞬间宕机&#xff0c;感觉比写正文还难&#xff1f;别…

作者头像 李华
网站建设 2026/3/27 6:14:44

走向开放硅:Baochip-1x 的 RISC-V MCU 架构与工程实践

在开源硬件领域&#xff0c;一款既有芯片级代码又可用于工程实践的项目并不多见。baochip-1x 就是这样一个鲜明例子&#xff1a;它是一个围绕 RISC-V 架构、绝大部分开源逻辑描述的 MCU&#xff08;微控制器&#xff09;项目。该项目的代码托管在 GitHub 上&#xff0c;并提供部…

作者头像 李华
网站建设 2026/4/11 23:32:23

最新谷歌商店安装教程(保姆级),谷歌三件套问题汇总!闪退,无法登录等各手机解决方案

一定要看清楚&#xff0c;很多大佬最后失败就是没掌握方法。 重要提醒 这里给大家汇总谷歌三件套的版本合集&#xff0c;应该是目前最全面的谷歌三件套版本汇总了。 在安装的时候一定要试一下不同版本的谷歌服务框架&#xff01; 在安装的时候一定要试一下不同版本的谷歌服务…

作者头像 李华
网站建设 2026/4/15 18:53:41

【大数据毕设源码分享】django基于协同过滤算法+数据可视化的经济型酒店推荐系统大数据的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/7 22:01:40

为什么我不愿意用Anaconda了?

我记得从我开始读本科接触Python开始&#xff0c;就一直被各种博客灌输Anaconda省事、方便的思想&#xff0c;所以每次Anaconda更新我都会第一时间去更新&#xff0c;但近几年我发现网上对Anaconda的意见增多&#xff0c;不少小伙伴开始自己配置Python了&#xff0c;或者改用mi…

作者头像 李华