Hibernate使用新生成的ID将对象值复制到新对象中

我正在使用带有一些嵌套表的单列pk的关系数据库。 我需要在项目中添加简单的归档。 归档仅在应用程序到达特定状态时发生,因此我希望将现有的hibernate对象复制到新实例中,新实例将使用新ID保存,同时保留现有对象。 我似乎无法弄清楚如何将现有对象复制到新实例,而无需手动设置每个新的实例字段。 有人知道这样做的简单方法吗?

我也在使用Hibernate,我得到了同样的要求。 我遵循的是实现Cloneable 。 下面是如何执行此操作的代码示例。

 class Person implements Cloneable { private String firstName; private String lastName; public Object clone() { Person obj = new Person(); obj.setFirstName(this.firstName); obj.setLastName(this.lastName); return obj; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } } 

或者你可以去基于reflection的解决方案,但我不会建议。 查看此网站了解更多详情。

只需检索对象,将其分离,将id设置为null并保持它。

 MyEntity clone = entityManager.find(MyEntity.class, ID); entityManager.detach(clone); clone.setId(null); entityManager.persist(clone); 

如果您的对象具有oneToMany关系,则必须为所有子项重复操作,但设置父对象id(在persist调用之后生成)而不是null。

当然,您必须删除OneToMany关系中的任何CASCADE persist ,否则您的持久性将在DB或fk约束失败中创建所有子项的重复项。

您可以克隆该对象并擦除该ID并将其保存回来,以便分配新的ID。

所以

 Person person = EmployeeDAO.get(empId); Person newPersonCopy = person.createCopyWithNoId() EmployeeDAO.add(newPersonCopy); 

在这种情况下, createCopyWithNoId()将创建对象的克隆并将Id字段设置为null。 当你现在添加新的克隆时,hibernate引擎会将其视为一个新对象,并且数据库将分配一个新的主键。

请注意我避免调用方法克隆,因为我们操作Id(将其设置为null)时出来的并不是一个精确的克隆;

另一种方法是添加一个构造函数,该构造函数接收了person类型的对象并创建了一个新对象,但只是没有设置Id字段,使其保留默认值null。 再次坚持使用DAO。

看看以下链接。 最强大的克隆机制之一,可以通过hibernate以最有效的方式使用

http://thoughtfulsoftware.blogspot.in/2013/05/using-variable-depth-copy-to-prevent.html

您可以克隆该对象是否可克隆,或者您可以为要复制的对象定义一个方法/构造函数,并将其自身的参数复制到一个新实例并将其返回给您。

正如我在本文中所解释的那样,在克隆实体时,使用其他人建议的detach或深度克隆并不是一种方法。 如果您尝试使此过程完全自动化,那么您将错过并非所有属性都值得重复的观点。

因此,最好使用复制构造函数并准确控制需要克隆的属性。

所以,如果你有像这样的Post实体:

 @Entity(name = "Post") @Table(name = "post") public class Post { @Id @GeneratedValue private Long id; private String title; @OneToMany( mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true ) private List comments = new ArrayList<>(); @OneToOne( mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY ) private PostDetails details; @ManyToMany @JoinTable( name = "post_tag", joinColumns = @JoinColumn( name = "post_id" ), inverseJoinColumns = @JoinColumn( name = "tag_id" ) ) private Set tags = new HashSet<>(); //Getters and setters omitted for brevity public void addComment( PostComment comment) { comments.add(comment); comment.setPost(this); } public void addDetails( PostDetails details) { this.details = details; details.setPost(this); } public void removeDetails() { this.details.setPost(null); this.details = null; } } 

在复制Post并将其用作新模板的模板时克隆comments是没有意义的:

 Post post = entityManager.createQuery( "select p " + "from Post p " + "join fetch p.details " + "join fetch p.tags " + "where p.title = :title", Post.class) .setParameter( "title", "High-Performance Java Persistence, 1st edition" ) .getSingleResult(); Post postClone = new Post(post); postClone.setTitle( postClone.getTitle().replace("1st", "2nd") ); entityManager.persist(postClone); 

您需要添加到Post实体的是复制构造函数:

 /** * Needed by Hibernate when hydrating the entity * from the JDBC ResultSet */ private Post() {} public Post(Post post) { this.title = post.title; addDetails( new PostDetails(post.details) ); tags.addAll(post.getTags()); } 

因此,复制构造函数是解决实体克隆/复制问题的最佳方法。