mysql 迟加载_Mybatis3详解(十一)——延迟加载

1、N+1问题

N+1问题主要是针对分步查询,分步查询就是使用association或collection标签中的select属性来执行另外一个 SQL 映射语句来返回预期的复杂类型,例如:

在前面的代码中(分步查询),我们所有的级联都已经成功了,但是这样会引发性能问题,就是我们查询数据时,级联的数据也会跟着全部查询出来。但是如果我们暂时只需要部门的信息,而不需要级联对象中的信息,这就会使数据库多执行几条毫无意义的SQL,导致数据库资源的损耗和系统性能的下降。而如果有多重级联的话则会更加明显,假如现在有N个级联,本来我们只要查询主数据,只要一次查询就可以了,但是由于级联的关系,其级联的数据也会跟着查询出来,后面的SQL语句还会执行N次,这样就造成了N+1问题。

以前面员工和部门的例子举例:我们本来要的是部门数据,根据部门id查询部门信息,但是由于一个部门可以有多个员工,级联数据会跟着查询出来,假如现在有N个员工,那么查询的语句如下:

本来我们只需要部门的一条数据即可,但是查询了N+1次,这是不合理的。那么为了应对N+1问题,Mybatis提供了延迟加载功能。

2、什么是延迟加载

延迟加载也叫做懒加载、惰性加载。就是我们希望一次性把常用的级联数据通过SQL直接查询出来,对于那些不想要的级联数据则不要取出,而是等待要用的时候才取出来。在mybatis中,resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。

3、如何开启延迟加载

开启延迟加载有两种方式:

①、全局配置延迟加载:这种方式就是给所有的级联配置延迟加载。Mybatis默认是不开启延迟加载的,需要我们去全局配置文件中打开延迟加载。配置项

作用

配置值

默认值

lazyLoadingEnabled

全局的延迟加载开关,开启时,所有级联对象都会延迟加载

true | false

false

aggressiveLazyLoading

当启用时,有延迟加载属性的对象在被调用时将会加载该对象的所有属性。 否则,每个属性会按需加载

true | false

false 版本3.4.1之前为true

注意:这个aggressiveLazyLoading有点不好理解,下面会有介绍。

全局配置如下:

②、fetchType属性为局部配置延迟加载:这种方式需要用到fetchType属性,主要解决全局配置的缺点,因为不是所有的地方都要使用到延迟加载,fetchType出现在级联元素association和collection中,它存在两个值:eager:立即加载对应的数据。

lazy:延迟加载对应的数据。

4、全局配置实现延迟加载

以前面部门Department和员工Employee为例,一个部门可以包含多名员工的一对多关系。

①、创建员工和部门实体类:

员工实体类:

部门实体类:

②、创建员工和部门Mapper接口

EmployeeMapper:

DepartmentMapper:

③、创建员工和部门SQL映射文件

EmployeeMapper.xml

DepartmentMapper.xml

④、在Mybatis的配置文件中开启全局延迟加载

⑤、数据库连接和日志文件

db.properties:

log4j.properties:

⑥、测试代码

⑦、测试结果

(1)、只使用部门数据,这时候不需要查询员工信息

f38325546b81c04057e9076ac721cc73.png

016fc5f12eef509c6312d6bf7672fda2.png

可以发现只查询了部门的信息。

(2)、需要使用员工数据,这时候因为需要获取员工数据所以要查询员工信息。

d58cc3de1f348c21a0459d0d447dd5de.png

eed2a72c69a1eb98f55e3e1056051258.png

我们发现部门和员工数据都查询了,先是查询了部门的信息,然后我们又要获取员工的信息,所有后面再去查询员工的信息。

而我们在关闭延迟加载的查询时这样的,它直接给我们的数据全部都查询出来了,而不是等到我想要的时候才去查询。

b7a0d49abe45da32fef04dca27141415.png

5、fecthLazy实现局部延迟加载

fecthLazy实现局部延迟加载的方式配置非常简单,如下:

①、我们把Mybatis的全局配置文件中的开启延迟加载的配置删除或者注释

42d3ae7fe5cfa61288b37982628d6f0f.png

②、然后将我们需要设置为延迟加载的地方设置fecthLazy=lazy即可

bfaba921d748d900d03bc8fb61921a8a.png

③、执行的结果和前面的测试结果是一样的,所以我们一般推荐使用这种方式,这种方式的好处就是我哪里想要延迟加载就设置哪里即可。

6、lazyLoadingEnabled和aggressiveLazyLoading的使用lazyLoadingEnabled:主要控制延迟加载的开关。为true时表示开启延迟加载,false关闭。

aggressiveLazyLoading:true表示如果有延迟加载属性的对象在被调用时将会加载该对象的所有属性,false则表示每个属性会按需加载。

我们主要来学习一下aggressiveLazyLoading属性

(1)、aggressiveLazyLoading的属性为false,即每种属性按需加载,不调用就不加载。

运行测试方法:

6dbc3cd158573277ff60de0708b1d838.png

运行结果:

bef89979242c553240770ded2ac7999a.png

可以看到只执行department的sql语句,并且只加载了调用的属性。

(2)、aggressiveLazyLoading设置为true:只要对这个类的任意操作将完整加载整个类的所有属性,即执行级联的SQL语句。运行同样的测试方法:

965e42d39c8a3a67e118099d4e7e8e6d.png

我们只调用了department对象中的getXxx方法,而并没有调用employee对象中的getXxx方法,但是mybatis却调用了查询员工SQL语句。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值