2013-12-10 75 views
3

我有如下一个一对多的关系 -Hibernate的一个一对多:在更新,改变了孩子不更新

父HBM: -

<hibernate-mapping> 
    <class name="ParentClass" table="PARENT_TABLE" schema="schemaname" lazy="false"> 

     <cache usage="read-write" /> 

     <id name="id" column="PARENT_ID_ID" type="java.lang.Long"> 
      <generator class="sequence"> 
       <param name="sequence">schemaname.parent_sequence_name</param> 
      </generator> 
     </id> 

     <version name="versionNumber" column="version_num" type="java.lang.Long" insert="false" /> 
     <property name="recordStatus" column="RECORD_STATUS" type="java.lang.String" insert="false" /> 

     <list name="children" cascade="all-delete-orphan"> 
      <key column="PARENT_ID" /> 
      <list-index column="LINE_NUMBER" /> 
      <one-to-many class="ChildClass" /> 
     </list> 

     &audit; 
    </class> 
</hibernate-mapping> 

儿童HBM: -

<hibernate-mapping> 
    <class name="ChildClass" table="CHILD_TABLE" schema="schemaname" lazy="false"> 

     <id name="id" column="CHILD_ID" type="java.lang.Long"> 
      <generator class="native"> 
       <param name="sequence">schema.child_sequence_name</param> 
      </generator> 
     </id> 

     <version name="versionNumber" column="VERSION_NUMBER" type="java.lang.Long" /> 
     <property name="recordStatus" column="RECORD_STATUS" type="java.lang.String" /> 
     <property name="lineNumber" column="LINE_NUMBER" type="java.lang.Long" /> 
     <many-to-one name="parent" column="PARENT_ID" class="ParentClass" fetch="select" /> 
    &audit; 
    </class> 
</hibernate-mapping> 

我正在使用Struts进入窗体中的父窗体和子窗体并进入动作类。动作类执行.saveOrUpdate(父)。

sessionFactory.getCurrentSession().saveOrUpdate(parent); 

当我插入一个新的父项时,它插入子项很好。插入后,我将控件移回具有相同值的窗体。然后,我改变一些孩子的价值观并重新提交。在这种情况下,我可以看到(从休眠日志)父进程已更新,但更改后的子进程未更新。

Hibernate中是否有一个选项来强制更改父级更新时更改的子级?如果只有变化的孩子不能更新,我可以让所有的孩子都得到更新。

如果这些信息不足以理解我正在尝试做什么,请让我知道,我会提供更多信息。

在此先感谢

更新: -

我只注意到休眠抛出这个异常的子记录试图更新: -

Could not synchronize database state with session 
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.efleets.services.billing.domain.InvoiceBulk#206] 
    at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1761) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2403) 
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2303) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2603) 
    at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92) 
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248) 
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232) 
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140) 
    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 com.efleets.services.common.integration.GenericDAOImpl.flush(GenericDAOImpl.java:115) 

感谢。任何帮助将不胜感激。

+0

你可以在代码中为更新情况设置父数据和子数据吗? –

+0

通过Struts2操作从表单中设置数据。除Struts2配置外,没有真正的代码。我已验证已更改的数据位于传入操作的对象中。 –

+0

你有没有检查过所有的查询是否正在通过休眠被触发 –

回答

2

你的映射看起来是正确的。如果您从Child.hbm中删除version子句,您的程序可能会工作,但这不是一个解决方案,因为您的应用程序不再是正确的。

你可以很容易地用这个逻辑重现异常:
会话1加载该行。
会话2加载该行。
会话1会修改该行的任何列并将其保存。
会话2会修改该行并尝试保存该行。现在出现异常。
在像你这种情况下的网络环境中,这通常不是错误。当两个用户同时修改相同的数据时会发生这种情况。您必须捕捉异常并向第二个用户提供有用的信息。

在你的情况下,你的代码中的任何地方都可能有错误,在你发布的部分中不可见。
请检查:
插入和更新,它们是在同一个会话中还是在两个不同的会话中?
如果有一个会话,它是否会发生一个不同的会话对孩子的更新?
如果两个会话,你使用相同或不同的子(!)对象的实例吗?

你可以做什么:
- 修改之前,无论是evict()load()refresh()(的Session所有方法)的母公司,或许也 - 不要在两个不同的会议
使用任何Hibernate的数据库对象的同一实例这些孩子。

+0

非常感谢Johanna的明确解释。一个注意:我只有一个会话(一个用户)。我在后续保存中从同一会话中收到此错误。我会尝试其他建议,并让你知道。 –

+0

您的应用程序是一个Web应用程序(我猜是因为您使用的是struts)?在一个Web应用程序中,即使只有一个用户,你也不能确定这个用户的所有请求都被同一个线程所拒绝,并且这取决于你的Hibernate用法,这意味着它可以是不同的会话。所以,如果还没有完成,我建议检查它是否真的是相同的会话。 – Johanna