Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate 休眠:已将实体副本分配给其他实体_Hibernate_Merge - Fatal编程技术网

Hibernate 休眠:已将实体副本分配给其他实体

Hibernate 休眠:已将实体副本分配给其他实体,hibernate,merge,Hibernate,Merge,嗨 我目前试图理解,我的编码和实体模型有什么问题 我使用hibernate 4.2来执行CRUD操作,只使用泛型DAO模式和带注释的实体来级联ALL和orphanRemoving=true。 我有一个DayPlan实体,它与DayPlaneElement弱实体有一个omany关系。DayPlaneElement保存到java.util.Set中。每个DayPlaneElement都有一个属性“order” DayPlan与实体人也有一对一的关系。保存到java.util.列表中的实体Person

我目前试图理解,我的编码和实体模型有什么问题 我使用hibernate 4.2来执行CRUD操作,只使用泛型DAO模式和带注释的实体来级联ALL和orphanRemoving=true。 我有一个DayPlan实体,它与DayPlaneElement弱实体有一个omany关系。DayPlaneElement保存到java.util.Set中。每个DayPlaneElement都有一个属性“order”

DayPlan与实体人也有一对一的关系。保存到java.util.列表中的实体Person

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

换句话说,想象一下,存在一个表,表示一天的计划。这些列是从0到24的小时数。行是必须从日计划开始执行操作的人员。每列都是DayPlanElement实体。每一行都是Person实体。每个单元格都是DayPlanelementry实体

如果我只是向表中添加新元素(也是Persons)并删除它(也从列表中删除它,然后调用DayPlanDAO.merge(dayPlan)——我希望是级联和删除——我没有问题

只有当我尝试对给定的人员重新排序(仅删除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。hashCode()使用该Id。我只是不理解错误消息,三次将输出相同的属性-Id

我找到了for事件缓存,但现在我不了解以下用例测试:

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


我们拥有Id=1的简单实体entity1,然后我们将其持久化。然后我们创建简单实体copy1,并将其作为值放入事件缓存中。持久化实体*1*作为键使用。 然后,我们创建一个Id为2的简单实体*2*,将其持久化,然后创建Id为2的副本*2*实体,并将其作为值放入事件缓存。作为键使用持久化的entity2。 为什么这样的情况是错误的,为什么预期必须抛出非法状态异常


感谢您的帮助!

如果这是在测试上下文中,我建议您在session.flush()之后使用session.clear()。这将有效地清除会话缓存,而会话缓存似乎是问题的核心

这个问题的潜在原因(我能想到):

  • 相同的实体副本正在不同的实体键下添加到缓存中。请在EventCache.java中的put方法下设置断点以获取更多详细信息
  • 您正在使用的hibernate版本中新引入的错误

对于Hibernate版本4.3.4及更高版本,有一个解决方案。只需添加此工件:

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

com.intersult
jpa补丁
1.1

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

我的代码也有同样的问题。请尝试以下解决方案:

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

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

我希望有帮助

最好的,
Chong

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


有关更多详细信息,请参阅项目和组件之间的关系是单向的还是双向的?如果是双向的,请确保没有Cascade.MERGE调用返回到项目


删除CascadeType。从jpa配置文件中的关系中合并它将解决此问题

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

properties.put("hibernate.event.merge.entity_copy_observer", "allow");

同样的问题!请,如果你找到了解决方案-发布两个小时来寻找解决方案,而且很简单,同时也很愚蠢…谢谢,那么解决方案是什么?我也有同样的问题D:等等,什么?这解决了我的hibernate合并问题!它是如何工作的?你有关于这个解决方案的正式文档吗?
properties.put("hibernate.event.merge.entity_copy_observer", "allow");