Mybatis中的sql-xml延迟加载机制
hi,我是阿昌
,今天记录一下关于Mybatis中的sql-xml延迟加载机制
一、前言
首先mybatis技术本身就不多介绍,说延迟加载机制之前,那要先知道2个概念:
- 主查询对象
- 关联对象
假设咱们现在有2张表,一张是item表,一张是sku表,对应关系是1对多的关系
如果在这个条件下,我们要查询item表的信息且对应item下的sku的数据:
public class ItemDO {private Long id;private String numIid;private List<String> skuIdList;}
- 主查询对象:itemDO
- 关联对象:itemDO对象中的skuIdList
二、正文
1、延迟加载
那什么是延迟加载,那就是懒加载、惰性加载;
在mybatis中延迟加载一般用用1对1或1对多的联合查询
中
如果开启了延迟加载,mybatis则只会对主对象进行查询,而只有在主查询对象的关联对象的属性被调用时,mybatis才会执行关联对象的查询;
在上面的item&sku场景下,我们如果只访问item对象时并不会马上返回其关联对象skuList的值,只有在该item的skuList属性被访问时,才会去数据库中查询sku列表的信息
2、如何开启
在mybatis中可以通过lazyLoadingEnabled
的属性值来开启延迟加载设置;
aggressiveLazyLoading
的属性值为false来全局开启延迟加载。
那也可以在Mapper的映射文件中,在collection
或associaition
标签的fetchType
属性,来局部的设置延迟加载策略。
其中Mapper文件局部设置的优先级会高于全局的延迟加载策略。
3、代码验证
demo代码如下:
System.out.println("0");List<ItemDO> itemDOList = skuMapper.findAll();System.out.println("1");ItemDO itemDO = itemDOList.get(0);System.out.println(itemDO);System.out.println("2");
3、原理
Mybatis中的延迟加载,是在获取到主对象的结果集之后处理的,他的核心源码在org.apache.ibatis.executor.resultset.DefaultResultSetHandler
中的org.apache.ibatis.executor.resultset.DefaultResultSetHandler#createResultObject(org.apache.ibatis.executor.resultset.ResultSetWrapper, org.apache.ibatis.mapping.ResultMap, org.apache.ibatis.executor.loader.ResultLoaderMap, java.lang.String)
方法,
它的意图很简单,就是为我们的主查询对象生产一个代理对象类并返回。点进去看会发现延迟加载有2个动态代理生成方式:Cglib
和 Javassist
默认使用的是Javassist
动态代理类的实现方法是org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory.EnhancedResultObjectProxyImpl#invoke
,该方法的主要逻辑是判断是否开启延迟加载,如果开启了,就会执行事先储存好的关联对象的查询SQL,将查询的结果通过反射赋值给关联对象。