Mybatis - 延迟加载
2020-04-09 本文已影响0人
zbsong
前两节说到了一对一、一对多和多层级联操作,当多层级联层数太多时,不建议使用级联,会造成复杂度的增加,不利于他人的理解和维护,同时还存在一些劣势,比如有时候并不需要获取所有的数据,,但是级联会多执行几次SQL,将全部关联信息查询出来,这样就会导致执行SQL较多从而导致性能下降。针对这种问题,我们可以使用延迟加载来解决,本节继续使用前两节的demo来演示延迟加载的功能。
- 全局配置
- 修改application.yml 添加延迟加载全局配置
mybatis:
mapper-locations: classpath:mappers/*.xml
configuration:
#开启延迟加载,默认即时加载
lazy-loading-enabled: true
#Mybatis默认是按层级延迟加载的,为true时按层级加载,否则就按我们调用的要求加载
aggressive-lazy-loading: false
#打印日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#指定哪个对象的方法触发一次延迟加载。默认值:equals,clone,hashCode,toString ,可以阻挡不相干的操作触发,实现懒加载
lazy-load-trigger-methods: ""
注意:实体类中如果是使用的lombok,则加上@ToString(doNotUseGetters = true)
- 修改AuthorService,方便查看效果
@Service
public class AuthorService {
@Autowired
private AuthorMapper authorMapper;
public Author getAuthorById(String id) {
Author author = authorMapper.getAuthorById(id);
System.out.println("查询作者信息表数据");
author.getAuthorInformation();
System.out.println("查询作者的主题表数据");
author.getSpecials();
System.out.println("查询作者的文章表数据");
for (int i = 0; i < author.getSpecials().size(); i++) {
author.getSpecials().get(i).getArticles();
}
return author;
}
}
测试
在第一步打个断点,然后调用AuthorService的getAuthorById方法获取作者信息 image.png image.png第一步执行结束后可以看到级联的authorInformation和specials信息没有查询出来,级联的SQL也没有执行。
- 局部配置
也有部分场景,需要一部分级联的对象数据即时加载,一部分不需要,这个时候可以使用局部延迟加载的功能,我们可以在
association
和collection
元素中加入fetchType
属性实现局部延迟加载功能。
fetchType
有两个取值,如下:
eager
:即时加载
lazy
:延迟加载
- 修改AuthorMapper.xml,为association添加
fetchType="eager"
实现即时加载,为collection 添加fetchType="lazy"
实现延迟加载
<resultMap id="BaseResultMap" type="com.sy.mybatis.pojo.Author" >
<id column="id" property="id" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="login_name" property="loginName" jdbcType="VARCHAR" />
<result column="pwssword" property="pwssword" jdbcType="VARCHAR" />
<association fetchType="eager" property="authorInformation" column="id" select="com.sy.mybatis.mapper.AuthorInformationMapper.getAuthorInformationbyAuthorId"></association>
<collection fetchType="lazy" property="specials" column="id" select="com.sy.mybatis.mapper.SpecialMapper.getSpecialsByAuthorId"></collection>
</resultMap>
测试
在第一步打个断点,然后调用AuthorService的getAuthorById方法获取作者信息
image.png image.png 第一步执行结束后可以看到设置了fetchType="eager"
即时加载级联的authorInformation对象数据查询了出来,执行了级联SQL,而设置了fetchType="lazy"
延迟加载的specials对象信息没有查询出来,级联的SQL也没有执行。
在return处再打个断点,继续执行代码到return处。
image.png
image.png
从执行的sql日志中可以看到,再次调用即时加载的属性时没有重新执行级联查询,后面的延迟加载对象在我调用时才去查询了对应的数据,这样就实现了局部延迟加载功能。