news 2026/6/15 7:15:55

第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/6/10 16:44:13

JMeter压力测试,如何“温柔”地搞垮你的服务器?

大家好&#xff0c;我是小悟。 一、JMeter是何方神圣&#xff1f; 假如&#xff0c;你就是那个在黑色星期五早上8点冲向超市大门的购物狂魔&#xff0c;而JMeter就是你那支可以瞬间克隆出1000个你的神奇部队&#xff01;它不是什么神秘的黑客工具&#xff0c;而是Apache家族里…

作者头像 李华
网站建设 2026/6/15 12:22:18

驾校管理|基于springboot + vue驾校管理系统(源码+数据库+文档)

驾校管理 目录 基于springboot vue驾校管理系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue驾校管理系统 一、前言 博主介绍&#xff1a;✌️大…

作者头像 李华
网站建设 2026/5/21 13:11:52

数组算法-双指针

首先&#xff0c;双指针法&#xff0c;本质是通过两个索引&#xff08;指针&#xff09; 在数组上移动&#xff0c;用一次遍历&#xff08;O (n) 时间复杂度&#xff09;替代嵌套循环&#xff08;O (n)&#xff09;&#xff0c;核心是用空间换时间&#xff08;仅额外使用两个变…

作者头像 李华
网站建设 2026/6/15 13:26:24

小白必看:免费域名申请避坑指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个交互式新手向导&#xff1a;1.解释域名/DNS等基础概念 2.分步动画演示注册流程 3.高亮显示关键表单字段 4.内置模拟练习环境 5.提供术语词典。使用React开发响应式界面&am…

作者头像 李华
网站建设 2026/6/7 6:44:54

零基础理解哈夫曼树:从原理到实现

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个交互式哈夫曼树学习工具。功能&#xff1a;1. 分步动画演示建树过程&#xff1b;2. 可调节的模拟数据输入&#xff1b;3. 实时显示编码结果&#xff1b;4. 简单的练习题和…

作者头像 李华