高级java每日一道面试题-2025年01月26日-框架篇[Mybatis篇]-Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

如果有遗漏,评论区告诉我进行补充

面试官: Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

我回答:

MyBatis中的延迟加载

一、延迟加载的配置

全局配置:

在MyBatis的配置文件mybatis-config.xml中,可以通过 <settings> 标签来设置全局的延迟加载行为。

  • lazyLoadingEnabled: 设置为 true 表示开启延迟加载,默认值为 false
  • aggressiveLazyLoading: 设置为 false 表示只有在访问某个延迟加载属性时,才会触发加载。如果设置为 true,则一旦调用了延迟加载的对象中的任意一个属性,所有延迟加载的属性都会被加载。默认情况下,该值为 false
<settings>
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

局部配置:

可以在 <association><collection> 标签中通过 fetchType="lazy" 来指定具体的映射关系是否需要延迟加载。

<resultMap id="personResultMap" type="Person">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <association property="address" javaType="Address" 
                 select="selectAddressById" column="address_id" fetchType="lazy"/>
</resultMap>
二、延迟加载的实现原理

MyBatis使用动态代理机制(Dynamic Proxy)和CGLIB代理来实现延迟加载功能。

  1. 代理对象的创建:

    • 当MyBatis解析 <resultMap> 并发现某个属性配置了 fetchType="lazy" 时,它会在加载这个对象时,为该属性创建一个代理对象。
    • 这个代理对象可以是一个Java动态代理(基于接口的)或者是CGLIB代理(基于子类的)。代理对象并不包含实际的数据,而是记录下要执行的SQL语句及其参数。
  2. 延迟加载的触发:

    • 当应用程序首次访问该代理对象的属性时(例如调用 user.getAddress()),MyBatis通过代理机制捕获这个访问请求。
    • 代理对象的Invoker接口在捕获到访问请求后,立即执行预先定义好的SQL查询,从数据库中获取实际的数据。
  3. 查询结果的返回与缓存:

    • 查询结果返回后,MyBatis将结果映射到目标对象(如 Address),并填充到原始对象的相应属性中。
    • 在延迟加载完成后,MyBatis会将代理对象替换为实际的查询结果对象。后续对该属性的访问将直接返回已经加载的数据,而不会再次触发延迟加载。
三、延迟加载的性能优化
  1. 减少不必要的数据库查询操作:

    • 延迟加载可以显著减少不必要的数据库查询操作,尤其是在对象关联关系复杂的场景下。
  2. Session生命周期管理:

    • 确保延迟加载的触发在MyBatis SqlSession生命周期内进行,否则可能会引发SqlSession关闭后无法加载数据的异常。
  3. 结合 aggressiveLazyLoading 进行优化:

    • 根据实际需求调整 aggressiveLazyLoading 配置,在需要时提前加载关联数据,减少多次SQL查询的开销。
  4. 使用缓存:

    • 可以结合MyBatis的二级缓存来缓存延迟加载的结果,进一步提升性能。

注意事项

尽管延迟加载可以显著减少不必要的数据库查询,但也需要注意以下几点:

  • N+1查询问题:虽然延迟加载可以避免一次性加载大量关联数据,但如果设计不当,可能会导致N+1查询问题。因此,在使用延迟加载时,应仔细评估应用的具体需求和性能影响。

  • 事务管理:由于延迟加载会在后续时间点执行查询,这要求原事务仍然有效。否则,可能无法正确地加载关联数据。

综上所述,MyBatis通过动态代理机制实现了灵活的延迟加载功能,为开发者提供了在复杂对象关系映射中优化数据库访问的手段。理解其工作原理有助于更好地利用这一特性,同时避免潜在的问题。通过合理配置和良好的实践,MyBatis的延迟加载可以在保持代码简洁性的同时,大幅度提升系统性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java我跟你拼了

您的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值