Hibernate version:
3.0
Mapping documents:
For superclass:
<hibernate-mapping>
<class abstract="true" name="org.scforge.crm.core.domain.impl.DefaultCRMEntity" table="CRMENTITY" entity-name="org.scforge.crm.core.domain.CRMEntity">
<id name="id" column="ID" type="long">
<generator class="native" />
</id>
<property name="salutation" column="SALUTATION" type="string" />
<property name="firstName" column="FIRSTNAME" type="string" />
<property name="middleName" column="MIDDLENAME" type="string" />
<property name="lastName" column="LASTNAME" type="string" />
<property name="preferredName" column="PREFERREDNAME" type="string" />
<property name="leadSource" column="LEADSOURCE" type="string" />
<property name="title" column="TITLE" type="string" />
<property name="department" column="DEPARTMENT" type="string" />
<property name="birthDate" column="BIRTHDATE" type="date" />
<property name="syncContact" column="SYNCCONTACT" type="boolean" />
<property name="doNotCall" column="DONOTCALL" type="boolean" />
<property name="officePhone" column="OFFICEPHONE" type="string" />
<property name="mobilePhone" column="MOBILEPHONE" type="string" />
<property name="homePhone" column="HOMEPHONE" type="string" />
<property name="faxPhone" column="FAXPHONE" type="string" />
<property name="pagerPhone" column="PAGERPHONE" type="string" />
<property name="otherPhone" column="OTHERPHONE" type="string" />
<property name="emailAddress" column="EMAILADDR" type="string" />
<property name="altEmailAddress" column="ALTEMAILADDR" type="string" />
<property name="emailOptOut" column="EMAILOPTOUT" type="boolean" />
<property name="invalidEmail" column="INVALIDEMAIL" type="boolean" />
<property name="description" column="DESCRIPTION" type="string" />
<property name="comments" column="COMMENTS" type="string" />
<one-to-one name="shippingAddress" class="org.scforge.crm.core.domain.CRMAddress"></one-to-one>
<one-to-one name="mailingAddress" class="org.scforge.crm.core.domain.CRMAddress"></one-to-one>
</class>
</hibernate-mapping>
For subclass:
<hibernate-mapping>
<joined-subclass name="org.scforge.crm.core.domain.impl.DefaultCRMContact" table="CRMCONTACT" entity-name="org.scforge.crm.core.domain.CRMContact" extends="org.scforge.crm.core.domain.CRMEntity">
<key column="CRMCONTACTID" />
<one-to-one name="reportsTo" class="org.scforge.crm.core.domain.CRMContact"></one-to-one>
<property name="assistant" column="ASSISTANT" type="string" />
<property name="assistantPhone" column="ASSISTANTPHONE" type="string" />
<property name="assistantEmail" column="ASSISTANTEMAIL" type="string" />
</joined-subclass>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
/* delete all instances using the superclass type */
Query query = session.createQuery( "delete from " + new defaultCRMEntity().getEntityName() );
query.executeUpdate();
Full stack trace of any exception that occurs:
org.hibernate.exception.ConstraintViolationException: could not execute update query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:63)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.hql.ast.UpdateStatementExecutor.execute(UpdateStatementExecutor.java:99)
at org.hibernate.hql.ast.QueryTranslatorImpl.executeUpdate(QueryTranslatorImpl.java:297)
at org.hibernate.impl.SessionImpl.executeUpdate(SessionImpl.java:871)
at org.hibernate.impl.QueryImpl.executeUpdate(QueryImpl.java:89)
at org.scforge.crm.core.domain.home.impl.DefaultCRMEntityHomeTest.testFindAllEntities(DefaultCRMEntityHomeTest.java:106)
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:585)
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 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: com.ibm.db2.jcc.b.SQLException: A parent row cannot be deleted because the relationship "PRHODES.CRMCONTACT.FKF61588210A8FD72" restricts the deletion.
at com.ibm.db2.jcc.b.ce.d(ce.java:975)
at com.ibm.db2.jcc.a.bd.k(bd.java:312)
at com.ibm.db2.jcc.a.bd.a(bd.java:61)
at com.ibm.db2.jcc.a.r.a(r.java:64)
at com.ibm.db2.jcc.a.bq.c(bq.java:217)
at com.ibm.db2.jcc.b.cf.C(cf.java:1109)
at com.ibm.db2.jcc.b.cf.a(cf.java:1505)
at com.ibm.db2.jcc.b.cf.executeUpdate(cf.java:322)
at org.hibernate.hql.ast.UpdateStatementExecutor.execute(UpdateStatementExecutor.java:76)
... 19 more
Name and version of the database you are using:
DB2 8.1.0
Situation: I have an inheritance relationship, modeled using table per subclass technique. The CRMContact class extends CRMEntity. (there are also other subclasses of CRMEntity, such as CRMLead). What I want is to be able to delete all instances of all classes that extend CRMEntity, by doing something like:
Query delQuery = session.createQuery( "delete from CRMEntity" );
query.executeUpdate();
However, my first attempt at doing this generated the error above. It seems that the database won't delete the row from CRMENTITY table, because of the foreign key relation with a row in CRMCONTACT. So my question is, is there a way to instruct Hibernate to delete the subclass instance first, so the superclass instance can be deleted?
I was able to make this work by altering my database constraint to use ON DELETE CASCADE, but this doesn't really seem like the right solution. It works, but it kinda violates the idea of Hibenate abstracting away the database. Granted, all abstractions leak, and if this is the only solution, then that's OK. I just pose this question because I suspect that I'm missing something in regards to Hibernate.. it "knows" about the superclass - > subclass relation, so I am thinking it probably knows how to manage this situation...
Any input is highly appreciated.
|