Hibernat: Lazy Initialization过程

在Hibernate手册中是这样描述 Lazy Initialization-延迟加载的

集合(不包括数组)是可以延迟初始化的,意思是仅仅当应用程序需要访问时,才载入他们的值。对于使用者来说,初始化是透明的, 因此应用程序通常不需要关心这个(事实上,透明的延迟加载也就是为什么Hibernate需要自己的集合实现的主要原因)。

另外一种选择是不使用延迟初始化集合。既然延迟初始化可能引起上面这样错误,默认是不使用延迟初始化的。但是, 为了效率的原因, 我们希望对绝大多数集合(特别是实体集合)使用延迟初始化。


如果你不描述,则Lazy的属性为False(即不使用延迟加载!这让我想到原来我们的一位同事没有Load出List就怪罪于Hibernate,看来是子虚乌有的!) 所以Lazy属性的设置与你内存的大小是有很大关系的,如果你采用Hibernate默认的设置,也许不经意(就是Hibernate"透明持久化")Load出主表的记录就连带着将子表的一个上千万的List给Load进内存中,你的服务器不崩溃才怪呢!!

Javaeye的那些个高手总是不解释"透明持久化"这个概念,让很多初学者非常的疑惑(比如我),在打印出Hibernate的调试信息后,一切都变得自然。。。
你可以尝试着将Lazy更换成true|false
<list name="currentSteps" cascade="all-delete-orphan" lazy="false" >
<key column="entry_Id"/>
<index column="stepIndex"/>
<one-to-many class="com.company.engine.workflow.po.HibernateCurrentStep"/>
</list>

当你将lazy更改成false(也就是默认值)时,并在Load出主记录后关闭session,比如如下程序
try
{
List result = session.find(ENTRY_SEARCH_SQL, new Long(entryId), Hibernate.LONG);
return (WorkflowEntry) result.get(0);
}
catch (HibernateException he)
{
throw new StoreException(he);
}finally
{
if(session != null)
try
{
session.close();
}
catch (HibernateException he)
{
throw new StoreException(he);
}
}

当你执行如下测试的时候
try
{
HibernateWorkflowEntry entry = (HibernateWorkflowEntry) store.findEntry(0);
logger.debug("find entry by id - " + entry);
assertNotNull(entry);

List cl = entry.getCurrentSteps();
for(int i=0;i<cl.size();i++)
{
HibernateCurrentStep step = (HibernateCurrentStep) cl.get(i);
logger.debug("get entry current steps["+i+"] = " + step);
logger.debug("get entry current steps["+i+"] = " + step.getEntry());

}

}
catch (Exception e)
{
e.printStackTrace();
assertTrue(false);
}

就会接受到如下的异常信息

net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no session or session was closed
at net.sf.hibernate.collection.PersistentCollection.initialize(PersistentCollection.java:209)
at net.sf.hibernate.collection.PersistentCollection.read(PersistentCollection.java:71)
at net.sf.hibernate.collection.List.size(List.java:79)
at test.com.company.engine.workflow.store.ExtHibernateWorkflowStoreTest.testFindEntry(ExtHibernateWorkflowStoreTest.java:82)
........

net.sf.hibernate.collection.List
/**
* @see java.util.List#size()
*/
public int size() {
read();
return list.size();
}

这里的read()就会反向的再次读取数据库记录,目的是再次的Load出子记录来!可是这个时候你已经将Session关闭了!!所以Hibernate也就无法完成加载的任务,LazyInitializationException异常自然就扔了出来


但是现在就有一个问题:当list执行read()方法的时候,给它的session是什么?(答案肯定是你Open的那个session)但是hibernate如何确保session的唯一性呢?这个问题比较的BT,需要看SessionFactoryImpl这个构造函数到底怎么维护session的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值