Hi, I'm using versioned data for optimistic locking in long transactions. I was testing out the locking and found my stale object was having its version number updated but nothing else.
For example:
User object has the following stale properties:
First name = John
Last name = Doe
Version = 0
The database record has the following:
First name = Johnny
Last name = Doe
Version = 1
When I execute the following code with the above stale User object:
Code:
public void saveOrUpdateUser(User user) throws DAOException {
DAOException error = null;
Transaction tx = null;
try {
Session session =
HibernateJNDIUtil.getSession(RiverdogProperties.RIVERDOG_AMP);
tx = session.beginTransaction();
session.saveOrUpdate(user);
tx.commit();
} catch (StaleObjectStateException sose) {
error = new StaleDataException("Stale data when updating user " + user.getUserName(), sose);
//user.setVersion(new Long(-1));
} catch (HibernateException he) {
error = new DAOException("Error saving user " + user.getUserName(), he);
} finally {
if (error != null) {
try {
if (tx != null) {
tx.rollback();
}
} catch (Throwable t) {
//nothing to do here...
}
//docs say to close session if rollback occurs
HibernateJNDIUtil.closeSession(RiverdogProperties.RIVERDOG_AMP);
logger.error(error);
throw error;
}
}
I get the expected StaleObjectStateException but my stale object looks like this:
First name = John
Last name = Doe
Version = 1
The version number (and only the version number) was updated. Immediately running the method again with the stale object causes the update to succeed which, of course, is not what I want... My commented out fix is above in the StaleObjectStateException catch block. This seems to work (won't allow the update to occur until the user has explicitly retrieved the latest version from the db).
I'm using Hibernate 2.1 with JDK 1.4 and Tomcat 5.0.16 with Oracle 9i.
My mapping file:
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.enterbridge.riverdog.domain.User"
table="Users"
dynamic-update="false"
dynamic-insert="false">
<id name="userName"
column="UserName"
type="java.lang.String">
<generator class="assigned"/>
</id>
<version name="version"
type="long"
column="Version"/>
<property name="email"
type="java.lang.String"
update="true"
insert="true"
column="Email"/>
<property name="password"
type="java.lang.String"
update="true"
insert="true"
column="Password"/>
<idbag name="roles"
table="UsersRoles"
lazy="false">
<collection-id column="ID" type="string">
<generator class="uuid.hex"/>
</collection-id>
<key column="UserName"/>
<many-to-many column="RoleName"
class="com.enterbridge.riverdog.domain.Role"
outer-join="true"/>
</idbag>
<property name="firstName"
type="java.lang.String"
update="true"
insert="true"
column="FirstName"/>
<property name="lastName"
type="java.lang.String"
update="true"
insert="true"
column="LastName"/>
<property name="created"
type="java.util.Date"
update="false"
insert="true"
column="Created"/>
<property name="modified"
type="java.util.Date"
update="true"
insert="true"
column="Modified"/>
</class>
</hibernate-mapping>
Am I doing something wrong or is this a feature/bug in Hibernate?
Thanks,
Matt