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

MyBatis延迟加载

文章目录

  • 1. 延迟加载的定义
  • 2. 延迟加载的原理
  • 3. 延迟加载的方式
    • 直接加载
    • 侵入式延迟加载
    • 深度延迟加载
  • 总结

1. 延迟加载的定义

延迟加载是MyBatis中一种按需查询的机制。当执行主查询获取到主对象后,对于主对象中的关联对象,并不会立即执行关联查询,而是在真正访问关联对象时才会触发对应的SQL语句进行查询。
这种机制的核心思想是"用时再取"。比如查询一个用户信息时,如果该用户关联了多个订单,延迟加载不会立即查询出所有订单数据,而是等到代码中真正调用获取订单列表的方法时,才会执行查询订单的SQL语句。

好处:
延迟加载能够有效避免不必要的数据库查询,减少数据库的负载压力,提高应用程序的整体性能。特别是在处理大量数据或者复杂关联关系时,延迟加载能够显著优化查询效率。

2. 延迟加载的原理

MyBatis的延迟加载基于动态代理技术实现。当MyBatis执行主查询创建结果对象时,会判断是否需要进行延迟加载。如果需要延迟加载,MyBatis会为该对象创建一个代理对象,而不是直接返回原始对象。这个代理对象会拦截对关联属性的访问操作。当程序代码访问需要延迟加载的属性时,代理对象会检测到这个调用,然后执行以下步骤:

  1. 首先,代理对象会根据配置的select语句和column参数,构造对应的SQL查询。
  2. 然后,代理对象会使用原始的SqlSession执行这个SQL查询,获取关联数据。
  3. 接着,将查询结果设置到目标属性中,最后返回查询到的数据给调用方。

3. 延迟加载的方式

MyBatis中的延迟加载根据加载时机和触发条件的不同,可以分为三种主要方式:

直接加载

直接加载是指在执行主查询的同时立即执行关联查询,一次性获取所有相关数据。这种方式不存在延迟,所有数据在第一次查询时就全部加载完成。

侵入式延迟加载

侵入式延迟加载是指当访问主对象的任意属性时,都会触发所有延迟加载属性的查询。这种方式对主对象的访问比较"敏感",只要触碰到对象就会加载所有关联数据。

<configuration><settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="true"/></settings>
</configuration>

当aggressiveLazyLoading设置为true时,启用侵入式延迟加载。在这种模式下,如果访问了主对象的任何属性(包括调用toString()、equals()等方法),MyBatis会立即加载该对象所有配置了延迟加载的关联属性。

Order order = orderMapper.selectById(1);
System.out.println(order.getOrderNo()); // 这行代码会触发所有延迟加载

深度延迟加载

深度延迟加载是最精确的延迟加载方式,只有在真正访问某个特定的关联属性时,才会触发该属性对应的查询。这种方式提供了最细粒度的控制。

<configuration><settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/><setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode"/></settings>
</configuration>

当aggressiveLazyLoading设置为false时,启用深度延迟加载。在这种模式下,只有直接访问关联属性时才会触发对应的查询。lazyLoadTriggerMethods用于指定哪些方法调用会触发延迟加载。

<resultMap id="UserResultMap" type="User"><id column="id" property="id"/><result column="username" property="username"/><collection property="orders" select="com.example.mapper.OrderMapper.selectByUserId"column="id" fetchType="lazy"/>
</resultMap>

使用示例:

User user = userMapper.selectById(1);
System.out.println(user.getUsername()); // 不会触发订单查询
System.out.println(user.getId()); // 不会触发订单查询List<Order> orders = user.getOrders(); // 只有这行代码才会触发订单查询

深度延迟加载是最常用的方式,避免了不必要的数据库查询,同时保持了代码的清晰性。

总结

MyBatis延迟加载是一种重要的性能优化机制,通过按需查询的方式减少数据库访问压力。延迟加载基于动态代理技术实现,当访问关联属性时才触发相应的SQL查询。根据触发条件和加载时机的不同,延迟加载分为三种方式:直接加载在主查询时立即获取所有数据,侵入式延迟加载在访问主对象任意属性时触发所有关联查询,而深度延迟加载只在访问特定关联属性时触发对应查询。

http://www.dtcms.com/a/354604.html

相关文章:

  • 云计算学习100天-第29天
  • Node.js 的模块化规范是什么?CommonJS 和 ES6 模块有什么区别?
  • Python DELL Logo
  • day1 ———C++———变量和字符串的使用
  • AI驱动企业数字化转型:解码未来三年的智能化变革密码
  • STAGEWISE实战指南:从集成到使用的完整解决方案
  • AI在商业领域的多元应用:从写作助手到精准运营,解锁AI商业工具新价值
  • 流程控制语句(3)
  • 操作系统中的死锁是什么意思
  • 农行广西区分行携手广西专精特新商会共探金融赋能专精特新企业新路径
  • 用KPI导航数字化转型:制造企业如何科学评估系统上线成效
  • 流程控制语句(2)
  • Java网络编程(UDP, TCP, HTTP)
  • 【Linux基础知识系列:第一百一十五篇】使用gzip与bzip2进行压缩
  • 从首次测试到采购40个机器人:Junior kühlk如何自动化协作机械臂矩阵
  • Linux学习-基于TCP实现群聊
  • 医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(三)
  • windows下查看别的服务器的端口是否通
  • [光学原理与应用-319]:激光器光路设计的主要输出文件的形式和内容
  • 解构与重构:“真人不露相,露相非真人” 的存在论新解 —— 论 “真在” 的行为表达本质
  • 一文读懂:用PyTorch从零搭建一个Transformer模型
  • (LeetCode 每日一题) 3446. 按对角线进行矩阵排序(矩阵、排序)
  • 读大语言模型08计算基础设施
  • GeoScene Maps 完整入门指南:从安装到实战
  • 《Explanation of Adaptive Platform Design》详细解读
  • 同一个栅格数据,为何在QGIS和ArcGIS Pro中打开后显示的数值范围不同?
  • redis单哨兵模式
  • 单元测试到底是什么?该怎么做?
  • 破译心智密码:神经科学如何为下一代自然语言处理绘制语义理解的蓝图
  • 【后端】微服务后端鉴权方案