9

大家好,

我目前尝试了解,我的编码和实体模型有什么问题我使用休眠 4.2 进行 CRUD 操作,仅使用 Generic DAO 模式和带有级联 ALL 和 orphanRemoval=true 的注释实体。我的DayPlan实体与DayPlanElement弱实体具有 OneToMany 关系。DayPlanElement 保存在 java.util.Set 中。每个DayPlanElement都有一个属性“order”。

DayPlan还与实体Person具有OneToMany关系。实体Person保存到 java.util 中。列表

DayPlanElement与 DayPlanElementEntry实体具有 OneToMany 关系。java.util.Set 用于保存。Person实体也是 OneToMany 关系到DayPlanElementEntry 的弱实体。java.util.Set 用于保存。DayPlan 、DayPlanElementPerson实体具有由我的应用程序管理的 ID 作为字符串。DayPlanElementEntry弱实体有一个复合 Id: DayPlanElementEntryId用 EmbeddedId 注解,包含 parentPersonId 和 dayPlanElementId。它

换句话说想象一下,存在一张表,代表一天的计划。列是从 0 到 24 的小时数。行是必须从日计划进行操作的人员。每列都是 DayPlanElement 实体。每行都是 P​​erson 实体。每个单元格都是 DayPlanElementEntry 实体。

如果我只是将新元素(也是 Persons)添加到表中并删除它(也将其从 List 中删除,然后调用 DayPlanDAO.merge(dayPlan) - 我希望在级联和 orphanRemoval 上) - 我没有问题。

仅当我尝试重新排序给定的 Persons(仅删除 java.util.List 中的操作)和调用 DayPlanDAO.merge(dayPlan) 时 - 将引发以下异常:

Caused by: java.lang.IllegalStateException: 
Error occurred while storing entity 
[DayPlanElementEntry [getDayPlanMode()=NONE, getCompositeId()=DayPlanElementEntryId [parentPersonId=874c8eac-8796-478d-a4d5-dd011f7d6a4b, dayPlanElementId=ab683a25-633e-419e-89b6-4aef7829d4f6], hashCode=-2039940039]]. 

An entity copy 
[org.hw.domain.DayPlanElementEntry#DayPlanElementEntryId [parentPersonId=874c8eac-8796-478d-a4d5-dd011f7d6a4b, dayPlanElementId=ab683a25-633e-419e-89b6-4aef7829d4f6]] 

was already assigned to a different entity 

[org.hw.domain.DayPlanElementEntry#DayPlanElementEntryId [parentPersonId=874c8eac-8796-478d-a4d5-dd011f7d6a4b, dayPlanElementId=ab683a25-633e-419e-89b6-4aef7829d4f6]].

       at org.hibernate.event.internal.EventCache.put(EventCache.java:192)

       at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:285)

       at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151)

我调试EventCache,寻找问题解决方案,只检查实现的equals()和hashCode()方法 - 没有成功:-((注意,我为equals()方法使用Id。例如DayPlanElementEntry的复合id。那个id由 hashCode() 使用。我只是不明白错误消息,三次将输出相同的属性 - ids!

我找到了事件缓存的测试类,但现在我不明白以下用例测试:

    @Test
public void testCopyAssociatedWith2ExistingEntities() {
session.getTransaction().begin();
Simple entity1 = new Simple( 1 );
session.persist( entity1 );
Simple copy1 = new Simple( 1 );
cache.put(entity1, copy1);
Simple entity2 = new Simple( 2 );
session.persist( entity2 );
Simple copy2 = new Simple( 2 );
cache.put( entity2, copy2 );
session.flush();

try {
cache.put( entity1, copy2 );
fail( "should have thrown IllegalStateException");
}
catch( IllegalStateException ex ) {
// expected
assertTrue( ex.getMessage().startsWith( "Error occurred while storing entity [org.hibernate.event.internal.EventCacheTest$Simple#1]." ) );
}
session.getTransaction().rollback();
}

……

    @Entity
private static class Simple {
@Id
private int value;

public Simple(int value) {
this.value = value;
}

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}
}

我们有Id=1的简单实体 entity1 ,然后我们将其持久化。然后我们创建简单实体 copy1 并将其作为值放入事件缓存中。作为关键的持久实体* 1 * 使用。然后我们创建一个Id=2的 Simple entity* 2 * ,将其持久化,然后创建 id 为 2 的 copy* 2 * 实体并将其作为值放入事件缓存中。作为键使用的持久实体2。为什么这种情况是错误的,为什么必须抛出 IllegalStateException?

谢谢你的帮助!

4

6 回答 6

10

对于 Hibernate 4.3.4 及更高版本,有一个修复程序。只需添加此工件:

<dependency>
    <groupId>com.intersult</groupId>
    <artifactId>jpa-fix</artifactId>
    <version>1.1</version>
</dependency>

此修复将 MergeEventListener 替换为处理此类合并的此类。

于 2014-03-26T13:16:27.773 回答
9

这可以通过升级到 hibernate 4.2.15 / 4.3.6 或更高版本来解决,并将以下行添加到您的 persistence.xml:

<property name="hibernate.event.merge.entity_copy_observer" value="allow"/>

有关详细信息,请参阅https://hibernate.atlassian.net/browse/HHH-9106

于 2015-08-24T18:55:14.363 回答
7

我的代码也有同样的问题。试试这个解决方案:

它可能是由两个“cascade.all”引起的。当使用 DayPlan 实体时,它将同时具有列表和列表,并且都具有 1:M 到 DayPlanElementEntry。

因此,当 DayPlanElement 尝试访问它时,两个“cascade.all”可能会发现 DayPlanElementEntry 已分配给 Person,即使它是相同的 DayPlanElementEntry。

我希望它有所帮助。

最好的,冲

于 2014-03-31T18:45:10.830 回答
1

If this is in the context of a test, I suggest you follow your session.flush() with a session.clear(). This will effectively clear your session cache which seems to be at the core of the issue.

Potential reasons for this issue(I can think of):

  • The same entity copy is being added to the cache under different entity keys. Set a breakpoint under the put method found in EventCache.java to get more details.
  • A newly introduced bug in the version of hibernate that you are using.
于 2014-02-12T06:34:04.067 回答
1

在 jpa 配置文件中添加下面它将解决问题。

在多对多关系中,如果同一个实体在与已经存在的实体执行合并操作时重复,休眠将无法区分它们,直到我们帮助他获得差异。

properties.put("hibernate.event.merge.entity_copy_observer", "allow");
于 2017-09-09T18:46:40.490 回答
0

您在项目和组件之间的关系是单向的还是双向的?如果它是双向的,请确保您没有 Cascade.MERGE 调用返回到 Item。

从您的关系中删除 CascadeType.Merge

于 2016-06-07T09:47:49.650 回答