-->
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.  [ 3 posts ] 
Author Message
 Post subject: Lazy init Sets modified after closing session?
PostPosted: Sat May 07, 2005 5:01 pm 
Newbie

Joined: Sat May 07, 2005 4:19 pm
Posts: 2
Hibernate version:
2.1.4 and 2.1.8

Mapping documents:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
    PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
  <class name="com.ortera.atlas.core.UOWData" table="UOWData">

    <id name="id" type="int" column="UOW_DATA_ID">
      <meta attribute="scope-set">protected</meta>
      <generator class="native"/>
    </id>

    <property name="monitorTime" type="long" not-null="true">
    </property>

    <set name="nfrontData" table="UOW_DATA_NFRONT_DATA" cascade="all"
      lazy="true">
      <key column="UOW_DATA_ID"/>
      <one-to-many class="com.ortera.atlas.core.NfrontData"/>
    </set>

    <set name="ioRateData" table="UOW_DATA_IORATE_DATA" cascade="all"
      lazy="true">
      <key column="UOW_DATA_ID"/>
      <one-to-many class="com.ortera.atlas.core.IORateData"/>
    </set>

    <set name="ioSizeData" table="UOW_DATA_IOSIZE_DATA" cascade="all"
      lazy="true">
      <key column="UOW_DATA_ID"/>
      <one-to-many class="com.ortera.atlas.core.IOSizeData"/>
    </set>

    <set name="workData" table="UOW_DATA_WORK_DATA" cascade="all"
      lazy="true">
      <key column="UOW_DATA_ID"/>
      <one-to-many class="com.ortera.atlas.core.WorkData"/>
    </set>

    <many-to-one name="overviewData" class="com.ortera.atlas.core.OverviewData"
      column="OVERVIEW_DATA_ID" cascade="all">
    </many-to-one>

  </class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():
Code:
Transaction tx = session.beginTransaction();
session.save(uowData);
tx.commit();


Full stack trace of any exception that occurs:
No exception

Name and version of the database you are using:
Derby 10.0.2.2

The generated SQL (show_sql=true):
N/A

Debug level Hibernate log excerpt:
N/A

I create an instance of UOWData and populate its Set properties, open a session, begin a transaction, save it, commit, and close the session. So far so good.

When I later try to access the Set properties (e.g., call isEmpty()), I sometimes get a LazyInitializationException, but other times it works fine. It appears to me as if Hibernate changes the Set instances (or, more likely, the proxies) at some point after I've closed the session.

I have two theories that I hope someone can debunk or confirm:
1) Some Hibernat cleanup thread eventually kicks in and does something with existing lazy init proxies.
2) Other threads in my application open new sessions and load the same UOWData object from the database while I'm still working with the Java instance I saved in an earlier session. Does Hibernate reuse lazy init proxies and somehow end up using the same proxy instance for multiple Java instances representing the same database object (one being transient, the other persistent)?

I'm totally baffled of what I see, so I hope someone can either tell me that I'm doing something that is a big no-no (such as hanging on to a Java instance outside a session while loading the same object into another Java instance in a session) or that I may have encountered an obscure Hibernate issue and point me in the right direction.

Thanks.
Code:


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 09, 2005 9:44 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
Quote:
1) Some Hibernat cleanup thread eventually kicks in and does something with existing lazy init proxies.

Hibernate *never* creates threads. So, no.

Quote:
2) Other threads in my application open new sessions and load the same UOWData object from the database while I'm still working with the Java instance I saved in an earlier session. Does Hibernate reuse lazy init proxies and somehow end up using the same proxy instance for multiple Java instances representing the same database object (one being transient, the other persistent)?

Hibernate performs uniqueing only within the same session. Uniqueing is the term for returning the same java instance (i.e., ==) for multiple requests. A given collection reference instance would be re-used only within that given session. Your application might "transfer
the collection, but that is beyond the control of Hibernate.

In your first scenario, the Set is not lazy because you explicitly populated it. You'd not get LazyInitializationExceptions here.

No, if you later explicitly loaded the UOWData instance in a different session (as opposed to truly maintaining the original reference to it and re-attaching), then the associated collection would be lazy (because that is what you have specified in your mapping) and attempting to access that outside the session would result in a LazyInitializationException.


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 09, 2005 3:43 pm 
Newbie

Joined: Sat May 07, 2005 4:19 pm
Posts: 2
Thanks Steve, that really cleared up what I'm seeing!

Quote:
No, if you later explicitly loaded the UOWData instance in a different session (as opposed to truly maintaining the original reference to it and re-attaching), then the associated collection would be lazy (because that is what you have specified in your mapping) and attempting to access that outside the session would result in a LazyInitializationException.


That sounds reasonable, but I assume that if I access the Sets within the new session that loads the UOWData, they would get initialized. I would then be able to close the session and read the Sets outside the session without getting a LazyInitializationException, right? That is, unfortunately, not what I'm seeing.

Here's what I really try to do. I have an instance of UOWData, populated outside a session. I open a session and start a transaction, call session.saveOrUpdate(uowData), and commit. Other threads in my application may have modified the UOWData in the database, so the saveOrUpdate() may throw a StaleObjectStateException. In this case I want to programatically do what a user would do in this situation: load the current UOWData state into an instance in a session, repopulate the Set members with new data, and try the saveOrUpdate() again. This works. But when I then try to access a Set outside a session, I get a LazyInitializationException.

In code, it goes something like this:
Code:
// In an earlier session, load the UOWData instance and populate its Sets.

private void save(UOWData uowData) {
  Session session = factory.openSession();
  Transaction tx = session.beginTransaction();
   session.saveOrUpdate(uowData);
  try {
    tx.commit();
  }
  catch (StaleObjectException e) {
    tx.rollback();
    session.close();
    reloadAndPopulate(uowData);
    save(uowData);
  }
  session.close();
}

private void reloadAndPopulate(UOWData uowData) {
  Session session = factory.openSession();
  session.load(uowData, uowData.getId());
  // Repopulate all Sets from copies with the new data, i.e.,
  // uowData.getNfrontData().clear();
  // uowData.getNfrontData().addAll(newNfrontDataValues);
  ...
  // Just to be sure the proxies are really initialized, access them all, i.e.,
  // uowData.getNfrontData().isEmpty();
  ...
}


Calling save() always works, even if the state in the database has changed so that the relaodAndPopulate() method gets invoked. After save(), if I try to read the Sets, it works fine if save() didn't call reloadAndPopulate() and it fails with LazyInitializationException if it did call reloadAndPopulate().

I'd appreciate any pointers to what I'm doing wrong.

Thanks.


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