当前位置: 首页 > 知识库问答 >
问题:

如何克隆JPA实体

季博
2023-03-14

我已经在数据库中保存了一个JPA实体。
我想拥有它的副本(具有不同的id),并修改了一些字段。

最简单的方法是什么?例如:

  • 将它的@Id字段设置为null并持久化它会起作用吗?
  • 我是否必须为实体创建一个克隆方法(复制除@Id之外的所有字段)?
  • 还有其他方法吗(比如使用克隆框架)?

共有3个答案

戚升
2023-03-14

您最好使用复制构造函数并精确控制需要克隆的属性。

因此,如果您有一个像这样的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<PostComment> 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<Tag> 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并将其用作新帖子的模板时,克隆注释没有意义:

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());
}

这是解决实体克隆/复制问题的最佳方法。任何其他试图使此过程完全自动化的方法都忽略了一点,即并非所有属性都值得复制。

邵旺
2023-03-14

使用EclipseLink时,您可以使用非常方便的复制组功能

http://wiki.eclipse.org/EclipseLink/Examples/JPA/AttributeGroup#CopyGroup

一个很大的好处是,如果不做太多的修改,它也可以正确地克隆私人拥有的关系。

这是我的代码,克隆一个播放列表及其私人拥有的@OneToMany关系只需几句话:

public Playlist cloneEntity( EntityManager em ) {
    CopyGroup group = new CopyGroup();
    group.setShouldResetPrimaryKey( true );
    Playlist copy = (Playlist)em.unwrap( JpaEntityManager.class ).copy( this, group );
    return copy;
}

请确保您使用持久性()来保存这个新对象,合并()不起作用。

夏经武
2023-03-14

使用EntityManager.detach。它使bean不再链接到EntityManager。然后将Id设置为新Id(如果自动,则为null),更改您需要的字段并持久化。

 类似资料:
  • 问题内容: 我有一个JPA实体已经存在于数据库中。 我想要一个副本(具有不同的ID),并修改了某些字段。 最简单的方法是什么?喜欢: 将其设置为字段并坚持下去会起作用吗? 我是否需要为实体创建一个克隆方法(复制以外的所有字段)? 还有其他方法(例如使用克隆框架)吗? 问题答案: 使用。它使bean不再链接到EntityManager。然后将ID设置为新ID(如果为自动,则为null),更改所需的字

  • 本文向大家介绍如何实现对象克隆?相关面试题,主要包含被问及如何实现对象克隆?时的应答技巧和注意事项,需要的朋友参考一下 实现 Cloneable 接口并重写 Object 类中的 clone() 方法。 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

  • 问题内容: 我有一个其中包含许多bufferedimages的对象,我想创建一个新对象,将所有bufferedimages复制到新对象中,但是这些新图像可能会更改,并且我不希望通过更改原始对象图像来更改新对象图像。 明白了吗? 这有可能做到吗,有人可以建议一个好方法吗?我曾经想到过getSubImage,但在某处阅读过,该子映像的任何更改都被重新关联回了父映像。 我只希望能够获得BufferedI

  • 问题内容: 如何使用ES6克隆Javascript类实例。 我对基于jquery或$ extend的解决方案不感兴趣。 我见过很多关于对象克隆的讨论,这些讨论表明问题非常复杂,但是使用ES6时,会出现一个非常简单的解决方案-我将其放在下面,看看人们是否认为它令人满意。 编辑:有人建议我的问题是重复的;我看到了这个答案,但它已有7年历史,并且使用ES6之前的js涉及非常复杂的答案。我建议我的问题(允

  • 问题内容: 如何克隆 Java并同时在Java中克隆其项目? 例如,我有: 我希望其中的对象与狗列表中的对象不同。 问题答案: 你将需要迭代这些项目,然后逐个克隆它们,然后将克隆放入结果数组中。 显然,要使该方法起作用,你将必须使你的类实现接口并重写该方法。

  • 问题内容: 如果克隆数组,我将使用 我想知道如何在nodejs中克隆对象。 问题答案: 对于不需要压缩每一滴性能的实用程序和类,我经常作弊,只是使用JSON执行深层复制: 这不是唯一的答案,也不是最优雅的答案。所有其他答案都应考虑成为生产瓶颈。但是,这是一个快速而肮脏的解决方案,非常有效,并且在大多数情况下(我会克隆属性的简单哈希值)很有用。