什么是延迟加载
- MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。延迟加载可以有效的减少数据库压 力。
- Mybatis的延迟加载,需要通过resultMap标签中的association和collection子标签才能演示成功。
- Mybatis的延迟加载,也被称为是嵌套查询,对应的还有嵌套结果的概念,可以参考一对多关联的案例。
- 注意:MyBatis的延迟加载只是对关联对象的查询有延迟设置, 对于主加载对象都是直接执行查询语句的。
关联查询分类
MyBatis根据对关联对象查询的select语句的执行时机,分为三种类型:直接加载、 侵入式加载与深度延迟加载
- 直接加载: 执行完对主加载对象的select语句,马上执行对关联对象的select查询。
- 侵入式延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。但当要访问主加载对象的某个属性(该属性不是关联对象的属性)时,就会马 上执行关联对象的select查询。
- 深度延迟: 执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关 联对象的详情时,才会执行对关联对象的select查询。
代码案例:
本篇基于一对多查询中的第二种分词查询,代码无须改动,只做配置修改
application.yml配置
侵入性延迟加载
mybatis:
configuration:
# 全局启用或者禁用延迟加载 默认关闭
lazy-loading-enabled: true
# 侵入性延迟加载开关
aggressive-lazy-loading: true
深度延迟加载
mybatis:
configuration:
# 全局启用或者禁用延迟加载 默认关闭
lazy-loading-enabled: true
# 侵入性延迟加载开关
aggressive-lazy-loading: false
# 以下方法会触发延迟加载,不配置的时候默认为"equals", "clone", "hashCode", "toString"
# lazy-load-trigger-methods: equals
编写单元测试
@SpringBootTest
class KkbStudyApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void test3() {
UserExt query = userMapper.query2(2);
System.err.println(query.getName());
System.err.println(query);
}
}
控制台输出
2021-05-21 11:11:01.710 DEBUG 24008 --- [ main] c.e.kkbstudy.mapper.UserMapper.query2 : ==> Preparing: select `user`.id,`user`.name from `user`where `user`.id = ?
2021-05-21 11:11:01.741 DEBUG 24008 --- [ main] c.e.kkbstudy.mapper.UserMapper.query2 : ==> Parameters: 2(Integer)
2021-05-21 11:11:01.813 DEBUG 24008 --- [ main] c.e.kkbstudy.mapper.UserMapper.query2 : <== Total: 1
李四
2021-05-21 11:11:01.818 DEBUG 24008 --- [ main] c.e.k.mapper.OrderMapper.simpleQuery : ==> Preparing: select id,user_id,`desc` from `order` where user_id = ?
2021-05-21 11:11:01.819 DEBUG 24008 --- [ main] c.e.k.mapper.OrderMapper.simpleQuery : ==> Parameters: 2(Integer)
2021-05-21 11:11:01.820 DEBUG 24008 --- [ main] c.e.k.mapper.OrderMapper.simpleQuery : <== Total: 2
[Order(id=1, userId=2, desc=第一笔订单), Order(id=2, userId=2, desc=第二笔订单)]
可以看到我们第一次去输出UserExt中的用户对象的时候并没有去触发查询order,直到我们去输出UserExt对象调用toString()方法的时候,才触发延迟加载,去查询了用户ID为2的订单对象。最终封装到了我们的UserExt对象中。
N+1问题
- 深度延迟加载的使用会提升性能。
- 如果延迟加载的表数据太多,此时会产生N+1问题,主信息加载一次算1次,而从信息是会根据主信息传递过来的条件,去查询从表多次。