Hibernate version: 3.1
Database: MySQL 5.0
Hello,
Could someone explain why session.lock(obj, LockMode.READ) does not seem to do a version check on associated instances? It only seems to associate detached objects with the session similar to LockMode.NONE.
What I try to do is have a outside process (or manually) modify an associated object in the database. Then in the program associate corresponding detached objects with the session and do a version check.
I have two persisted classes - Property and Resident. A property contains a set of residents. So I have my mapping files as follows:
<class name="ManagedProperty" table="ManagedProperty">
<id name="id" column="id">
<generator class="native" />
</id>
<version name="version"/>
<property name="name"/>
<set name="residents" cascade="lock,save-update">
<key column="property_id"/>
<one-to-many class="Resident"/>
</set>
</class>
<class name="Resident" table="Residents">
<id name="id" column="id">
<generator class="native" />
</id>
<version name="version"/>
<property name="firstName"/>
<property name="lastName"/>
<property name="unit"/>
<property name="propertyId" column="property_id"/>
</class>
Then in first session I create a property object add two residents and save. This works well.
Code:
Session session =HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
ManagedProperty prop = new ManagedProperty();
Resident resident1 = new Resident();
Resident resident2 = new Resident();
prop.setResidents(new HashSet());
prop.getResidents().add(resident1);
prop.getResidents().add(resident2);
session.save(prop);
session.getTransaction().commit();
Then I manually go to the database and update a record for one of the residents (incrementing its version).
Then in the program I associate the detached objects with the session.
Code:
session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.lock(prop, LockMode.READ);
session.getTransaction().commit();
I expect that calling session.lock() with LockMode.READ would throw a stale object exception, but it never does. Even though I have a cascade="lock" attribute on the set in the mapping file a version check is not done. I can only get it to work by doing
Code:
session.lock(resident, LockMode.READ)
However the whole idea is to avoid calling session.lock() for every object in the set.
What do you think is happening in this case? Is Hibernate sofisticated enough to handle cascading version checks on associated instances?
Code:
Hibernate: insert into ManagedProperty (version, name) values (?, ?)
Hibernate: insert into Residents (version, firstName, lastName, unit, property_id) values (?, ?, ?, ?, ?)
Hibernate: insert into Residents (version, firstName, lastName, unit, property_id) values (?, ?, ?, ?, ?)
Hibernate: update Residents set property_id=? where id=?
Hibernate: update Residents set property_id=? where id=?
Hibernate: select resident0_.id as id0_, resident0_.version as version0_, resident0_.firstName as firstName0_, resident0_.lastName as lastName0_, resident0_.unit as unit0_, resident0_.property_id as property6_0_ from Residents resident0_
Hibernate: select id from ManagedProperty where id =? and version =?