当前位置: 首页 > 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.xdnf.cn/news/1384129.html

相关文章:

  • LaunchScreen是啥?AppDelegate是啥?SceneDelegate是啥?ContentView又是啥?Main.storyboard是啥?
  • DoIP路由激活报文
  • 玄机靶场 | 第九章-blueteam 的小心思3
  • day083-Filebeat数据采集案例与Kibana可视化应用
  • 创建uniApp小程序项目vue3+ts+uniapp
  • Docker 核心技术:Union File System
  • ros2与gazebo harmonic机械臂仿真项目Moveit2YoloObb的优化
  • 有限与无限的游戏 之感
  • Rust 登堂 之 类型转换(三)
  • CnSTD+CnOCR的联合使用
  • 虚拟机逃逸攻防演练技术文章大纲
  • 编写TreeMap自定义排序的插曲
  • InstructGPT:使用人类反馈训练语言模型以遵循指令
  • 文本处理与模型对比:BERT, Prompt, Regex, TF-IDF
  • 在angular20中使用monaco-editor
  • 任天堂NDS中文游戏ROM精选毕业整合包整理分享! +NDS模拟器
  • Maven 编译打包一个比较有趣的问题
  • 机器视觉学习-day08-图像缩放
  • 企业如何管理跨多个系统的主数据?
  • Maven核心用法
  • 3446. 按对角线进行矩阵排序
  • [数组]27.移除元素
  • Kafka02-集群选主
  • 【Node.js从 0 到 1:入门实战与项目驱动】2.4 开发工具推荐(VS Code 、IDEA及插件、终端工具、调试工具)
  • 配置 Gitlab 和 Elasticsearch/Zoekt 并使用 Docker Metadata 数据库、Camo 代理服务
  • AI 如何 “看见” 世界?计算机视觉(CV)的核心技术:图像识别、目标检测与语义分割
  • Day16_【机器学习常见术语】
  • 宋红康 JVM 笔记 Day08|堆
  • MySQL 中 tinyint(1)、int(11)、bigint(20) 的数字到底是什么意思?
  • Vibe Coding 概念提出者 AndrejKarpathy 谈强化学习。