MyBatis中的延迟加载策略
一:延迟加载
1.了解延迟加载:
延迟加载又叫懒加载,也叫按需加载,也就是说先加载主信息,需要的时候,再去加载从信息。代码中有查询语句,当执行到查询语句时,并不是马上去DB中查询,而是根据设置的延迟策略将查询向后推迟。
2.延迟加载的好处:
先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,减轻数据库服务器的压力,因为查询单表要比关联查询多张表速度要快。
3.如何开启MyBatis的延迟加载:
Mybatis的延迟加载功能默认是关闭的
需要在mybatis-config.xml(mybatis的核心配置)文件中通过setting标签配置来开启延迟加载功能
<settings>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--value为true时为侵入式延迟加载,false为深入式延迟加载-->
<setting name="aggressiveLazyLoading" value="true"/>
</settings>
4.延迟加载的resultMap
4.1当在resultMao中使用过association或者collection进行关系映射之后才能使用MyBatis的延迟加载策略
4.2 延迟加载需要两个select语句来完成
关联对象的查询与主加载对象的查询必须是分别进行的select语句,不能是使用多表连接所进行的select查询。因为,多表连接查询,实质是对一张表的查询,对由多个表连接后形成的一张表的查询。会一次性将多张表的所有信息查询出来。
5.关联对象的加载时机
MyBatis的延迟加载只是对关联对象的查询有延迟设置,对于主加载对象都是直接执行查询语句的。
1.直接加载
即执行对象的select语句,完成对主加载马上执行对关联对象的select查询。
2.侵入式延迟加载(aggressiveLazyLoading) 也可看做立即加载
执行对主加载对象的查询时,不会执行对关联对象的查询。但是当要访问主加载对象的详情时马上执行对关联对象的select查询。即对关联对象的执行查询,侵入到了主加载对象的访问详情中。也可理解为:将关联对象的详情侵入到主加载对象的详情中去,即将关联对象的详情作为主加载对象的一部分出现了!
3.深度延迟加载
执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关联对象的详情时,才会执行对关联对象的select查询。
六:延迟加载测试案例
1.将俩张表的关联关系在实体类中体现出来,也就是在一张表中添加另一张表的对象
2.创建Dao层的方法一级Mapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.yjc.dao.ISmbmsDao"> <resultMap id="SmbmsProviderResult" type="SmbmsBill"> <collection property="smbmsProvider" ofType="SmbmsProvider" select="getSmbmsProvider" column="providerId"> </collection> </resultMap> <select id="getSmbmsBillList" resultMap="SmbmsProviderResult"> select * from smbms.smbms_bill where id=#{id} </select> <select id="getSmbmsProvider" resultType="SmbmsProvider"> select * from smbms.smbms_provider where id=#{providerId} </select> </mapper>
3.测试类
public class YiTest { public static void main(String[] args) { SqlSession session = SqlSessionUtils.getSession(); ISmbmsDao mapper = session.getMapper(ISmbmsDao.class); SmbmsBill smbmsBillList = mapper.getSmbmsBillList(1); } }
当没有开启延迟加载策略的时候,MyBatis默认是直接加载当执行上面的测试类的时候结果如下
1.直接加载
如上图所示,一共向数据库发送了两条请求,此时我们开启侵入式延迟加载 然后再执行上面的测试
2.侵入式延迟加载
<settings> <!--开启延迟加载--> <setting name="lazyLoadingEnabled" value="true"/> <!--value为true时为侵入式延迟加载,false为深入式延迟加载--> <setting name="aggressiveLazyLoading" value="true"/> </settings>
此时测试的结果如下
由于我们只进行了查询操作,并没有对查询出来的主对象进行操作(访问改对象的属性或及方法)所以此时并没有进行加载关联的查询
那么我们接下来访问一些主对象的一些属性
结果如下
这就是侵入式延迟加载的效果,当对主加载对象进行操作的时候就会去加载关联对象(向数据库发送请求)
3.深度式延迟加载
在核心配置文件中修改setting节点
<!--开启延迟加载--> <setting name="lazyLoadingEnabled" value="true"/> <!--value为true时为侵入式延迟加载,false为深入式延迟加载--> <setting name="aggressiveLazyLoading" value="false"/>
修改完成之后继续执行上次执行的测试方法
从上面的结果中可以看到同样的测试方法,开始深度式延迟之后只向数据库发送了一次请求,这是因为我们在测试类中只访问了主对象的属性,并没有使用关联对象的任何属性
那么接下来我们修改测试类,在测试类中添加对关联对象的访问
public class YiTest { public static void main(String[] args) { SqlSession session = SqlSessionUtils.getSession(); ISmbmsDao mapper = session.getMapper(ISmbmsDao.class); SmbmsBill smbmsBillList = mapper.getSmbmsBillList(1); //获取关联对象中的proName属性 System.out.println(smbmsBillList.getSmbmsProvider().getProName()); } }
测试结果如下
当我们访问关联对象时候就发送请求进行对关联关系的加载,这就是MyBatis中的深度式延迟加载策略
以上就是我对MyBatis的延迟加载机制的理解,有不足之处还请指出
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)