Hi all,
I have three classes: CircularLinkOwnerDO, CircularLinkChildOneDO, CircularLinkChildTwoDO. CircularLinkOwnerDO has one-to-many composite association to both CircularLinkChildOneDO and CircularLinkChildTwoDO. CircularLinkChildOneDO has a many-to-one reference association to CircularLinkChildTwoDO.
My problem is, when I delete CircularLinkOwnerDO, I get "Integrity constraint violation" exception becuase hibernate was deleting CircularLinkChildTwoDO first before CircularLinkChildOneDO.
Hibernate version:2.1.4
Name and version of the database you are using: HypersonicSQL
Mapping documents:
Code:
<hibernate-mapping>
<class name="CircularLinkOwnerDO" table="CircularLinkOwnerDO">
<id name="id" column="id" type="string">
<generator class="assigned"/>
</id>
<!-- Note: You will not get the exception if you switch the order of these two lists around, becasue Hibernate will remove childOne first. -->
<list name="compositeChildrenTwo" cascade="all-delete-orphan">
<key column="CircularLinkOwner_compositeChildrenTwo_FK"/>
<index column="CircularLinkOwner_compositeChildrenTwo_index"/>
<one-to-many class="CircularLinkChildTwoDO"/>
</list>
<list name="compositeChildrenOne" cascade="all-delete-orphan">
<key column="CircularLinkOwner_compositeChildrenOne_FK"/>
<index column="CircularLinkOwner_compositeChildrenOne_index"/>
<one-to-many class="CircularLinkChildOneDO"/>
</list>
</class>
<class name="CircularLinkChildOneDO" table="CircularLinkChildOneDO">
<id name="id" column="id" type="string">
<generator class="assigned"/>
</id>
<many-to-one name="referenceToChildrenTwo"
column="referenceToChildrenTwo"
class="CircularLinkChildTwoDO"
cascade="save-update"/>
</class>
<class name="CircularLinkChildTwoDO" table="CircularLinkChildTwoDO">
<id name="id" column="id" type="string">
<generator class="assigned"/>
</id>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Basically in my unit test, all I am doing is this:
Code:
CircularLinkOwnerDO owner = new CircularLinkOwnerDO();
CircularLinkChildOneDO childOne = new CircularLinkChildOneDO();
CircularLinkChildTwoDO childTwo = new CircularLinkChildTwoDO();
owner.getCompositeChildrenOne().add(childOne);
owner.getCompositeChildrenTwo().add(childTwo);
childOne.setReferenceToChildrenTwo(childTwo);
Transaction txn = session.beginTransaction();
session.save(owner);
txn.commit();
Transaction txn = session.beginTransaction();
session.delete(owner);
txn.commit();
Full stack trace of any exception that occurs:Code:
java.sql.SQLException: Integrity constraint violation: FK9B36F9EE579D68C7 table: CIRCULARLINKCHILDONEDO in statement [delete from CircularLinkChildTwoDO where id='1205471E-68D6-0481-C474-688CF3432B8C']
at org.hsqldb.Trace.getError(Unknown Source)
at org.hsqldb.Result.<init>(Unknown Source)
at org.hsqldb.jdbcConnection.executeHSQL(Unknown Source)
at org.hsqldb.jdbcConnection.execute(Unknown Source)
at org.hsqldb.jdbcStatement.fetchResult(Unknown Source)
at org.hsqldb.jdbcStatement.executeUpdate(Unknown Source)
at org.hsqldb.jdbcPreparedStatement.executeUpdate(Unknown Source)
at net.sf.hibernate.impl.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:22)
at net.sf.hibernate.persister.EntityPersister.delete(EntityPersister.java:598)
at net.sf.hibernate.impl.ScheduledDeletion.execute(ScheduledDeletion.java:29)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2382)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2340)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2204)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
at HibernateTransactionImpl.commit(HibernateTransactionImpl.java:32)
at HibernateSessionImpl$TransactionProxy.commit(HibernateSessionImpl.java:178)
at TestModelBase_TestElement.delete(TestModelBase_TestElement.java:60)
at TestModel_CircularLink_TestElement.testDeleteCircularLink_1(TestModel_CircularLink_TestElement.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:289)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:523)
Now, of course I can resolve this issue by rearranging the order of the two lists in the mapping file or I can do:
Code:
childOne.setReferenceToChildrenTwo(null);
before I delete the owner from database.
But I thought this is something that hibernate should handle internally?
see topic:
http://forum.hibernate.org/viewtopic.php?t=606Now the problem gets even more trickier when there is a intermediate class: CircularLinkMiddleManDO, sitting in between the owner and childOne(see mapping below).
This time, I can only fix the problem by set null before delete. I thought I should bring up this case because the nature of this mapping is somewhat different from the first case.
Code:
<hibernate-mapping>
<class name="CircularLinkOwnerDO" table="CircularLinkOwnerDO">
<id name="id" column="id" type="string">
<generator class="assigned"/>
</id>
<many-to-one name="middle"
class="CircularLinkMiddleManDO"
column="middle"
cascade="all"/>
<list name="compositeChildrenTwo" cascade="all-delete-orphan">
<key column="CircularLinkOwner_compositeChildrenTwo_FK"/>
<index column="CircularLinkOwner_compositeChildrenTwo_index"/>
<one-to-many class="CircularLinkChildTwoDO"/>
</list>
</class>
<class name="CircularLinkMiddleManDO" table="CircularLinkMiddleManDO">
<id name="id" column="id" type="string">
<generator class="assigned"/>
</id>
<list name="compositeChildrenOne" cascade="all-delete-orphan">
<key column="CircularLinkMiddleMan_compositeChildrenOne_FK"/>
<index column="CircularLinkMiddleMan_compositeChildrenOne_index"/>
<one-to-many class="CircularLinkChildOneDO"/>
</list>
</class>
<class name="CircularLinkChildOneDO" table="CircularLinkChildOneDO">
<id name="id" column="id" type="string">
<generator class="assigned"/>
</id>
<many-to-one name="referenceToChildrenTwo"
column="referenceToChildrenTwo"
class="CircularLinkChildTwoDO"
cascade="save-update"/>
</class>
<class name="CircularLinkChildTwoDO" table="CircularLinkChildTwoDO">
<id name="id" column="id" type="string">
<generator class="assigned"/>
</id>
</class>
</hibernate-mapping>
Have I done something really stupid in the mapping file to cause this exception? Or can anyone suggest some other solution??
Many thanks!