Hibernate version:
3.0.5
Mapping documents:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="ht.Project" table="project">
<id name="projectId" type="java.lang.Integer" unsaved-value="null" column="project_id" >
<generator class="identity"/>
</id>
<property name="priority" column="priority" type="int" />
<map name="projectTexts" table="project_text" cascade="all-delete-orphan"
lazy="false" fetch="join">
<key column="project_id" />
<map-key type="string" column="language_id" />
<element type="string" column="project_text" />
</map>
</class>
</hibernate-mapping>
CodeAssume the following:
Code:
Session session1 = ...;
Project p = ...; // Object created or read from database
p.setPriority(...);
p.getProjectTexts().put("EN", "Enlish project text");
Transaction tx = session1.beginTransaction();
session1.saveOrUpdate(p);
session1.flush(); // CAUSES PROBLEMS WITH COLLECTION!
// For some reason there is a failure
tx.rollback;
session1.close();
// The user fixes the problem and retries to save
Session session2 = ...
Transaction tx = session2.beginTransaction();
session2.saveOrUpdate(p);
tx.commit();
session2.close();
Now the thing is, that the above code works as expected for the simple properties (i.e. priority in the project table is updated by the second session) but not for the collection (the Map of Strings mapped to the project_text table are NOT updated). After flushing in the first session, the collection is no longer marked dirty, and Hibernate does not try to save it in the second session.
There are numerous questions on this forum about the ID being generated and then Hibernate throws a HibernateException. The recommendation here is to throw away both the session and the objects, because they may be inconsistent (i.e. HibernateExceptions are non-recoverable). Please note that there is
no HibernateException being thrown here, but the problem is the same; the object hierarchy seems to be left in an inconsistent state that I cannot recover from.
The above scenario is of course very simplified, but assume a much larger object hierarchy that is updated using a UI wizard. When trying to save, an error is detected that the user needs to correct. In this case, the user does not want to start over from the beginning, but only fix the problem and retry to save.
The only way I can see to get around this is to never ever call flush until you know you will not roll back. In practise this means using hibernate.transaction.flush_before_completion and never flushing explicitly.
Or is there any other way around this?