在我们查数据时,mybatis会默认把关联的数据查出来,而关联查询比单表查询慢,并且我们有时候不需要那么多的数据。所以我们需要开启懒加载,关联的数据等需要的时候再查出来。

myBatis开启懒加载,需要在mybatis主配置文件的settings标签中配置lazyLoadingEnabled为true,aggressiveLazyLoading为false。

lazyLoadingEnabled=true 即开启延迟加载

aggressiveLazyLoading=false即按需加载

一、懒加载的概念

1、MyBatis中的延迟加载,也称为懒加载,是指进行关联查询时,按需执行子查询。

当程序需要获取使用关联对象时,mybatis再执行子查询,这样可以减轻数据库的压力,在一定程度上可以降低程序运行消耗、提高查询效率。

2、懒加载的适用场景:

当前业务只使用主加载对象的其他属性,或者暂时只使用主加载对象的其他属性,长时间以后才使用主加载对象的关联对象属性。

3、懒加载只对关联查询起作用(一对一、一对多、多对多),且只对嵌套查询方式起作用,因为嵌套结果、扩展类的方式都是一次查询所需数据,不存在子查询,也就不存在延迟加载的情况。

MyBatis的延迟加载只是延迟执行子查询,对于主加载对象的查询都是直接执行的。

二、子查询的执行时机(关联对象的加载时机)

一共有三种:

1、直接加载:执行完主加载对象的查询,马上执行子查询。

2、侵入式延迟: 先执行主加载对象的查询,后续使用主加载对象的属性时(调用getter方法)才执行子查询。 只要使用主加载对象的属性,就执行子查询

3、深度延迟:先执行主加载对象的查询,后续使用主加载对象的关联对象属性时才执行子查询。 使用的属性要是主加载对象的关联对象属性时,才执行子查询

懒加载一共有2种方式,按照懒的程度,分为侵入式延迟、深度延迟。

三、配置方式

可在全局配置文件中进行配置,也可以在映射文件中进行配置。

1、默认就是直接加载,什么都不用配置,当然也可以显式配置:

<settings>
  <setting name="lazyLoadingEnabled" value="false"/>
</settings>

2、侵入式延迟

<settings>
  <!-- 使用懒加载 -->
  <setting name="lazyLoadingEnabled" value="true"/>
  <!-- 使用侵入式延迟的懒加载 -->
  <setting name="aggressiveLazyLoading" value="true"/>
</settings>

aggressive 咄咄逼人的、激进的、主动模式的、喜好侵入的,一有机会就加载,故名侵入式延迟。

缺省aggressiveLazyLoading时,默认为true——侵入式延迟

3、深度延迟

<settings>
  <!-- 使用懒加载 -->
  <setting name="lazyLoadingEnabled" value="true"/>
  <!-- 使用深度延迟的懒加载 -->
  <setting name="aggressiveLazyLoading" value="false"/>
</settings>

4、也可以在映射文件的<association>或<collection>中单独配置某个关联对象的加载方式

也就是 fetchType 的值,有2个可选的值:

  • eager  直接加载,默认值。eager 饥渴的。
  • lazy  深度延迟。

此种方式不能指定为侵入式延迟。

5、在全局配置文件中进行的配置是配置所有的,在映射文件中的配置是配置单个的。

显式配置了懒加载,又在映射文件中配置了懒加载,冲突时以全局配置文件中的配置为准。

四、关于 Mybatis 设置懒加载无效的问题

1、看了 mybatis 的教程,讲到关于mybatis 的懒加载的设置:只需要在 mybatis 的配置文件中设置两个属性就可以了:

<settings>
        <!-- 打开延迟加载的开关 -->
        <setting name="lazyLoadingEnabled" value="true" />
        <!-- 将积极加载改为消息加载即按需加载 -->
        <setting name="aggressiveLazyLoading" value="false" />
    </settings>

如果你只配了lazyLoadingEnabled属性,那就不行了。

官方对这两个属性的解释是:

lazyLoadingEnabled 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。默认:false

aggressiveLazyLoading 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。默认:true

ef mysql 使用懒加载 mybatis开启懒加载_加载

2、但是经过测试之后发现还是无效的,经过一番折腾,发现是因为我在测试的时候,调用了查询出来的对象的 toString 方法,所以触发了一次懒加载:

EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
Employee employee = mapper.selectEmployee(1);
System.out.println(employee);

后来在配置文件中加入了这个设置:

<setting name="lazyLoadTriggerMethods" value=""/>

再试一遍,问题解决了。

lazyLoadTriggerMethods:指定哪个对象的方法触发一次延迟加载。默认值:equals,clone,hashCode,toString

所以,当我打印对象时,由于触发了 toString 方法,所以触发了一次懒加载。