I thought I understood how Hibernate's first level cache worked, but after reading some more of the Reference Manual, and analyzing some debug output from my code, I realize that I really don't know how the cache works. Here's my problem in a nutshell: when I issue an saveOrUpdate command for an object after the system has been idle for a few minutes, Hibernate re-reads the object from the database (including reading all of the collections that make up the object) before the update of the object is performed. So, the question is, why is this happening? I thought it was because the idle time caused the data in the first level cache to expire, so Hibernate first wanted to refresh the cache to make it current. But, after reading some of the reference manual, it appeared that the cache was in the session and was only available while the session was open. In my case, I get the session, update the object, and then immediately close the session. I put some debug statements before and after the update statement to see if the object was in the session's cache, and found out that the object was never in the session before the update, but always was after the update.
So I guess I have three questions:
1) How does the session cache actually work?
2) Why is my object being re-read from the database before the update after the system has been idle for awhile?
3) Can I keep Hibernate from re-reading the object before the update?
Thanks.
Here's the code that updates the object:
Code:
public static void update(Object updateObject) throws Exception
{
Session session = null;
Transaction transaction = null;
Exception exception = null;
try
{
session = HibernateUtils.currentSession();
transaction = session.beginTransaction();
session.saveOrUpdate(updateObject);
session.flush();
transaction.commit();
}
catch (Exception e)
{
e.printStackTrace();
exception = e;
try
{
transaction.rollback();
}
catch (Exception ex)
{
//do nothing
}
}
finally
{
try
{
if (session != null)
{
HibernateUtils.closeSession();
}
}
catch (Exception e)
{
//do nothing
}
}
//rethrow any DB2 exception encountered. the exception will result in an error message being displayed on the UI.
if (exception != null)
{
throw exception;
}
}
Here's my object definition:
Code:
<class name="com.ibm.caes.wcs.db.cache.beans.UserPreferences" table="user">
<cache usage="read-write"/>
<id name="webId" column="webId"/>
<property name="rssCategory"/>
<property name="rssTitle"/>
<set name="selectedProducts" inverse="true" cascade="all, delete-orphan" lazy="false" sort="com.ibm.caes.wcs.db.cache.beans.UserProduct">
<cache usage="read-write"/>
<key column="webId"/>
<one-to-many class="com.ibm.caes.wcs.db.cache.beans.UserProduct"/>
</set>
<set name="settings" inverse="true" cascade="all, delete-orphan" lazy="false">
<cache usage="read-write"/>
<key column="webId"/>
<one-to-many class="com.ibm.caes.wcs.db.cache.beans.UserSetting"/>
</set>
<set name="tabs" lazy="false" inverse="true" cascade="all, delete-orphan" sort="com.ibm.caes.wcs.db.cache.beans.Tab">
<cache usage="read-write"/>
<key column="webid" not-null="true"/>
<one-to-many class="com.ibm.caes.wcs.db.cache.beans.Tab"/>
</set>
<array name="searches" inverse="true" cascade="all, delete-orphan">
<cache usage="read-write"/>
<key column="userid" not-null="true"/>
<list-index column="index"/>
<one-to-many class="com.ibm.caes.wcs.db.cache.beans.SavedSearch"/>
</array>
</class>