MyBatis延迟加载
当我们进行多表查询时,会牵扯到多张表,如果我们查询之后,并不一定使用结果中的全部字段,可能只会用到其中几个字段,这时,如果我们只需要一两个字段但是每次的查询都是多表查询一定会很影响效率,所以的我们可以使用延迟加载的方案
立即加载:不管用不用,只要一调用方法,马上发起查询
延迟加载:在真正使用数据的时候才发起查询,不用的时候不查询关联的数据,又叫做按需加载(懒加载)
延迟加载又根据加载时机分为侵入式延迟和深度延迟
侵入式延迟加载
- 执行对主加载对象的查询时,不会执行对关联对象的查询。但当要访问主加载对象的详情属性时,就会马上执行关联对象的select查询。
深入延迟加载
- 执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关联对象的详情时,才会执行对关联对象的 select 查询。
实现延迟加载
前面我们使用resultMap标签完成了手动映射,使用association、collection实现了一对一和一对多的关系,使用它们还可以完成延迟加载的功能。
首先,需要在mybatis-config.xml文件中进行一些全局配置
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 配置是否为深度加载,默认就是false,所以也可以不写,使用侵入式加载就用true-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
然后就是map映射文件
<!-- 一对一关系 延迟加载-->
<!-- 查询所用订单的sql-->
<select id="findOrderUserList" resultMap="resultMap_order_user">
select o.id,o.uid,o.number,o.createtime,o.des from t_orders o
</select>
<!-- 查询用户的sql,需要时才会使用此sql-->
<select id="findUserListToOrder" parameterType="int" resultType="user">
select u.id as id,u.username as username from t_user u where id=#{uid}
</select>
<resultMap id="resultMap_order_user" type="ordervo">
<id column="id" property="id"/>
<result column="uid" property="uid"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<!-- 延迟加载,配置后只有需要user的数据时,才会加载select中的语句-->
<association property="user" javaType="User" column="uid" select="findUserListToOrder">
<id column="id" property="id"/>
<result column="username" property="username"/>
</association>
</resultMap>
(这里是一对一的关系,使用的是association标签,collection标签同理)
public class OrderVo implements Serializable {
private static final long serialVersionUID = -7655399935824396176L;
private Integer id;
private Integer uid;
private String number;
private Timestamp createtime;
private String des;
private User user;
public User getUser() {
return user;
}
@Override
public String toString() {
return "OrderVo{" +
"id=" + id +
", uid=" + uid +
", number='" + number + '\'' +
", createtime=" + createtime +
", des='" + des + '\'' +
'}';
}
}
测试:
查看订单列表
@Test
public void test1(){
IOrderMapper iOrderMapper = sqlSession.getMapper(IOrderMapper.class);
List<OrderVo> list = iOrderMapper.findOrderUserList();
for (OrderVo orderVo: list){
System.out.println(orderVo);
}
}
这时我们调用了findOrderUserList,但是只循环遍历了订单列表,并没用访问和使用orderVo中的user属性
查看结果:
这时我们让每一次循环不止打印订单的信息,还需要打印订单对应的用户信息:
@Test
public void test2(){
IOrderMapper iOrderMapper = sqlSession.getMapper(IOrderMapper.class);
List<OrderVo> list = iOrderMapper.findOrderUserList();
for (OrderVo orderVo: list){
System.out.println(orderVo);
System.out.println(orderVo.getUser());
}
}
查看结果: