延迟加载:侵入式延迟和深度延迟

先提交后获取,异步调用?

还记得多线程中的Future和FutureTesk吗?就是先提交后获取的异步调用,线程使用的是Callable接口而不是Runnable接口。异步调用可以有效率地解决这些场景:假设一个计算任务需要耗费很长时间,它的计算结果我们并不急着需要,在等待该计算完成的过程中,我们想充分利用等待的时间,让CPU去做其他的事情,等我们需要这个计算结果时,再去拿这个计算任务的结果返回值。

毫无疑问这种方法可以省去很多不必要的等待时间,提高系统的效率,在MyBatis里有一种延迟加载机制,也类似于这样的思想。在一些关联查询里,我们查询的信息大都不在同一张表中,需要关联多张表查询,但是对于复杂的场景,多表关联查询效率不高,延迟加载机制可以解决这一问题。我们知道单表查询速度一定比多表查询快很多,所以可以通过延迟加载,一开始我们先做单表查询,等需要关联的数据时,再去做关联查询,例如我们在商场数据库中查询顾客的商品清单,并且关联查询这些清单对于的顾客信息,显然要连接商品信息表和顾客表两张表,使用延迟加载,先查询出商品信息表信息,等需要获取顾客信息时,再去单表查询出顾客信息,类似于异步调用的思想,不必一次查询出嵌套关联对象的信息,按需获取,无疑能提高查询的效率。

关于延迟加载,有一些要注意的是:

第一:使用延迟加载时,SQL语句要拆分成多句,例如关联嵌套查询,我们的SQL语句不能写成多表连接,一句完成查询,否则会变成直接加载。

第二:延迟加载对于主对象来说是直接加载的,只有关联对象例如association标签对中关联的对象,才是延迟加载。那么如何控制它延迟加载?如何在我需要时采取查询关联对象的信息?下面会说。

setting配置中的延迟加载和按需加载

延迟加载机制能提高查询效率,但它不是默认开启的,首先要在全局配置文件的settings标签对中配置延迟加载的属性为true。在settings标签中配置setting标签对,有两个属性可以给我们设置,lazyLoadingEnabled属性和aggressiveLazyLoading属性。lazyLoadingEnabled属性控制全局是否使用延迟加载机制,默认是false。aggressiveLazyLoading属性配置是否需要按需加载,默认是false,在设置按需加载为false后,加载了某一个对象,则这个对象的所有属性和关联的对象都会一起被加载,而如果按需加载设置为true,则当使用到某个对象时,才会去加载某个对象的属性。

对于这两个属性不同的配置方式,可以产生出不同的延迟加载效果,主要是由aggressiveLazyLoading按需加载属性决定的,分为侵入式延迟加载和深度延迟加载两种,不同的延迟加载,它们的查询包装类和Mapper映射配置,SQL语句都是一样的,下面我们就先来看这三个配置,假设现在有这么一个需求,查询购物清单表中的信息,以及关联查询购物清单对应的顾客信息:

查询包装类

首先是查询包装类,我们的主对象是购物清单信息:

public class ShoppingCart implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int cartId; // 购物车id
	private int userId; // 用户id
	private int productId; // 商品id
	private String productName; // 商品名
	private int number; //商品数量
	private double price; //商品价格
	
	public ShoppingCart() {
//		System.out.println("进入ShoppingCart类无参数构造方法");
	}
	
	public ShoppingCart(int cartId, int userId, int productId, 
			String productName, int number, double price) {
//		System.out.println("进入ShoppingCart类有参数构造方法");
		this.cartId = cartId;
		this.userId = userId;
		this.productId = productId;
		this.productName = productName;
		this.number = number;
		this.price = price;
		//this.user = user;
	}
}
// 省略get()和set()方法

关联对象是顾客信息:

public class User implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值