如何使用cascade ="all,delete-orphan"制作hibernate集合的副本

use*_*273 13 java hibernate

我试图像这样制作一个hibernate实体A的副本:

A a = (A) session.get(A.class, id);
session.evict(a);
a.setId(null);
session.save(a);
Run Code Online (Sandbox Code Playgroud)

然而,这不起作用,我获得以下期望:

org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": com.test.A.B
Run Code Online (Sandbox Code Playgroud)

因为我有一个在实体A中定义的B实体的集合,所以可以安全地假设发生此错误:

<list name="B"  table="B" lazy="false" cascade="all,delete-orphan">
    <key column="A_ID" not-null="true"/>
    <index column="X"/>            
    <one-to-many class="com.test.B"/>
</list>
Run Code Online (Sandbox Code Playgroud)

怎么可能制作一个实体A的副本,包括它的实体B的集合,而没有hibernate对它不满意?

Dra*_*vic 2

没有这样的自动方法来复制对象。一般来说,复制的对象可能与其他对象相关联,而其他对象又与其他对象等相关联,因此您最终可能会复制数据库的很大一部分。用于复制的任何工具都需要知道对象图中的何处停止复制、不复制什么(就 Hibernate 实体而言,这些是 id、版本列等)等等。

但是,您可以利用框架来Dozer避免需要手动编写的大部分样板代码。

关于集合重新分配问题,您不能将相同的B实例集合分配给两个不同的As,因为它在逻辑上是一个many-to-many关联。这也是您需要手动处理的事情,因为它特定于您的业务用例。

另外,请确保不要在其他实体实例中重用来自一个实体实例的相同集合代理,因为 Hibernate 在内部将它们与其原始父级联系在一起 - 始终在新实例中创建一个新集合(可能包含也可能不包含相同的元素)。