Hibernate延迟加载及关联关系的查询策略

  • 【版权所有,文章允许转载,但须以链接方式注明源地址,否则追究法律责任】

为什么hibernate需要延迟加载?

通过关联关系可以在程序中方便地获取关联对象的数据,但是如果从数据库中加载Student对象时,就同时自动加载所有关联的Grade对象,而程序实际上仅仅需要访问Student对象时,那么这些关联的Grade对象就白白浪费了许多内存空间。Hibernate查询Student对象时,立即查询并加载与之关联的Grade对象,这种查询策略就叫做立即加载。但是立即加载有两大不足
<1> 会执行不必要的查询语句,影响查询性能。
<2> 可能会加载大量不需要的对象,增加系统开销,浪费内存空间。
为了解决以上问题,Hibernate就提供了延迟加载策略。延迟加载策略能避免加载应用程序不需要访问的关联对象。就以Student类和Grade类为例,介绍如何设置加载策略,以优化查询性能。
Hibernate允许在对象-关系映射文件中使用lazy属性配置加载策略,并且分为类级和关联级两个级别,分别进行控制。看下表:

级 别Lazy属性取值
类级别<class>元素中lazy属性的可选值为true(延迟加载) 和 false(立即加载) 。默认值为true
一对多关联级别<set>元素中lazy属性的可选值为true(延迟加载)、extra(增强延迟加载)、false(立即加载)。默认值为true
多对一关联级别<many-to-one>元素中lazy属性的可选值为proxy(延迟加载)、no-paoxy(无代理延迟加载)和false(立即加载)。默认值为proxy

大家看完表可以发现,不管哪个级别默认都是延迟加载的查询策略,以减少系统资源的开销!

类级别的查询策略

类级别的默认加载策略就是延迟加载,所以你不写lazy属性也可以。例如:
<class name="cn.pojo.Student" table=" STUDENT ">

划重点本人自己总结:实体类对象目的是访问他的属性,用立即加载。实体类对象目的仅仅是获得他的引用,用延迟加载。

一对多和多对多的关联查询策略

先写个示例代码:

<hibernate-mapping>
    <class name="cn.hibernatedemo.entity.Dept" table="`DEPT`">
        <id name="deptNo" column="`DEPTNO`" type="java.lang.Byte">
            <generator class="assigned"/>
        </id>
        <property name="deptName" type="java.lang.String" column="`DNAME`"/>
        <property name="location" type="java.lang.String">
        	<column name="`LOC`"></column>
        </property>
        <set name="emps" inverse="true" lazy="true">
        	<key column="`DEPTNO`"></key>
        	<one-to-many class="cn.hibernatedemo.entity.Emp"/>
        </set>
    </class>
</hibernate-mapping>

这两种查询策略用的都是set元素,所以lazy属性在set元素中设置,<set>标签的lazy属性取值决定了emps集合被初始化时机(就是说到底是在加载Dept对象时就被初始化,还是在程序访问emps集合是被初始化)看下表lazy属性的取值:

lazy属性值加 载 策 略
true默认值,延迟加载
false立即加载
extra增强延迟加载

1.立即加载
很多情况下,应用程序并不需要访问这些emp对象,所以在一对多关联级别中不能随意使用立即加载策略!
2.延迟加载
对于set元素而言,应该优先考虑默认的延迟加载策略,直接不写lazy属性就可以,例如:

  <set name="emps" inverse="true" >
        	<key column="`DEPTNO`"></key>
        	<one-to-many class="cn.hibernatedemo.entity.Emp"/>
  </set>

3.增强延迟加载

 <set name="emps" inverse="true" lazy="extra">
        	<key column="`DEPTNO`"></key>
        	<one-to-many class="cn.hibernatedemo.entity.Emp"/>
  </set>

增强延迟加载与一般的延迟加载主要区别在于,增强延迟加载能进一步延迟Dept对象的emps集合代理类实例的初始化时机。当程序第一次访问emps属性的iterator()方法时,会导致emps集合代理类实例的初始化,而当程序第一次访问emps属性的size()、contains()和isEmpty()方法时,Hibernate不会初始化emps集合的代理实例,仅通过特定的select语句查询必要的信息。以下代码演示了增强延迟策略在hibernate运行时的行为:

tx=session.beginTransaction();
Dept dept=(Dept) session.get(Dept.class,new Byte("10"));
//以下语句不会初始化emps集合类实例
//执行sql语句:select count(empNo) from emp where DEPTO=?
dept.getEmps().size();

//以下语句不会初始化emps集合类实例
//执行SQL语句:select * from emp where DEPTO=?
dept.getEmps().iterator();
tx.commit();

多对一关联查询策略

在映射文件中度偶对一是用<many-to-one>标签设置的,看下表:

lazy属性值加 载 策 略
proxy默认值,延迟加载
no-proxy无代理延迟加载
false立即加载
多对一也是默认延迟加载,与前边不同的是它默认加载的属性值是proxy,并且它的属性没有true了。那么什么情况下使用哪种加载呢?
划重点:应用程序仅仅访问emp对象,并不需要与他关联的dept对象时,就用默认的延迟加载即可!
注意:第二个属性无代理延迟加载,需要在编译期间进行字节代码增强操作,否则运行情况和延迟加载一样,所以很少会用到。

【创作不易,帮助到你的话点个赞谢谢】

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值