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()
方法来制作(浅)对象副本。 要制作深层副本,您可以编写此处提议的方法。