如何使用cascade =“all,delete-orphan”制作hibernate集合的副本
我试图像这样制作一个hibernate实体A的副本:
A a = (A) session.get(A.class, id); session.evict(a); a.setId(null); session.save(a);
然而,这不起作用,我得到以下的经验:
org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": com.test.AB
可以安全地假设发生此错误,因为我有一个在实体A中定义的B实体的集合:
怎么可能制作一个实体A的副本,包括它的实体B的集合,而没有hibernate对它不满意?
我之前在项目中遇到了同样的问题。
对我来说,将list-entries的ID设置为null是有效的。
// 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克隆 。
原因是,hibernate试图“重用”已复制的“复制”实体的列表条目。 但是这个已经存在的列表条目链接到原始实体。 因此,它试图在实体中“更改”列表本身,因为实体已更改。 但如果使用“delete-orphans”进行注释,则无法更改列表(您只能修改列表的条目,而不能修改列表本身)。 所以抛出了exception。
如果我将list-entry-IDs设置为null,它们也将被插入newley。 并且对象层次结构(而不仅仅是主实体)是重复的。 所以不再抛出这个例子。
没有自动方式来复制这样的对象。 通常,复制的对象可以与进一步与其他对象相关联的其他对象相关联,因此您最终可能会复制数据库的大部分内容。 您用于复制的任何工具都需要知道对象图中停止复制的位置,不复制的内容(就Hibernate实体而言,它们是ID,版本列和类似物)等等。
但是,您可以使用Dozer
框架来避免手动编写的大部分样板代码。
关于集合重新分配问题,您不能将相同的B
实例集合分配给两个不同的A
,因为它在逻辑上可以是many-to-many
关联。 这也是您需要手动处理的事情,因为它特定于您的业务用例。
此外,请确保不要在其他实体实例中重用相同的集合代理,因为Hibernate会在内部将它们与原始父代绑定 – 始终在新实例中创建新集合(可能包含也可能不包含相同的元素)。
如果要复制现有实体(修改它)并将其另存为新实体,则需要深层复制该对象。 您可以通过序列化然后反序列化该对象来执行对象的深层复制。
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; }
- Java JPA GenerationType.Auto值始终为null
- Spring – slf4J:如何自动记录错误和exception?
- 如何在hibernate上指定Double的精度?
- 如何将查询映射到非实体类+实体类
- 为什么默认情况下禁用hibernate batching / order_inserts / order_updates?
- 无法导入org.hibernate.session
- 使用数据库现有表创建实体类?
- 使用Spring 3进行基于注释的事务管理和对象映射的最小Hibernate 4 XML配置?
- 带有Hibernate的org.hibernate.hql.ast.QuerySyntaxException