Skip to content

延迟加载使用及原理

一、核心概念

1. 什么是延迟加载?

延迟加载(懒加载)是指在需要用到数据时才进行加载,不需要用到数据时不加载数据。 MyBatis支持一对一关联对象和一对多关联集合对象的延迟加载,默认关闭,需手动开启。

2. 配置开启延迟加载

mybatis-config.xml中配置:

xml
<settings>
    <!-- 开启延迟加载 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 按需加载(可选配置) -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

二、使用场景示例

以用户表和订单表的一对多关联为例:

java
public class User {
    private Integer id;
    private String username;
    // 关联订单集合,延迟加载
    private List<Order> orderList;
}

public class Order {
    private Integer id;
    private String name;
    private Integer userId;
    private User user;
}
  • 未开启延迟加载:查询用户时,会同时执行用户表和订单表的SQL查询;
  • 开启延迟加载:查询用户时,仅执行用户表查询,orderList为代理对象;当调用user.getOrderList()时,才会执行订单表的SQL查询。

三、底层实现原理

延迟加载通过CGLIB动态代理实现,流程如下:

  1. 创建代理对象:MyBatis为目标对象(如User)创建CGLIB代理对象;
  2. 拦截目标方法:当调用关联属性的getter方法(如getOrderList())时,进入代理对象的拦截器invoke方法;
  3. 判断并执行查询:拦截器发现目标属性(orderList)为null,执行关联SQL查询;
  4. 设置属性并返回:将查询结果设置到目标对象的属性中,再返回属性值。

面试相关问题

  1. 问:MyBatis是否支持延迟加载?默认开启吗?答: MyBatis支持一对一和一对多关联的延迟加载,默认不开启,需要在配置文件中通过lazyLoadingEnabled=true手动开启。

  2. 问:延迟加载的底层实现原理是什么?答: 延迟加载通过CGLIB动态代理实现:为目标对象创建代理对象,当调用关联属性的getter方法时,代理拦截器判断属性是否为null,若为null则执行关联SQL查询,将结果设置到属性中后再返回。

  3. 问:延迟加载的优缺点是什么?答: 优点是按需加载数据,减少不必要的SQL查询,提升性能;缺点是会增加一次额外的SQL查询,若所有关联属性都需要访问,总查询次数会增加,需结合业务场景使用。

  4. 问:如何配置MyBatis的延迟加载?答:mybatis-config.xml<settings>中配置lazyLoadingEnabled=true开启延迟加载,同时可配置aggressiveLazyLoading=false实现按需加载,避免不必要的触发。

Powered by VitePress 1.6.4 | 持续更新中