1、延迟加载概述
- 应用场景 如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。
- 延迟加载的好处 先从单表查询、需要时再从关联表去关联查询,大大提高 数据库性能,因为查询单表要比关联查询多张表速度要快。
- 延迟加载的条件:1)resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。2)延迟加载是针对分步查询而言的
2、开启延迟加载
Mybatis的延迟加载功能默认是关闭的
需要在mybatis-config.xml全局配置文件中通过setting标签配置来开启延迟加载功能
需要在mybatis-config.xml全局配置文件中通过setting标签配置来开启延迟加载功能开启延迟加载的属性:
lazyLoadingEnabled:全局性设置懒加载。默认为false,true表示开启延迟加载
aggressiveLazyLoading:false表示关闭积极加载
说明:这两个属性必须一起设置
【示例】
<settings>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--关闭积极加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
3、延迟加载测试
延迟加载需求:通过订单编号20140921003查询order并延迟加载user。就是演示上述演示过的一对一的表关系案例。
如果通过订单编号查询order并且查询user信息,在正常情况下的查询语句应该是:
分析:
如果改成延迟加载,也就意味着,先查询order,等需要的时候再去查询user,那就相当于将上面的一条语句变成了两条语句:
1、通过订单编号查询order
2、通过查询出来的order中的user_id查询user
sql语句:
分步查询:
#第一步:根据order_number查询订单信息;
SELECT * FROM tb_order WHERE order_number = '20140921003';
#第二步:根据订单信息中的user_id查询出下单人的信息;
SELECT * FROM tb_user WHERE id = 1;
第一步:编写接口方法
在OrderMapper接口中新建:queryOrderUserLazy方法
/**
* 根据orderNumber懒加载查询订单及用户信息
* @param orderNumber
* @return
*/
Order queryOrderUserLazy(@Param("orderNumber") String orderNumber);
第二步:编写SQL
【OrderMapper.xml】
<!--懒加载结果集-->
<resultMap id="orderUserLazyResultMap" type="Order">
<id property="id" column="id"/>
<!--
1.column属性:延迟加载的sql语句中所需的参数,就是SELECT * FROM tb_user WHERE id = ?;
该sql语句的?位置。这里书写 user_id因为执行 SELECT * FROM tb_order WHERE order_number = #{orderNumber} 语句查询的用户id对应的列名就是user_id
2.select属性:调用指定sql语句来执行延迟加载,就是指定sql语句所在的位置,根据用户id查询用户信息位于UserMapper.xml文件中,具体地址是:namespace.id
3.执行流程:
先执行SELECT * FROM tb_order WHERE order_number = #{orderNumber} 根据订单号获取订单信息(包括用户id)
然后根据 select="com.itheima.sh.dao.UserMapper.selectById" 找到UserMapper.xml文件中的:
<select id="selectById" resultType="User">
select * from tb_user where id = #{id}
</select>
并将column="user_id" 对应的列值传递过去
并将查询的结果封装到User对象中,最后将User对象封装到Order对象中
-->
<association property="user" javaType="User" column="user_id" select="com.itheima.sh.dao.UserMapper.selectById"></association>
</resultMap>
<select id="queryOrderUserLazy" resultMap="orderUserLazyResultMap">
SELECT * FROM tb_order WHERE order_number = #{orderNumber}
</select>
【UserMapper.xml】
<mapper namespace="com.itheima.sh.dao.UserMapper">
<!--
查询语句
id: 接口中方法的名字
resultType:返回的实体类的类型,类全名
-->
<select id="selectById" resultType="User">
select * from tb_user where id = #{id}
</select>
</mapper>
说明:
1.column属性:延迟加载的sql语句中所需的参数,就是SELECT * FROM tb_user WHERE id = ?; 该sql语句的?位置。这里书写 user_id因为执行 SELECT * FROM tb_order WHERE order_number = #{orderNumber} 语句查询的用户id对应的列名就是user_id 2.select属性:调用指定sql语句来执行延迟加载,就是指定sql语句所在的位置,根据用户id查询用户信息位于 UserMapper.xml文件中,具体地址是:namespace.id 3.执行流程: 先执行SELECT * FROM tb_order WHERE order_number = #{orderNumber} 根据订单号获取订单信息(包括用户id) 然后根据 select="com.itheima.sh.dao.UserMapper.selectById" 找到UserMapper.xml文件中的: select * from tb_user where id = #{id} 并将column="user_id" 对应的列值传递过去 并将查询的结果封装到User对象中,最后将User对象封装到Order对象中
【注意】
- 懒加载首先是把SQL拆分;
- 然后在resultMap中,通过关联映射配置中的,select属性引入需要懒加载进来的对象;
第三步:开启懒加载
在mybatis-config.xml全局配置文件中,开启懒加载
<!--settings属性配置-->
<settings>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--关闭积极加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
第四步:测试
【没有访问关联对象】
在没有访问关联对象的属性时,只发送了一条SQL。
【访问关联对象的属性】
访问关联对象属性时,发送了两条SQL语句。按需查询-----懒加载!