【问题标题】:Hibernate one-to-many : On update, changed children are not updated休眠一对多:更新时,更改的子项不会更新
【发布时间】:2013-12-28 08:33:15
【问题描述】:

我有一个一对多的关系如下 -

父 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(parent)。

sessionFactory.getCurrentSession().saveOrUpdate(parent); 

当我插入一个新的父母时,它会很好地插入孩子。插入后,我将控件移回具有相同值的表单。然后,我更改了孩子的一些值并再次提交。在这种情况下,我可以(从休眠日志中)看到父级已更新,但更改后的子级未更新。

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

如果这些信息不足以理解我想要做什么,请告诉我,我会提供更多信息。

提前致谢

更新:-

我刚刚注意到 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)

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

【问题讨论】:

  • 能否展示一下为更新案例设置父子数据的代码?
  • 数据是通过 Struts2 动作从表单中设置的。除了 Struts2 配置之外,它背后没有真正的代码。我已验证更改的数据在传递给操作的对象中。
  • 你检查过hibernate触发的所有查询
  • 是的,我查过了。 Hibernate 触发插入的所有查询。但是,在更新期间,只会触发更新父项的查询。

标签: java hibernate one-to-many


【解决方案1】:

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

您可以使用以下逻辑轻松重现您遇到的异常:
会话 1 加载行。
会话 2 加载行。
会话 1 修改该行的任何列并保存它。
会话 2 修改该行并尝试保存它。现在出现了异常。
在像您的情况这样的网络环境中,这通常不是错误。当两个用户同时修改相同的数据时,就会发生这种情况。您必须捕获异常并向第二个用户提供有用的消息。

在您的情况下,您的代码中可能存在错误,在您发布的部分中看不到。
请检查:
插入和更新,它们是在同一个会话中还是在两个不同的会话中?
如果是一个会话,是否会发生另一个会话对孩子的更新?
如果有两个会话,您使用相同还是不同的 child(!) 对象实例?

你可以做什么:
- 不要在两个不同的会话中使用任何 Hibernate 数据库对象的相同实例
- 在修改之前,evict()load()refresh()Session 的所有方法)父,也许还有子。

【讨论】:

  • 非常感谢约翰娜的清晰解释。注意事项:我只有一个会话(一个用户)。我在后续保存的同一会话中收到此错误。我会尝试其他建议并让您知道。
  • 您的应用程序是 Web 应用程序吗(我猜是因为您使用的是 struts)?在 Web 应用程序中,即使只有一个用户,您也无法确定该用户的所有请求都由同一个线程执行,并且取决于您的 Hibernate 使用情况,这意味着它可以是不同的会话。所以如果还没有完成,我建议检查它是否真的是相同的会话。
【解决方案2】:

你试过cascade="all"而不是cascade="all-delete-orphan"

检查

http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/example-parentchild.html

【讨论】:

  • 能否请您提供子 hbm 和测试用例以复制此内容。我很想解决这个问题。
  • 萨托什,谢谢。我已将子 hbm 添加到初始帖子中
猜你喜欢
  • 2013-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多