I have a bi-directional <one-to-one> mapping based on primary keys. Class A is mapped to table A and configured to cascade updates to Class B, which is mapped to table B.
This works fine when there are no exceptions. The update cascades successfully.
However, if the update to A instance succeeds, but the update to B instance generates an exception at the database level, the transaction rolls back, but the update that was made to table A does not get rolled back for some reason.
I am using JBoss DataSource and Spring declarative transactions, delegating to the HibernateTransactionManager and Hibernate is configured to use JTA as the transaction strategy.
I can see in the log that Hibernate begins a JTA transaction and then after the second update results in an exception, rolls back the JTA transaction.
The behavior is acting like it would in autocommit=true mode, but my understanding was that Hibernate turns autocommit=false before it does its stuff.
Hibernate version:
3.0.5
hibernate.properties
hibernate.dialect=org.hibernate.dialect.SQLServerDialect
hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup
Mapping documents:
<hibernate-mapping>
<class name="A" table="A" select-before-update="true">
<id name="id" type="long">
<column name="InstrID" not-null="true"/>
<generator class="identity"/>
</id>
<timestamp name="auditEffDate" column="Audit_EffDate"/>
<property name="visitId" column name="VID" type="long"/>
<one-to-one name="b" class="B" cascade="save-update"/>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="b" table="B" select-before-update="true">
<id name="id" type="long">
<column name="InstrID" not-null="true"/>
<generator class="foreign">
<param name="property">a</param>
</generator>
</id>
<timestamp name="auditEffDate" column="Audit_EffDate"/>
<one-to-one name="a" class="A" constrained="true"/>
<property name="checks" column="Checks" type="integer"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
tx = session.beginTransaction();
session.saveOrUpdate(a);
tx.commit();
Name and version of the database you are using:
MS SQL Server 7, jTDS driver 1.0.3
Log
2005-07-12 16:12:28,621 DEBUG [org.hibernate.transaction.JTATransaction] begin
2005-07-12 16:12:28,621 DEBUG [org.hibernate.transaction.JTATransaction] Looking for UserTransaction under: UserTransaction
2005-07-12 16:12:28,621 DEBUG [org.hibernate.transaction.JTATransaction] Obtained UserTransaction
2005-07-12 16:12:28,621 DEBUG [org.hibernate.transaction.JTATransaction] Began a new JTA transaction
...
update table A
update table B
database exception
...
2005-07-12 16:12:28,670 DEBUG [org.hibernate.transaction.JTATransaction] rollback
2005-07-12 16:12:28,670 DEBUG [org.hibernate.transaction.CacheSynchronization] transaction after completion callback, status: 4
2005-07-12 16:12:28,670 DEBUG [org.hibernate.jdbc.JDBCContext] after transaction completion
2005-07-12 16:12:28,670 DEBUG [org.hibernate.impl.SessionImpl] after transaction completion
2005-07-12 16:12:28,670 DEBUG [org.hibernate.transaction.JTATransaction] Rolled back JTA UserTransaction
Thanks for any ideas.
- Charlie
|