大家好,我是锋哥。今天分享关于【MyBatis如何处理懒加载和预加载?】面试题。希望对大家有帮助;

MyBatis如何处理懒加载和预加载?

超硬核AI学习资料,现在永久免费了!

MyBatis 中,懒加载(Lazy Loading)和预加载(Eager Loading)是处理关联对象(如一对一、一对多映射)时的重要机制,用于平衡系统性能与数据完整性。以下是详细解释:


一、懒加载(Lazy Loading)

概念:
懒加载指在第一次访问关联对象时才执行 SQL 查询获取数据,而不是在主对象加载时立即加载关联数据。
例如:当查询一个用户 User 时,其关联的订单 Order 不会立即被加载,只有当你调用 user.getOrders() 时,MyBatis 才会发出 SQL 查询订单表。

实现机制:
MyBatis 使用 动态代理(CGLIB 或 JDK Proxy) 实现懒加载。

  • 当调用主对象的 getter 方法时,会判断属性是否已加载;
  • 若未加载,则通过代理执行延迟查询;
  • 一旦加载完成,该属性的代理将被真实对象替代。

配置方式:


    
    
    
    

示例:

fetchType="lazy" 时,只有访问 user.getOrders() 时才执行查询。

优点:

  • 减少初始查询开销;
  • 提高系统响应速度;
  • 适合大数据量或层级较深的对象关系。

缺点:

  • 若频繁访问关联属性,可能导致 N+1 查询问题;
  • 在关闭 SqlSession 后访问懒加载属性会抛异常(因为连接已关闭)。

二、预加载(Eager Loading)

概念:
预加载即在查询主对象时立即加载其关联对象的数据,不需要等到访问时再查询。
适用于需要完整数据展示或频繁访问关联对象的场景。

实现方式: MyBatis 在定义映射关系时设置 fetchType="eager" 或在全局禁用懒加载:


    

或在具体映射中指定:

此时 MyBatis 在执行主查询时会立即加载 orders

优点:

  • 避免懒加载的延迟查询和会话关闭问题;
  • 查询逻辑更简单。

缺点:

  • 一次性加载大量数据可能影响性能;
  • 对数据量较大、关联复杂的对象不适合。

三、总结对比

特性懒加载(Lazy)预加载(Eager)
查询时机访问属性时查询主对象时
SQL执行次数可能多次一次性执行
性能初始性能好,后期可能多次查询一次加载,内存占用高
适用场景数据量大、不常访问关联对象需要完整数据或频繁访问关联对象

实际建议:

  • 在数据层较深、访问不确定的情况下使用懒加载;
  • 在展示页面或统计报表中需要完整信息时使用预加载;
  • 结合 缓存机制(一级、二级缓存) 优化懒加载性能。

是否希望我结合一个具体的 User-Order 实体 XML 配置示例(包含一对多和懒加载触发)来演示实际写法?