Hibernate延迟加载

小编:管理员 533阅读 2022.09.14

前言:

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

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

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

代码:

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

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

一对多:

1.查询Customer,对orders进行延迟加载设置,在customer.hbm.xml进行设置,延迟加载默认为开启状态。


     
     
     
复制

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

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

现在将延迟加载关闭,customer.hbm.xml中将set标签的lazy属性改为false。


      
      
      
复制

现在继续查询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.hbm.xml中进行设置。默认值为false,即关闭延迟加载。

复制

所以,查询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,加载对应的Student,默认延迟加载是开启的,在classes.hbm.xml中进行设置。


    
    
    
复制

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

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

现在将lazy改为false。


      
      
      
复制

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

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

获取Student,调用classes也是同样的配置,在student.hbm.xml中进行配置即可。

总结:

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

关联标签: