【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。就不会有这样的效果。