PDA

View Full Version : Failed to lazily initialize a collection - no Session



lixin_chu
Sep 17th, 2004, 11:28 PM
Hi,
I am using Spring, Hibernate and Struts. Here is what I try to do:
3 persisted classes:
A --> (1-to-many) --> B --> (1-to-many)--> C

All with cascade="all"

In one Struts Action, I retrieve A and found that all B are retrieved automatically (I use A.getBs()). After which I put A into the request and forward to another Action.

In the second Action, I try to get C (using B.getCs()) but got error message:
-----------------------------------------------------------------------------
18.09.04 12:18:44 [http8080-Processor25] DEBUG org.springframework.orm.hibernate.SessionFactoryUt ils - Opening Hibernate session
18.09.04 12:18:44 [http8080-Processor25] DEBUG net.sf.hibernate.impl.SessionImpl - opened session
18.09.04 12:18:44 [http8080-Processor25] DEBUG org.springframework.transaction.support.Transactio nSynchronizationManager - Bound value [org.springframework.orm.hibernate.SessionHolder@16 8be1b] for key [net.sf.hibernate.impl.SessionFactoryImpl@39d072] to thread [http8080-Processor25]
18.09.04 12:18:44 [http8080-Processor25] DEBUG net.canal.core.action.BaseLookupAction - BaseAction: getLookupMapName( keyName = View )
18.09.04 12:18:44 [http8080-Processor25] DEBUG net.canal.core.action.BaseLookupAction - BaseAction: getLookupMapName( keyName = Prepare )
18.09.04 12:19:19 [http8080-Processor25] ERROR net.sf.hibernate.LazyInitializationException - Failed to lazily initialize a collection - no Session
net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no Session
------------------------------------------------------------------------------

Does it mean that before forwarding to Action B, I need to retrieve C first ? I thought it should be transparent to me as the cascade is set to 'all' for these classes already.

What do I misunderstood ?

thanks in advance !

lixin_chu
Sep 17th, 2004, 11:33 PM
By the way, I have OpenSessionInView configured in web.xml:

----------------
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate.support.OpenSess ionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>canalSessionFactory</param-value>
</init-param>
</filter>

<filter>
<filter-name>ResponseOverrideFilter</filter-name>
<filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>

------------------------

problem is still there.

irbouho
Sep 18th, 2004, 12:10 AM
After which I put A into the request and forward to another Action.

is this a server forward or are you using redirect?

In the Action where you try to get C, you can rebind your entity to Hibernate Session before calling getCs() using


Session session = SessionFactoryUtils.getSession&#40;sessionFactory, false&#41;;
session.lock&#40;B, LockMode.NONE&#41;;


HTH

lixin_chu
Sep 18th, 2004, 08:27 PM
I am using Struts Action forward, somethign like this:
return (mapping.findForward("success"));

The action manpping is something like this:
<forward name="success" path=".createTemplateDef"/>

which goes to a Tiles (.createTemplateDef).

I suppose it is forward not redirect.

I will try your suggetion.

thanks

tuor
Sep 21st, 2004, 01:50 AM
worked for you?

seems that we have the same problem ...
made a similar post yesterday - maybe you can have a look at it

thanx

tuor

sakkew
Sep 22nd, 2004, 05:18 AM
I have a similar problem. In the first action it's possible to load a lazy collection after loading the parent, but loading the collection in another action does not work. What am I missing? I can see in the log that the filter is actually closing the session, or is the log-message just vague?

DEBUG HibernateTransactionManager [http8080-Processor24] - Not closing pre-bound Hibernate session [net.sf.hibernate.impl.SessionImpl@1c81ac0] after transaction
DEBUG OpenSessionInViewFilter [http8080-Processor24] - Closing single Hibernate session in OpenSessionInViewFilter
DEBUG SessionFactoryUtils [http8080-Processor24] - Closing Hibernate session
DEBUG SessionImpl [http8080-Processor24] - closing session
DEBUG SessionImpl [http8080-Processor24] - disconnecting session
DEBUG SessionImpl [http8080-Processor24] - transaction completion

lixin_chu
Sep 22nd, 2004, 05:39 AM
have not got time to try tuor's suggestion. I am busy with a few other things. really tired.

but i still think it is a configuration problem if I understand the OpenSessionInView correctly.

lixin_chu
Sep 25th, 2004, 01:28 AM
found the problem (I hope):

1. when retrieving the parent object, OpenSessionInView creates a new session; SessionImpl is kept in the child collection

2. in the next requst, OpenSessionInView will create another new session; when trying to get child collection, the previous session is used but not initialized so causing the problem.

But i do not know how to fix the problem.

lixin_chu
Sep 25th, 2004, 04:45 AM
I tried 'singleSession' to 'true' but still the same problem. So it seems that it IS becuase the previous session is not initialized.

I will try the lock suggestion but in this case, 'lazy loading' only means I gain performace benifit the first time when I retrieve the parent obj. The code is messy if I have have to touch the hibernate session anywhere I need to access collections.

where is the bext place to put the lock method ?

is my understanding correct ?

lixin_chu
Sep 25th, 2004, 08:12 PM
I try the suggestion:

Session session = SessionFactoryUtils.getSession(sessionFactory, false);
session.lock(B, LockMode.NONE);


but it is still the same.

Before calling session.lock(), I can see that B has C info like this (I am using Eclipse IDE)
B--
additions=null
collectionSnapshot=SessionImpl$CollectionEntry (id=353)
directlyAccessible=false
initialized=false
initializing=false
session=SessionImpl (id=356)
set=null
tempList=null

After locking, the collectionSnapshot and session are all changed to a different id.

Then when I access Bs, I do get all the items - and also the initialized is changed to 'true'

But I am wondering if this is the right way to support the lazy loading:
1) I have to add this code in everywhere I need to access a lazily loaded collection
2) any performace issue by introducing this locking ?

thanks !

lixin_chu
Sep 25th, 2004, 08:19 PM
typo. the above solution works. but i am still trying to understand more and why OpenSessionInViewFilter plus lazy=true is not sufficient.

lixin_chu
Sep 25th, 2004, 08:54 PM
this is indeed weird !

The above solution only works if I step into my A.getBs() during debugging. If not, the 'initialized=false' will not be changed to 'initialized=true' hence I can not get any Bs.

here is my code:
------

List aList = (List) request.getSession().getAttribute ("aList");
A a = aList.get(0);
try {
session.lock (a, LockMode.NONE);
} catch {
....
}

Set b = (Set) a.getB(); //<====I have to step into this !!!

......
------

I am using Spring framework 1.1, Hibernate 2.1.6, Struts 1.1 and I am debugging in Eclipse 3.0.

mikanboy
Dec 17th, 2004, 03:32 PM
Karl's weblog post (http://www.jroller.com/comments/kbaum/Weblog/orm_lazy_initialization_with_dao)explains this in further detail.

http://www.jroller.com/comments/kbaum/Weblog/orm_lazy_initialization_with_dao

Juanit0
Jul 28th, 2005, 04:19 AM
I begin using Spring, and my example was this simple tutorial (http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=1)

However, it does not explain how to manage lazy collections.
I tried to apply the advices given in the Karl's weblog post (http://www.jroller.com/comments/kbaum/Weblog/orm_lazy_initialization_with_dao), but as I encountered some problems.
Here is a part of my xml configuration file


<bean id="myTransactionManager" class="org.springframework.orm.hibernate.HibernateTransac tionManager">
<property name="sessionFactory"><ref local="mySessionFactory"/></property>
</bean>
<bean id="userService" class="org.springframework.transaction.interceptor.Transa ctionProxyFactoryBean">
<property name="transactionManager"><ref local="myTransactionManager"/></property>
<property name="target"><ref local="userTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>


As you can see, I use TransactionProxyFactoryBean elements while Karl Baum uses ProxyFactoryBean.
The problem is that I cannot use the hibernateInterceptor as he does.

Any idea about how to adapt it ?
Thanks.