大家好,
我目前正在尝试理解,我的编码和实体模型有什么问题我使用hibernate 4.2来进行CRUD操作,只使用Generic DAO模式和带有级联ALL和orphanRemoval = true的带注释实体.我有DayPlan实体与DayToMany关系到DayPlanElement弱实体.该 DayPlanElement被保存到java.util.Set中.每个DayPlanElement都有一个属性"order".
该DayPlan也有一个实体一对多关系的人.实体Person保存到java.util中.清单.
该DayPlanElement具有一对多关系DayPlanElementEntry弱实体.java.util.Set用于保存.该人士实体也一对多关系DayPlanElementEntry弱实体.java.util.Set用于保存.该DayPlan,DayPlanElement和 人实体有ID,通过我的应用程序管理,为String.该DayPlanElementEntry弱实体具有复合编号:DayPlanElementEntryId与EmbeddedId注释,包含parentPersonId和dayPlanElementId.它
换句话说,想象一下,存在一个表,代表日计划.列是从0到24的小时数.行是人员,必须从日计划开始操作.每列都是DayPlanElement实体.每一行都是Person实体.每个单元格都是DayPlanElementEntry实体.
如果我只是添加到表新元素(也是人)并删除它(也从列表中删除它,然后调用DayPlanDAO.merge(dayPlan) - 我希望在级联和orphanRemoval) - 我没有问题.
只有当我尝试重新排序给定的人(只是删除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)
Run Code Online (Sandbox Code Playgroud)
我去了解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();
}
Run Code Online (Sandbox Code Playgroud)
....
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
我们有Id = 1的简单实体entity1 ,然后我们坚持它.然后我们创建Simple实体copy1并将其作为值放入事件缓存中.使用持久化实体*1*作为关键.然后我们创建一个Id = 2的Simple实体*2*,保持它,然后创建id为2 的copy*2*实体,并将其作为值放入事件缓存中.作为持久化实体2使用的关键.为什么这种情况是错误的,为什么会出现这种情况,必须抛出IllegalStateException?
谢谢你的帮助!
Tir*_*res 10
对于Hibernate版本4.3.4及其周围,有一个修复.只需添加此工件:
<dependency>
<groupId>com.intersult</groupId>
<artifactId>jpa-fix</artifactId>
<version>1.1</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
此修补程序将MergeEventListener替换为处理此类合并的MergeEventListener.
我的代码遇到了同样的问题.尝试此解决方案:
这可能是由两个"cascade.all"引起的.当使用DayPlan实体时,它将同时具有列表和列表,并且两者都具有1:M到DayPlanElementEntry.
因此,当DayPlanElement尝试访问时,两个"cascade.all"可能会发现DayPlanElementEntry已分配给Person,即使它与DayPlanElementEntry相同.
我希望它有所帮助.
最好的,冲
这可以通过升级到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
如果这是在测试的上下文中,我建议您在 session.flush() 之后使用 session.clear()。这将有效地清除您的会话缓存,这似乎是问题的核心。
这个问题的潜在原因(我能想到的):
| 归档时间: |
|
| 查看次数: |
16001 次 |
| 最近记录: |