一文带你掌握Mybatis延迟加载原理简单了解

1,854 阅读2分钟

这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战

Mybatis延迟加载

什么是延迟加载

延迟加载是加载策略的一种,加载策略分为延迟加载和直接加载两种策略。延迟加载主要体现在关联查询中。

比如在开发过程中很多时候我们并不需要总是在加载⽤户信息时就⼀定要加载他的订单信息。此时就是我们所说的延迟加载。

延迟加载就是在需要⽤到数据时才进⾏加载,不需要⽤到数据时就不加载数据。延迟加载也称懒加载。

延迟加载的优点

Mybatis先从单表查询,需要时再从关联表去关联查询,⼤⼤提⾼数据库性能,因为查询单表要⽐关联查询多张表速度要快。

延迟加载的缺点

因为只有当需要⽤到数据时,才会进⾏数据库查询,这样在⼤批量数据查询时,因为查询⼯作也要消耗时间,所以可能造成⽤户等待时间变⻓,造成⽤户体验下降。

注意事项

  • 在多表中:

    • ⼀对多,多对多:通常情况下采⽤延迟加载⼀对⼀
    • (多对⼀):通常情况下采⽤⽴即加载
  • 延迟加载是基于嵌套查询来实现的

延迟加载的实现

局部延迟加载实现

在association和collection标签中都有⼀个fetchType属性,通过修改它的值,可以修改局部的加载策略。

 <!--开启⼀对多延迟加载-->
<resultMap id="userMap" type="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<!--fetchType="lazy" 懒加载策略 fetchType="eager" ⽴即加载策略-->
<collection property="orderList" ofType="order" column="id" select="com.mybatis.dao.OrderMapper.findByUid" fetchType="lazy">
</collection>
</resultMap>

<select id="findAll" resultMap="userMap">
SELECT * FROM `user`
</select>

全局延迟加载实现

在Mybatis的核⼼配置⽂件中可以使⽤setting标签修改全局的加载策略。

<settings>
<!--开启全局延迟加载功能-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>

注意事项

<!--关闭⼀对⼀延迟加载-->
<resultMap id="orderMap" type="order">
<id column="id" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
<!-- fetchType="lazy" 懒加载策略 fetchType="eager" ⽴即加载策略-->
<association
property="user"
column="uid"
javaType="user"
select="com.mybatis.dao.UserMapper.findById"
fetchType="eager">
</association>
</resultMap>
<select id="findAll" resultMap="orderMap">
SELECT * from orders
</select>

延迟加载原理实现

它的原理是,使⽤ CGLIB 或 Javassist( 默认 ) 创建⽬标对象的代理对象。当调⽤代理对象的延迟加载属性的getting ⽅法时,进⼊拦截器⽅法。⽐如调⽤ ⽅法,进⼊拦截器的 ⽅法,发现 需要延迟加载时,那么就会单独发送事先保存好的查询关联 B 对象的 SQL ,把 B 查询上来,然后调⽤a.setB(b) ⽅法,于是成 a.getB().getName() ⽅法的调⽤。这就是延迟加载的基本原理 对象b属性就有值了,接着往下走

总结

延迟加载主要是通过动态代理的形式实现,通过代理拦截到指定⽅法,执⾏数据加载。