【问题标题】:Hibernate Unidirectional Parent/Child relationship - delete() performs update on child table instead of deleteHibernate 单向父/子关系 - delete() 对子表执行更新而不是删除
【发布时间】:2010-11-04 00:21:05
【问题描述】:

如果我从父表中删除一条记录,我希望删除子表中的相应记录。如何让 Hibernate 从 Child 表中删除而不是尝试使用 null 进行更新?

我正在使用 Hibernate 3,但目前无法使用注释。我在下面附上了 HBM、DAO 等的副本。 -- 先谢谢了

尝试从父/子关系中的表中删除数据时,出现以下错误:

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)

我的桌子是:

家长

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)
)

孩子:

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);
      }    
}

【问题讨论】:

    标签: java hibernate mapping one-to-many


    【解决方案1】:

    一直都遇到了这个错误。

    只需在关系上加上一个 inverse="true",您的问题就会消失!

    <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>
    

    基本上相反的情况会告诉hibernate,孩子不能没有父母而存在,从而导致hibernate删除孩子。

    话虽如此,您还需要从父集合中删除charityTransfer 对象。

    【讨论】:

    • 我认为逆只与双向关系有关。即,它告诉 Hibernate 关系的哪一方应该被认为是“国王”。我弄错了吗?
    • 我建议你养成将 inverse="true" 设为默认值的习惯,然后再考虑是否应该删除它。我想我一方面可以数出我不必输入 inverse="true" 的次数。
    • 我发现这篇文章对逆运算的工作原理非常有见地。 blogs.warwick.ac.uk/colinyates/entry/… 通常,在双向一对多上设置 inverset=true 是个好主意。
    【解决方案2】:

    (注意:这已被两个用户作为错误答案提出)。

    Hibernate 文档说您可以将键列标记为 not-null="true"

    <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>
    

    来自Hibernate doc on collections

    如果声明了关联的外键列 NOT NULL,您必须声明映射 not-null="true" 或使用 与标记的集合映射的双向关联 逆=“真”。见后面对双向关联的讨论 在本章中了解更多信息。

    我还认为您的级联样式中有一个错字(all-delete-orphan 应该是 all,delete-orphan)。

    【讨论】:

    • not-null=truenullable=false 注释无法控制这一点,我自己测试过。它由inverse=truemappedBy="fieldName" 属性专门控制。
    • 谢谢:)。也由接受的解决方案描述。我已更新答案以将其标记为无效。
    猜你喜欢
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多