`
duoerbasilu
  • 浏览: 1483329 次
文章分类
社区版块
存档分类
最新评论

hibernate 中lazy作用

 
阅读更多

转载:

HIBERNATE的持久化对象加载策略。
延迟加载, 也就是用到的时候才去加载.这样可以提高一些性能.
Hibernate
lazy loading 采用了一个HibernateSession来管理session,它的逻辑是每进行一次数据库操作,就开新的session,操作完成后立即关闭该session。这样做的好处是可以严格关闭session,避免菜鸟级的错误,但是hibernate.org并不推荐这么做。因为这不适合lazy loading,也不适合跨方法的事务。

比如在我们的应用中,user->post形成一对多的映射,User中有一个包含postList
User中,有多个属性:namepasswordphone等,还有一个List类型的posts。当我们对posts使用lazy laoding的时候,hibernate会在获得User对象的时候,仅仅返回name,password,phone等基本属性,当你访问posts的时候,它才会从数据库中提取posts需要的数据,这就是所谓lazy laoding。但是在我们的系统中,session是被立即关闭的,也就是在读取了name,password,phone等基本属性后,session已经close了,再进行lazy loaiding就会有异常。
解决办法是在close session之前,调用Hibernate.initialize(user.getPosts()),告诉系统,user.getPosts()是需要lazy laoding的。但是这样做会破坏HibernateSession类的封装.
后来采用所谓的OpenSessionInView模式,把session的周期交给servlet filter来管理,每当有request进来,就打开一个sessionresponse结束之后再关闭它,这样可以让session存在于整个请求周期中。

本文主要针对一对多情况下读取父类的子集合时,hibernate 的lazy属性在其中的影响进行总结。(以下代码运行在jdk1.5,jboss eclipse ide 1.5,hibernate 3.1环境下)
假设有:父类 Person (含有Set类型属性Address),
子类 Address(碰巧集合的名字和子类的名字都是Address,不要混淆了)
Person.hbm.xml 主要片段:
<id
name="idx"
column="idx"
type="long"
>
<generator class="identity">
</generator>
</id>
<property
name="age"
type="int"
update="true"
insert="true"
column="age"
/>
<property
name="name"
type="java.lang.String"
update="true"
insert="true"
column="name"
/>
<set
name="address"
table="address"
lazy="true"
cascade="none"
sort="unsorted"
>
<key
>
<column
name="personidx"
/>
</key>
<one-to-many
class="com.abc.common.pojo.Address"
/>

</set>
(1)在session 的周期内,无论lazy 设为true or false, 不会有任何限制。访问父子数据的代码如下所示 :
//打开session
session = HibernateUtil.currentSession();

PersonDAO dao = new PersonDAO();
Person person = null;

person = (Person)dao.findByPrimaryKey(4);
Set addressSet = person.getAddress();

Address[] addressAry = new Address[addressSet.size()];
Address address = null ;
addressSet.toArray(addressAry);

for(int i=0 ;i<addressAry.length;i++){
................
}
//session关闭
session.close();
if (session.isOpen()){
HibernateUtil.closeSession();
}

(2)在session的周期外,访问父子数据的代码如下所示 :
//打开session
session = HibernateUtil.currentSession();

PersonDAO dao = new PersonDAO();
Person person = null;

person = (Person)dao.findByPrimaryKey(4);
/**********************
*留待后续处理
*********************/
session.close();

//session关闭之后才访问person的子集
Set addressSet = person.getAddress();

Address[] addressAry = new Address[addressSet.size()];
Address address = null ;
addressSet.toArray(addressAry);

for(int i=0 ;i<addressAry.length;i++){
................
}
if (session.isOpen()){
HibernateUtil.closeSession();
}

此时,上述代码的运行结果根据lazy的设置的不同而不同
lazy=false
结果:可以访问得到Person和Address的数据
lazy= true
根据代码的写法有不同
(1)代码其他处不做任何处理,则抛出异常
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
。。。。。。
(2)如果做一些处理如下,将上述那段代码中的"留待后续处理"换成以下代码
Hibernate.initialize(person.getAddress()); 则可以访问得到Person和Address的数据
实际编写时,不会象上述这样的写法,即将
Hibernate.initialize(person.getAddress());和person.getAddress()在同一个方法里面调用。他们往往出现在应用程序的不同层次中(前者出现在DAO层居多,而后者则出现在web层居多).

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics