Hibernate延迟加载

前言:

上一篇文章我们学习了Hibernate的多表关联关系,这里就涉及到一个很实用的概念:延迟加载或者也叫惰性加载,懒加载。使用延迟加载可以提高程序的运行效率。Java程序与数据库交互的频次越低,程序运行效率越高,所以我们应该尽量减少Java程序与数据库的交互次数,Hibernate延迟加载就很好的做到了这一点。

通过一个具体的业务场景来理解延迟加载:

客户(Customer)和订单(Orders),当我们查询Customer对象时,因为有级联关系,所以会将对应的Orders对象一并查询出来,这样就需要发送两条SQL语句,分别查询customer表和orders表中的数据。延迟加载的思路是:当我们查询Customer的时候,如果没有调用orders,则只发送了一条SQL语句查询customer;如果需要调用orders,则发送两条SQL语句查询customer和orders。所以延迟加载可以看做是一种优化机制,根据具体的代码,自动选择发送的SQL语句条数。

代码:

理解了延迟加载的概念,接下来就是如何使用了。

延迟加载使用起来很简单,直接在实体关系映射文件中进行配置即可。

一对多:

所以查询Customer,如果不调用orders,则会看到只发送一条SQL。

当调用orders的时候,发送两条SQL。

现在继续查询Customer,可以看到,即使没有调用orders属性,也同样发送了两条SQL,即延迟加载已经关闭,立即加载orders对象。

lazy属性除了可以设置true和false,还可设置extra,extra是比true更加懒惰的一种加载方式,或者说更加智能的一种加载方式,通过一个例子来理解两者的区别:

查询出Customer对象,然后需要打印该对象对应的orders集合的长度,使用lazy="true"。

会看到查询了两次SQL,第二次SQL首先将orders表中的记录查询出来,然后将这些记录映射成对象,创建Set集合对象,将oreders对象放入集合对象中,然后返回集合对象的长度,这是它的流程。

若将设置改为lazy="extra",会看到这样的SQL语句。

同样是两次SQL语句,第一次SQL没有区别。

此时第二次SQL语句是使用聚会函数来统计orders的总记录数,最终将结果2返回,与上面的操作接收到的结果是一样的。

但是很显然,这种方式更加高效,因为SQL直接统计了记录数然后返回,省去了查出记录--封装对象--放入集合--返回集合长度这一复杂的流程。

所以,通过这个例子我们可以看出,extra是更高效的一种加载方式,不到需要加载数据库具体数值的时候,是不会直接查询记录的。

这是通过Customer来设置orders的延迟加载,同理,我们也可以通过Orders来设置customer的延迟加载。

所以,查询Orders时,会发送两次SQL语句分别查询Orders以及级联的Customer。

现在将lazy的值进行修改,这个时候会发现,lazy的值不能改为true,可供我们选择的只有false proxy no-proxy。

其实这里的proxy和no-proxy是将开启延迟加载又进行了细分:

设置为no-proxy,当调用方法需要访问customer的成员变量时,发送SQL语句查询Customer,否则不发送。

设置为proxy,无论调用的方式是否需要访问customer的成员变量,都会发送SQL查询Customer。

这是两者的区别,但是在使用时,no-proxy编译时需要进行字节码增强操作,否则作用和proxy是一样的。

多对多:

所以查询Classes,从控制台看到只发送了一次SQL语句。

当调用Classes的students属性时,发送两次SQL。

现在将lazy改为false。

可以看到没有调用students属性,依然发送了两次SQL。

同理,lazy的第三个可选值extra与一对多关系是一样的,是比true更加懒惰的加载方式。

总结:

Hibernate延迟加载的配置有很多种方式,都是通过给标签设置lazy属性完来完成,并且不同的标签lazy属性的值是不一样的,重点还是理清楚实体类之间的关联关系,才可以通过设置lazy属性实现优化代码效率的目的。

下一篇:Hibernate配置文件详解-1

专业 热爱 专注

致力于最高效的Java学习

Java大联盟

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180127G05B7D00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券