-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Reattached object throwing LazyInitializationException
PostPosted: Sun Aug 07, 2005 11:46 pm 
Beginner
Beginner

Joined: Fri Jun 04, 2004 12:50 pm
Posts: 32
Hi all,

Here is the problem. I have an entity that has a one-to-many relationship with another entity. Those entities are kept in a Set. I am building a web application using Struts and am using the doFilter() method for opening and closing methods as described in the Hibernate in Action book (which by the way is awesome). So, a session is opened when an action is called and closed after the JSP pages for that request have finished being created.

On the first request a Camper entity is being called so that it can be updated. So I create a session, go get the Camper entity, store it in the session, display it and then close the session oafter the page has been rendered. This all works fine.

The problem is after I receive a request back again with the updated information. When I try to access the Camper method that holds the Set containing the other entities I get the following exception:

ERROR [LazyInitializationException] failed to lazily initialize a collection (com.camp.common.camper.Camper.registrations) - no session or session was closed

Now, a new session has been created at the beginning of the second action and as can be seen below the Registration set is lazily initialized. Does this mean that when the first action is called I need to make sure that the Registration set is initialized as well?

Can I get it so that the detached Camper object gets reattached to the new Session so that it can go and fetch the Registration Set if required? I have set up the second level cache and everything seems to be working fine. I have also over written the equal and hashCode methods but these may be incorrect. From what Hibernate in Action says, I need these methods overridden so that the Camper object can be correct identified and reattached correctly.

I have tried the update without attempting to touch the registration Set and everything works. So, I think that would suggest that the object gets reattached to the session correctly, but because it was initialized lazily from the beginning the Set somehow can not be accessed. Is this a good assumption? Am I correct in assuming that the camper object gets reattached correctly? Is there a way of reattaching an object programmatically? I cannot find out how this is done.

Any help greatly appreciated.
Cheers
Tom

Hibernate version: Whatever version comes with Jboss 4.0.2. I think its Hibernate 2.1

Mapping documents:
I am including both the MAPPING objects and the equal and hashCode methods of the classes.

Camper Mapping
<class name="com.camp.common.camper.Camper" table="tblCamper">

<cache usage="read-write"/>

<id name="camperID" type="integer">
<column name="id_camper" sql-type="integer" not-null="true"/>
<generator class="sequence">
<param name="sequence">tblcamper_id_camper_seq</param>
</generator>
</id>

<property name="lastName">
<column name="last" sql-type="char(32)" not-null="true"/>
</property>

<property name="firstName">
<column name="first" sql-type="char(32)" not-null="true"/>
</property>

<property name="gender">
<column name="gender" sql-type="boolean" not-null="false"/>
</property>

<property name="birthday">
<column name="birthday" sql-type="timestamp" not-null="false"/>
</property>

<property name="grade">
<column name="grade" sql-type="char(16)" not-null="false"/>
</property>

<property name="notes">
<column name="notes" sql-type="text" not-null="false"/>
</property>

<property name="doctor">
<column name="doctor" sql-type="char(64)" not-null="false"/>
</property>

<property name="doctorPhone">
<column name="doctor_phone" sql-type="char(16)" not-null="false"/>
</property>

<property name="healthCard">
<column name="health_card" sql-type="text" not-null="false"/>
</property>

<property name="dateEntered" update="false">
<column name="date_entered" sql-type="timestamp" not-null="false"/>
</property>

<property name="revisionDate">
<column name="revision_date" sql-type="timestamp" not-null="false"/>
</property>

<property name="userEntered">
<column name="user_entered" sql-type="char(128)" not-null="false"/>
</property>

<property name="email">
<column name="email" sql-type="char(128)" not-null="false"/>
</property>

<many-to-one name="school" column="fk_id_school" class="com.camp.common.school.School" not-null="true"/>

<many-to-one name="family" class="com.camp.common.family.Family" column="fk_id_family" not-null="true"/>

<set name="registrations" inverse="true">
<key column="fk_id_camper"/>
<one-to-many class="com.camp.common.registration.Registration"/>
</set>

</class>

Registration Mapping
<class name="com.camp.common.registration.Registration" table="tblRegistration">

<cache usage="read-write"/>

<id name="registrationID" type="integer">
<column name="id_registration" sql-type="integer" not-null="true"/>
<generator class="sequence">
<param name="sequence">tblregistration_id_registration_seq</param>
</generator>
</id>

<property name="medFormBack">
<column name="med_form_back" sql-type="boolean" not-null="false"/>
</property>

<property name="activityInfo">
<column name="activity_info" sql-type="text" not-null="false"/>
</property>

<property name="behaviourInfo">
<column name="behaviour_info" sql-type="text" not-null="false"/>
</property>

<property name="referralSource">
<column name="referral_source" sql-type="char(64)" not-null="false"/>
</property>

<property name="camperLeave">
<column name="camper_leave" sql-type="boolean" not-null="true"/>
</property>

<property name="whoLeave">
<column name="who_leave" sql-type="char(128)" not-null="false"/>
</property>

<property name="whoRelationship">
<column name="who_relationship" sql-type="char(128)" not-null="false"/>
</property>

<property name="confirmLetter">
<column name="confirm_letter" sql-type="boolean" not-null="true"/>
</property>

<property name="notes">
<column name="notes" sql-type="text" not-null="false"/>
</property>

<property name="dateEntered" update="false">
<column name="date_entered" sql-type="timestamp" not-null="false"/>
</property>

<property name="revisionDate" update="false">
<column name="revision_date" sql-type="timestamp" not-null="false"/>
</property>

<many-to-one name="camper" class="com.camp.common.camper.Camper" column="fk_id_camper" not-null="true"/>

<one-to-one name="registrationMedical" class="com.camp.common.registration.RegistrationMedical" property-ref="registration" cascade="all" outer-join="auto" constrained="false"/>

</class>

Camper equal and hashCode methods

public boolean equals(Object _camper) {

if (this == _camper) return true;
if (id_camper == null) return false;
if ( !(_camper instanceof Camper)) return false;
final Camper camper = (Camper) _camper;
return id_camper.equals(camper.getCamperID());

}

public int hashCode() {
return id_camper == null ? System.identityHashCode(this) : id_camper.hashCode();
}

Registration equal and hashCode methods
public boolean equals(Object _registration) {

if (this == _registration) return true;
if (id_registration == null) return false;
if ( !(_registration instanceof Registration)) return false;
final Registration registration = (Registration) _registration;
return id_registration.equals(registration.getRegistrationID());

}

public int hashCode() {
return id_registration == null ? System.identityHashCode(this) : id_registration.hashCode();
}




Code between sessionFactory.openSession() and session.close():
N/A

Full stack trace of any exception that occurs:
ERROR [LazyInitializationException] failed to lazily initialize a collection (com.camp.common.camper.Camper.registrations) - no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection (com.camp.common.camper.Camper.registrations) - no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:180)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:48)
at org.hibernate.collection.PersistentSet.size(PersistentSet.java:110)
at com.camp.common.camper.Camper.toString(Unknown Source)
at java.lang.String.valueOf(String.java:2131)
at java.lang.StringBuffer.append(StringBuffer.java:370)
at com.camp.helpers.camper.CamperHelper.modifyCamper(Unknown Source)
at com.camp.actions.camper.updateCamperAction.execute(Unknown Source)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at com.camp.common.utilities.HibernateFilter.doFilter(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:153)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
at java.lang.Thread.run(Thread.java:534)

Name and version of the database you are using:
Postgres 8.0

The generated SQL (show_sql=true):
From the first action:
select this_.id_camper as id1_0_, this_.last as last52_0_, this_.first as first52_0_, this_.gender as gender52_0_, this_.birthday as birthday52_0_, this_.grade as grade52_0_, this_.notes as notes52_0_, this_.doctor as doctor52_0_, this_.doctor_phone as doctor9_52_0_, this_.health_card as health10_52_0_, this_.date_entered as date11_52_0_, this_.revision_date as revision12_52_0_, this_.user_entered as user13_52_0_, this_.email as email52_0_, this_.fk_id_school as fk15_52_0_, this_.fk_id_family as fk16_52_0_ from tblCamper this_ where this_.id_camper=?

Debug level Hibernate log excerpt:


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 09, 2005 7:21 am 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
When you get an instance from a session and don't fetch all its properties, you cannot fetch them after you close the session.

Hibernate does not allow to fetch new data from another session because you then read data from two distinct transaction so you can have stale data.

The best way for you are :
- fetch the set in the first call
- store only the id in the http session and get the camper back in the second call (the second level cache can help you here to avoid another database call)
- use a long session which you connect/disconnect, this is explained in the hibernate in action book, maybe you can find an example in the caveat emptor app


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 09, 2005 8:29 am 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
scesbron wrote:
When you get an instance from a session and don't fetch all its properties, you cannot fetch them after you close the session.

Hibernate does not allow to fetch new data from another session because you then read data from two distinct transaction so you can have stale data.

The best way for you are :
- fetch the set in the first call
- store only the id in the http session and get the camper back in the second call (the second level cache can help you here to avoid another database call)
- use a long session which you connect/disconnect, this is explained in the hibernate in action book, maybe you can find an example in the caveat emptor app



(JBoss 4.0.2 comes with Hibernate 3)

This information isn't entirely correct. Read section 11.6 Modifying detatched Objects in of the Hibernate 3.0.5 reference doc.

If your Camper object hasn't been modified yet you can use session.lock() to reassociate it with the new session.

_________________
Preston

Please don't forget to give credit if/when you get helpful information.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 09, 2005 9:45 am 
Beginner
Beginner

Joined: Fri Jun 04, 2004 12:50 pm
Posts: 32
So if I reassociate with the new session using session.lock() does that mean that I can then access the Set which wasn't initialized in the previous session?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 09, 2005 9:57 am 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
tomansley wrote:
So if I reassociate with the new session using session.lock() does that mean that I can then access the Set which wasn't initialized in the previous session?


Yes, after you reattach the object with session.lock() you can access the set and hibernate will perform the SQL query to retrieve the data.

Be sure and familiarize yourself with the effects of the various LockMode values.

_________________
Preston

Please don't forget to give credit if/when you get helpful information.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 09, 2005 12:16 pm 
Beginner
Beginner

Joined: Fri Jun 04, 2004 12:50 pm
Posts: 32
Preston,

You rock. Worked like a charm.

Thanks


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.