JPA中的深层复制

我想在JPA中制作一个实体的深层副本。 我在这里找到了一个有趣的讨论: http : //forums.java.net/jive/thread.jspa?messageID = 253092&tstart = 0

这听起来像提议的解决方案是将所有@ Id设置为零。 这是我的基本代码:

//Start a JPA session. EntityManager em= emf.createEntityManager(); em.getTransaction().begin(); //Get the object I want to copy. MyClass myObject=em.find(MyClass.class,id); //Use reflection to find @Id's and set them to zero for all @OneToMany and @OneToOne relations. //TODO: write the ugly recursive code to do this. //Hoping this will create a deep copy. em.merge(myObject); //Close the session. em.getTransaction().commit(); em.close(); 

这是一个好策略吗? 可能有人已经写过这个TODO代码,他们可以共享???

谢谢!

我不确定是否将已管理对象的ID清零是一个好主意,尤其是。 当您的实体没有将equals()定义为ID相等时。 JPA实现可能已经将托管对象放在某个缓存中,并且在使用那里的对象ID时去了beserk。

我相信按照RK的答案并真正复制对象会更安全。

我解决了这个问题。

我创建了一个组件,它根据包的注释( javax.persistence )为您完成整个过程。

组件已将实体的id设置为null。 他根据每个属性关系@OneToMany@ManyToMany@ManyToMany的类型对要应用的算法进行所有分析。

 Person person = personDAO.find(1); PersistenceCloner cloner = new PersistenceCloner(person); Person personCopy = cloner.generateCopyToPersist(); 

下载 JAR和SOURCES: jpa-entitycloner

如果对象实现了Serializable,则可以使用writeObject()和readObject()来进行深层复制。 我们有一个数据传输对象层次结构,并通过抽象超类(DTO)中的此方法支持深层复制:

 /** * Reply a deep copy of this DTO. This generic method works for any DTO subclass: * * Person person = new Person(); * Person copy = person.deepCopy(); * * Note: Using Java serialization is easy, but can be expensive. Use with care. * * @return A deep copy of this DTO. */ @SuppressWarnings("unchecked") public  T deepCopy() { try { ObjectOutputStream oos = null; ObjectInputStream ois = null; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(this); oos.flush(); ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); return (T) ois.readObject(); } finally { oos.close(); ois.close(); } } catch ( ClassNotFoundException cnfe ) { // Impossible, since both sides deal in the same loaded classes. return null; } catch ( IOException ioe ) { // This has to be "impossible", given that oos and ois wrap a *byte array*. return null; } } 

(我确信有人会找到可能发生这些例外的原因。)

其他序列化库(例如,XStream)可以以相同的方式使用。

我能够按照问题中的描述获得深层复制。 有必要急切加载整个图形并将@ Id重置为null或零。 我发现Hibernate SessionFactory实际上有方法来帮助这个过程。

以上针对深层复制的其他建议似乎不起作用。 当然,问题可能出在键盘和椅子之间。 但它现在正在运作。

感谢大家!

你为什么想做这个? 这听起来有点像黑客攻击。

这就是说Apache Commons BeanUtils包含cloneBean()copyProperties()方法来制作(浅)对象副本。 要制作深层副本,您可以编写此处提议的方法。