-->
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.  [ 13 posts ] 
Author Message
 Post subject: Lazy collection not being fetched after update
PostPosted: Sun Feb 27, 2005 4:51 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
Read the rules before posting!
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version:
2.1.8
Mapping documents:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM
         "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
         
<hibernate-mapping package="com.myapp.model.hibernate">

<class name="Event"
      table="EVENT"
      lazy="true">
   <meta attribute="implements">java.lang.Cloneable</meta>      
   <!-- Common id property. -->
   <id name="id"
      type="long"
      column="EVENT_ID"
      unsaved-value="null">
      <generator class="native"/>
   </id>

   <property   name="date"
            update="true"
            type="date">
      <column name="DATE" not-null="true" length="12"/>
   </property>

   <set name="documents" lazy="true" inverse="true" cascade="all-delete-orphan">
      <key column="EVENT_ID"/>
      <one-to-many class="Document"/>         
   </set>
   
   <many-to-one name="type" column="EVENT_TYPE_ID" class="EventType"/>      
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM
         "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
         
<hibernate-mapping package="com.myapp.model.hibernate">
<class name="Document"
      table="DOCUMENT"
      lazy="true">
   
   <!-- Common id property. -->
   <id name="id"
      type="long"
      column="DOCUMENT_ID"
      unsaved-value="null">
      <generator class="native"/>
   </id>

   <property   name="name"
            update="true"
            type="string">
      <column name="NAME" not-null="false" length="75"/>
   </property>
   
   <list name="information" lazy="true">
      <key column="DOCUMENT_ID"/>
      <index column="SEQUENCE"/>
      <one-to-many class="Information"/>
   </list>
   
   <many-to-one name="event" column="EVENT_ID" class="Event"/>
</class>
</hibernate-mapping>

Code between sessionFactory.openSession() and session.close():
Code:
public boolean updateEvent(Event evt) {
    boolean returnv = false;
    Session session = null;
    Transaction tx = null;
    try {
      session = HibUtil.getSession();
      tx = session.beginTransaction();
      session.update(evt);
      session.flush();
      tx.commit();
      returnv = true;
    } catch (HibernateException he) {
      he.printStackTrace();
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        e.printStackTrace();
      }
    }
    return returnv;
  }
  public List getDocumentsForEvent(Event event) {
    List docs = null;
    Session session = null;
    Transaction tx = null;
    try {
      session = HibUtil.getSession();
      tx = session.beginTransaction();
      if (!session.contains(event)) {
        System.out.println("Session locking event: " + event.getId());
        session.lock(event, LockMode.UPGRADE);
      } else
        System.out.println("Session already has event: " + event.getId());
      Hibernate.initialize(event.getDocuments());
      docs = new java.util.ArrayList(event.getDocuments());

      tx.commit();
      session.close();
    } catch (HibernateException he) {
      he.printStackTrace();
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        e.printStackTrace();
      }
    }
    return docs;
  }


Name and version of the database you are using:
PostgreSQL 7.4
The generated SQL (show_sql=true):
Code:
Session locking event: 122
Hibernate: select EVENT_ID from EVENT where EVENT_ID =? for update
Hibernate: select documents0_.EVENT_ID as EVENT_ID__, documents0_.DOCUMENT_ID as DOCUMENT1___, documents0_.DOCUMENT_ID as DOCUMENT1_3_, documents0_.NAME as NAME3_, documents0_.EVENT_ID as EVENT_ID3_, from DOCUMENT documents0_ where documents0_.EVENT_ID=?
Hibernate: update EVENT set DATE=?, EVENT_TYPE_ID=? where EVENT_ID=?
Session locking event: 122
Hibernate: select EVENT_ID from EVENT where EVENT_ID =? for update



My code calls getDocumentsForEvent(eventObj) first and retrieves a Set of Documents. On the first pass, this works just fine.

The code then changes the date property of the event and calls updateEvent(eventOjb). This works fine as well...and you can see the update call in the generated SQL.

Finally, the code calls getDocumentsForEvent(eventObj) again to retrieve the list of objects again. However, this time the Documents are *not* retrieved. The call to event.getDocuments() in getDocumentsForEvent simply returns an empty Set.

I've toggled various things to try to change this, but nothing seems to work. The association is still there in the database, and if I restart the application, the Documents are retrieved properly again. However, another call to updateEvent and the same behavior results.

I'm quite flabbergasted, honestly.

Can someone please point me at the grave mistake I've made?

Thanks!

Jbwiv


Top
 Profile  
 
 Post subject: Code for HibUtil
PostPosted: Sun Feb 27, 2005 4:53 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
Code:
public class HibUtil {
  private static Configuration config   = null;
  private static SessionFactory factory = null;
  private static Log logger = LogFactory.getLog(HibUtil.class); 
  private static Session session = null;

   static {
      try {
         config = new Configuration().configure();
        //config = new Configuration();
         factory = config.buildSessionFactory();
         
      } catch (Throwable e) {
         logger.error("HibUtil setup failed.", e);
         throw new ExceptionInInitializerError(e);
      }
   }

   /**
    * Returns the SessionFactory used for this static class.
    *
    * @return SessionFactory
    */
   public static SessionFactory getSessionFactory() {
      return factory;
   }
   
   public static Session getSession() throws HibernateException {
     if (null==session || ! session.isOpen())
       session = factory.openSession();
     return session;
   }
   
   public static Configuration getConfig() {
     return config;
   }   
}
[/code]


Top
 Profile  
 
 Post subject: Further details
PostPosted: Sun Feb 27, 2005 6:25 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
If I change the getDocuments method to this and query specifically, it works:
Code:
public List getDocuments(Event event) {
    List docs = null;
    Session session = null;
    Transaction tx = null;
    try {
      session = HibUtil.getSession();
      tx = session.beginTransaction();
      if (!session.contains(event)) {
        System.out.println("Session locking event: " + event.getId());
        session.lock(event, LockMode.NONE);       
      } else
        System.out.println("Session already has event: " + event.getId());           
     
      docs = session.createQuery("from Document as d where d.event=:event").setEntity("event", event).list();

      tx.commit();
      session.close();
    } catch (HibernateException he) {
      he.printStackTrace();
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        e.printStackTrace();
      }
    }
    return docs;
  }


Why in the world is this happening?!?


Top
 Profile  
 
 Post subject: Still stumped
PostPosted: Mon Feb 28, 2005 12:45 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
I spent the larger part of last night examining this, and I'm still at a loss.

Stepping through with the Eclipse debugger shows that when the collection is accessed a second time, it shows as initialized=true. I assume this means that Hibernate thinks it's already been fetched, and this is why it doesn't re-fetch? However, the Set it returns is still empty.

How can I tell hibernate that it's not initialized? I've tried session.clear(), etc....no luck.

Am I missing something completely, or is this a bug?

Thanks,
Jbwiv


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 01, 2005 9:09 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
Still no idea on this one. I'll buy a six pack for the first person that answers this!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 02, 2005 4:09 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
in your method
public boolean updateEvent(Event evt)

evt is a detached instance, what update have you done during detachment? have you add an element to the collection?

please tell in one word what has changed in this object.

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 02, 2005 9:40 am 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
anthony wrote:
in your method
public boolean updateEvent(Event evt)

evt is a detached instance, what update have you done during detachment? have you add an element to the collection?

please tell in one word what has changed in this object.


Anthony,

That's the strange thing....there has been no change to the collection. The only change has been to the object containing the collection (the event object). If I update, for example, the date property of the Event object, Hibernate exhibits this behavior...consistently. This occurs when I've not touched the collection itself in any way except to read it. And the collection contents simply disappear.

Thanks very much for your time!

Jbwiv


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 02, 2005 10:03 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
can you make this test:
load your Event objet
detache it (just close session)
call evt.getCollection.get(0)

tell me if you have a lazy exception

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 02, 2005 10:11 am 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
anthony wrote:
can you make this test:
load your Event objet
detache it (just close session)
call evt.getCollection.get(0)

tell me if you have a lazy exception


Sure. However, it'll be later this evening before I can....won't have access to the code until then

Thanks very much for your assistance. I *really* appreciate it!.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 02, 2005 10:33 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
anthony wrote:
can you make this test:
load your Event objet
detache it (just close session)
call evt.getCollection.get(0)

tell me if you have a lazy exception



Anthony...no, no lazy exception. Of course, since the collection is a Set and not a List, I had to do:
Code:
ArrayList list = new ArrayList(event.getDocuments());
System.out.println("EVENTGET: " + list.get(0));

To try it out.

I do, however, get an IndexOutOfBounds exception from the above, but only after I update (and the set disappears, as described before).

Thanks for any input you can provide!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 02, 2005 10:50 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
Anthony,

Wanted to provide further information on the lifecycle of an "Event" object.

First, all event objects are loaded from another class, called EventHolder. The events are stored in this class as a set.

I have a method defined like this:

Code:
List getEvents(EventHolder holder);


This method calls holder.getEvents() to get the events, but as I mentioned, the events collection is defined as a Set. So, just before returning, the method does this:
Code:
return new ArrayList(events);


to convert it to a List.

Now, this List of events is then stored in a custom TableModel for display in a JTable. It's simply stored as a List in this TableModel.

Finally, a user can click an event in the table to cause another table to be populated with the documents from the event, which the getDocumentsForEvent() method I included in earlier posts is used for. When the user clicks the event in the JTable, the code returns the corresponding Event object from the List contained in the TableModel. It then passes this Event object to getDocumentsForEvent.

Now, a user may also right-click on the table to get the capability to edit an event...when this happens the Event is passed to updateEvent(), also detailed in an earlier post.

It's after this call to updateEvent() that the getDocumentsForEvent() method begins to fail...before this it works just fine.

I look forward to your response!

Jbwiv


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 03, 2005 2:33 am 
Beginner
Beginner

Joined: Sun Feb 20, 2005 12:14 am
Posts: 49
Hi Jbiw:

I followed the discussion to your problem. In section 10.6 of the manual it states:
Quote:
"The lock() method also allows an application to reassociate an object with a new session. However, the detached instance has to be unmodified! "


It looks like after the call to the first events.getDocuments() you are changing the date in the event and updating that. This changes the state of your detached event object.

I am wondering if the following call sequence will work for you:
// first update the state of the detached
session.update(event);
//and then a call to:
event.getDocuments();

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 03, 2005 9:39 am 
Beginner
Beginner

Joined: Tue Nov 09, 2004 9:48 am
Posts: 23
mkhumri wrote:
I am wondering if the following call sequence will work for you:
// first update the state of the detached
session.update(event);
//and then a call to:
event.getDocuments();


mkhumri,

Hello! Thanks for the reply. I suspected the same thing when this first happened and switched to session.update(), but same behavior. It does not update the object...I think this is related to it thinking the object is already initialized and doesn't seem to think it's dirty...otherwise I would see an "UPDATE EVENT....." coming across the log.

I wish this were the answer!

Thanks!

Jbwiv


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 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.