首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用cascade="all,delete-orphan“复制hibernate集合

如何用cascade="all,delete-orphan“复制hibernate集合
EN

Stack Overflow用户
提问于 2017-03-22 20:58:24
回答 3查看 2K关注 0票数 13

我正在尝试制作hibernate实体A的副本,如下所示:

代码语言:javascript
复制
A a = (A) session.get(A.class, id);
session.evict(a);
a.setId(null);
session.save(a);

然而,这并不起作用,我得到了以下结论:

代码语言:javascript
复制
org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": com.test.A.B

可以放心地假设发生此错误是因为我在实体A中定义了一个B实体的集合:

代码语言:javascript
复制
<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>

如何才能复制实体A,包括实体B的集合,而不会让hibernate感到不快呢?

EN

回答 3

Stack Overflow用户

发布于 2017-04-06 13:43:45

我之前在我的项目中也遇到过同样的问题。

对我来说,将列表条目的ID设置为null是可行的。

代码语言:javascript
复制
// make copy a of aOriginal by using serialisation clone 
a.setId(null);
for (B b : a.getBs()) {
    b.setId(null);
}
session.save(a);

对于克隆本身,我使用了Apache SerializationUtils clone

原因是,hibernate试图为“复制的”实体“重用”已经持久化的列表条目。但是这个已经持久化的列表条目被链接到原始实体。因此,它尝试“更改”实体中的列表本身,因为实体已更改。但是如果列表带有"delete-orphans“注释,则不能更改列表(您只能修改列表的条目,而不能修改列表本身)。所以抛出了异常。

如果我将list-entry-IDs设置为null,它们也将被插入newley。并且复制对象层次结构(而不仅仅是主实体)。因此exeption不再被抛出。

票数 4
EN

Stack Overflow用户

发布于 2017-04-04 23:26:15

如果要复制现有实体-修改它-并将其另存为新实体,则需要深入复制该对象。您可以通过序列化对象,然后反序列化该对象来执行对象的深层复制。

代码语言:javascript
复制
public Object deepCopy(Object input) {

    Object output = null;
    try {
        // Writes the object
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(input);

        // Reads the object
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        output = objectInputStream.readObject();

    } catch (Exception e) {
        e.printStackTrace();
    }
    return output;
}
票数 2
EN

Stack Overflow用户

发布于 2017-03-31 08:13:37

没有像那样自动复制对象的方法。通常,复制的对象可以与其他对象相关联,而其他对象又进一步与其他对象相关联,等等,因此您最终可能会复制数据库的一大部分。用于复制的任何工具都需要知道在对象图中的什么位置停止复制,不复制什么(就Hibernate实体而言,这些实体是ids、版本列和类似的),等等。

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

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

此外,请确保不要在其他实体实例中重用相同的集合代理,因为Hibernate会在内部将它们绑定到它们的原始父级-始终在新实例中创建新的集合(可能包含相同的元素,也可能不包含相同的元素)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42952330

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档