2009-06-18 6 views
8

Wenn ich einen Datensatz aus der übergeordneten Tabelle löschen möchte ich die entsprechenden Datensätze in der untergeordneten Tabelle gelöscht werden. Wie kann ich Hibernate aus der Child-Tabelle löschen, anstatt zu versuchen, mit einer Null zu aktualisieren?Hibernate Unidirektionale Parent/Child-Beziehung - delete() Führt Update auf untergeordnete Tabelle anstelle von löschen

Ich verwende Hibernate 3, kann jedoch keine Anmerkungen zu diesem Zeitpunkt verwenden. Ich habe unten Kopien von HBM, DAO usw. beigefügt. - Vielen Dank im Voraus

Beim Versuch, Daten aus Tabellen in Eltern-/Kind-Beziehung, die ich die folgende Fehlermeldung zu löschen:

Testcase: testDelete(com.dressbarn.imbo.model.data.hibernate.dao.CharityTransferDAOTest):  Caused an ERROR 
Hibernate flushing: Could not execute JDBC batch update; uncategorized SQLException for SQL [update RMS12.DRS_CHARITY_TRANSFER_ITEM set TSF_NO=null, TSF_SEQ_NO=null where TSF_NO=?]; SQL state [72000]; error code [1407]; ORA-01407: cannot update ("RMS12"."DRS_CHARITY_TRANSFER_ITEM"."TSF_NO") to NULL 
; nested exception is java.sql.BatchUpdateException: ORA-01407: cannot update ("RMS12"."DRS_CHARITY_TRANSFER_ITEM"."TSF_NO") to NULL 

org.springframework.jdbc.UncategorizedSQLException: Hibernate flushing: Could not execute JDBC batch update; uncategorized SQLException for SQL [update RMS12.DRS_CHARITY_TRANSFER_ITEM set TSF_NO=null, TSF_SEQ_NO=null where TSF_NO=?]; SQL state [72000]; error code [1407]; ORA-01407: cannot update ("RMS12"."DRS_CHARITY_TRANSFER_ITEM"."TSF_NO") to NULL 
; nested exception is java.sql.BatchUpdateException: ORA-01407: cannot update ("RMS12"."DRS_CHARITY_TRANSFER_ITEM"."TSF_NO") to NULL 

Caused by: java.sql.BatchUpdateException: ORA-01407: cannot update ("RMS12"."DRS_CHARITY_TRANSFER_ITEM"."TSF_NO") to NULL 

     at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:498) 
     at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:12368) 
     at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48) 
     at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246) 
     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237) 
     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:143) 
     at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298) 
     at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27) 
     at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000) 
     at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338) 
     at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106) 
     at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:578) 
     at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:662) 
     at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:632) 
     at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:314) 
     at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
     at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:629) 
     at com.dressbarn.imbo.model.data.hibernate.dao.CharityTransferDAO$$EnhancerByCGLIB$$6a21cd58.delete(<generated>) 
     at com.dressbarn.imbo.model.data.hibernate.dao.CharityTransferDAOTest.testDelete(CharityTransferDAOTest.java:112) 
     at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:69) 

Meine Tabellen sind:

Eltern:

CREATE TABLE DRS_CHARITY_TRANSFER 
(
    TSF_NO   NUMBER(10)     NOT NULL Primary Key, 
    FROM_LOC  NUMBER(10), 
    CHARITY_LOC_ID NUMBER(10), 
    STATUS   VARCHAR2(1 CHAR), 
    CREATE_DATE  DATE, 
    EXT_REF_NO  VARCHAR2(30 CHAR), 
    COMMENT_DESC VARCHAR2(2000 CHAR), 
    USER_ID   VARCHAR2(30 CHAR) 
) 

Kind:

CREATE TABLE DRS_CHARITY_TRANSFER_ITEM 
(
    TSF_NO  NUMBER(10) NOT NULL PRIMARY KEY, 
    ITEM  VARCHAR2(25 BYTE) NOT NULL PRIMARY KEY, 
    TSF_SEQ_NO INTEGER, 
    TSF_QTY  INTEGER 
) 

HBM XML

<hibernate-mapping package="com.dressbarn.imbo.model.data.hibernate.transfer" schema="RMS12"> 
    <class name="CharityTransfer" table="DRS_CHARITY_TRANSFER"> 
     <id name="transferNumber" column="TSF_NO" unsaved-value="undefined"> 

     </id> 
     <property column="FROM_LOC" length="10" name="fromLocation" type="java.lang.Long"/> 
     <property column="CHARITY_LOC_ID" length="10" name="toCharityLocId" type="java.lang.Long"/> 
     <property column="STATUS" name="status" type="string"/> 
     <property column="EXT_REF_NO" name="documentNumber" type="string"/> 
     <property column="COMMENT_DESC" name="comment" type="string"/> 
     <property column="CREATE_DATE" name="createDate" type="string"/> 
     <property column="USER_ID" name="userId" type="string"/> 
    <list name="charityTransferItemList" cascade="all-delete-orphan" lazy="false"> 
     <key column="TSF_NO" /> 
     <list-index column="TSF_SEQ_NO"/> 
     <one-to-many class="CharityTransferItem" /> 
    </list> 
</class> 

<class name="CharityTransferItem" table="DRS_CHARITY_TRANSFER_ITEM"> 
    <id name="item" column="TSF_NO" unsaved-value="undefined"> 

    </id> 
    <property column="ITEM" name="item" type="string"/> 
    <property column="TSF_SEQ_NO" length="10" name="sequence" type="integer"/> 
    <property column="TSF_QTY" length="12" name="quantity" type="long"/> 
</class> 

DAO

public class CharityTransferDAO extends HibernateDaoSupport implements ICharityTransfer { 

    public void delete(CharityTransfer charityTransfer) throws IMADataException { 
     try { 
     getSessionFactory() 
       .getCurrentSession() 
       .delete(charityTransfer); 
     } 
     catch (HibernateException e) { 
     throw new IMADataException("failed to delete charity shipping information", e); 
     }  
} 

Antwort

11

traf ich diesen Fehler alle Zeit.

Setzen Sie einfach eine inverse = "true" auf die Beziehung und Ihr Problem wird verschwinden!

<list name="charityTransferItemList" inverse="true" cascade="all-delete-orphan" lazy="false" > 
     <key column="TSF_NO" /> 
     <list-index column="TSF_SEQ_NO"/> 
     <one-to-many class="CharityTransferItem" /> 
    </list> 

Grundsätzlich ist die inverse das Kind nicht existieren kann, ohne einen Elternteil sagen, Ruhezustand, wodurch überwintert, das Kind zu löschen.

Nachdem dies gesagt wurde, müssen Sie auch das Objekt "charityTransfer" aus der Sammlung des übergeordneten Objekts entfernen.

+0

Ich dachte, dass inverse nur für bidirektionale Beziehungen relevant ist. D.h., es sagt Hibernate, welche Seite der Beziehung als "König" betrachtet werden sollte. Täusche ich mich? – waxwing

+0

Mike, Vielen Dank! Das hat den Trick gemacht. Mark –

+1

Ich würde vorschlagen, dass Sie sich angewöhnen, inverse = "true" als Standard, und dann darüber nachzudenken, ob Sie es entfernen sollten oder nicht.Ich denke, ich kann an einer Hand zählen, wie oft ich das inverse = "true" nicht setzen musste. –

1

(Hinweis: Dies wurde von zwei Benutzern als falsche Antwort ausgelöst).

Hibernate docs sagen, Sie können nur die Schlüsselspalte als not-null="true" markieren:

<list name="charityTransferItemList" cascade="all,delete-orphan" lazy="false"> 
     <key column="TSF_NO" not-null="true" /> 
     <list-index column="TSF_SEQ_NO"/> 
     <one-to-many class="CharityTransferItem" /> 
</list> 

Von Hibernate doc on collections:

If the foreign key column of a association is declared NOT NULL, you must declare the mapping not-null="true" or use a bidirectional association with the collection mapping marked inverse="true". See the discussion of bidirectional associations later in this chapter for more information.

Ich denke, es auch ein Tippfehler in der Kaskade Stil (all-delete-orphan sollte all,delete-orphan).

+0

Die Annotation "not-null = true" oder "nullable = false" kontrolliert das nicht, ich habe es selbst getestet. Es wird ausschließlich von den Eigenschaften 'inverse = true' oder 'mappedBy =" fieldName "gesteuert. – Shinzul

+0

Danke :). Auch von der akzeptierten Lösung beschrieben. Ich habe die Antwort aktualisiert, um sie als ungültig zu kennzeichnen. – jjmontes