前言:
上一篇文章我们学习了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大联盟
领取专属 10元无门槛券
私享最新 技术干货