【Mybatis进阶】延迟加载

首先我们先思考一个问题,假设:在一对多中,我们有一个用户,他有100个订单。

  问题1:在查询用户的时候,要不要把关联的订单查出来?
问题2:在查询订单的时候,要不要把关联的用户查出来?

  解答:
在查询用户的时候,用户下的订单信息应该是我们什么时候使用,什么时候去查询。
在查询订单的时候,订单的所属用户信息应该是随着订单查询时一起查询出来。

  搞清楚这两个简单的问题后,我们就可以引出延迟加载和立即加载的特性。

  延迟加载:在真正使用数据的时候才发起查询,不用的时候不查询关联的数据,延迟加载又叫按需查询(懒加载)
立即加载:不管用不用,只要一调用方法,马上发起查询。

还有一个实际的应用场景,就是一篇文章和文章中的图片,文章是立即加载,而文章关联的图片是在用到的时候才加载。相信大家都有过这种体检,就是用手机阅读文章的时候,只有阅读到有图片的位置,图片就会转圈圈加载,这也是延迟加载(懒加载)的体现,相信大家应该能明白其中的奥秘了。

实例

  理解了延迟加载的特性以后再看Mybatis中如何实现查询方法的延迟加载,在MyBatis的配置文件中通过设置settings的lazyLoadingEnabled属性为true进行开启全局的延迟加载,通过aggressiveLazyLoading属性开启立即加载。

还是老例子,用户和订单。本篇博客基于mybatis的环境已经搭建完成,如果不知道如何搭建,具体可以阅读笔者的博客——【从零开始学Mybatis笔记(三)】Dao开发方法

第一步:先把查询用户和订单的SQL写出来

    <!-- 通用查询结果列-->
    <select id="findAll" resultMap="userOrder">
        SELECT *
        FROM user
    </select>
    <select id="findOrderbyUserId" parameterType="int" resultType="Orders">
        select * from `orders` where user_id = #{userId}
    </select>

第二步:resultMap
第一步中我们使用的resultMap是延迟加载的关键,如下:

    <resultMap id="userOrder" type="com.tyust.entity.User">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        <!--        property对应User的属性orders
                    ofType对应orders中每一个元素对应的属性,因为orders是一个Order类的集合,所以就是Order类
                    javaType对应的就是order的java类型,就是List
                    select就是关联的查询方法
                    column就是user的属性,也是select中方法的参数,注意不是user_id-->
        <collection property="orders" ofType="com.tyust.entity.Orders"
                    select="com.tyust.dao.OrderMapper.findOrderbyUserId" column="id"/>
    </resultMap>

第三步:打开延迟加载设置

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

第四步:调试

当我们不使用User类的orders属性时,运行程序。

这时候我们把循环打印order的代码取消注释,再次运行程序。

结果就多出来好几条子查询。

如果我们把lazyLoadingEnabled的值改成false。就不会有这样的效果。

参考文献

Mybatis延迟加载的实现以及使用场景
【MyBatis学习11】MyBatis中的延迟加载

原文地址:https://www.cnblogs.com/zllk/p/14245169.html