@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并将其用作新模板时,克隆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);
/**
* 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());
}
8条答案
按热度按时间odopli941#
使用
EntityManager.detach
。它使bean不再链接到EntityManager。然后将Id设置为新的Id(如果自动设置,则为null),更改所需的字段并保持。ykejflvf2#
最好使用复制构造函数并精确控制需要克隆的属性。
因此,如果有一个
Post
实体,如下所示:复制
Post
并将其用作新模板时,克隆comments
没有意义:需要添加到
Post
实体的是copy constructor
:这是解决实体克隆/复制问题的最佳方法。试图使此过程完全自动化的任何其他方法都忽略了并非所有属性都值得复制这一点。
vwkv1x7d3#
在使用EclipseLink时,您可以使用非常方便的CopyGroup-Feature:
http://wiki.eclipse.org/EclipseLink/Examples/JPA/AttributeGroup#CopyGroup
一个很大的好处是,没有太多的拨弄它适当地克隆私人拥有的关系,太。
这是我的代码,克隆一个具有私有@ OneToMany关系的播放列表只需要几行代码:
确保使用persist()保存这个新对象,merge()不起作用。
ql3eal8s4#
我今天面临同样的问题:我在数据库中有一个实体,我想:
我成功地完成了以下步骤:
备注:如果我使用'persist'而不是'merge',最后一步(克隆持久性)不起作用,即使我在调试模式中注意到克隆id在'persist'命令后已更改!
我仍然面临的问题是,在分离第一个实体之前,尚未对其进行修改。
kh212irz5#
您可以使用Orika这样的Map框架。http://orika-mapper.github.io/orika-docs/ Orika是一个Java beanMap框架,可以递归地将数据从一个对象复制到另一个对象。它易于配置,并提供了各种灵活性。
以下是我在项目中使用它的方式:添加了一个依赖项:
然后在代码中使用它,如下所示:
如果您有许多需要这种克隆的用例,这可能会有所帮助。
ryevplcw6#
正如已接受答案的注解中提到的,detatch将忽略对托管实体的未刷新更改。
这里有
BeanUtils.copyProperties(Object source, Object target)
。这将允许您在不篡改entityManager的情况下进行浅层复制。**编辑:**引用自api文档:此方法用于执行属性得“浅层复制,“因此不会复制复杂属性(例如,嵌套属性).
This博客文章可能会告诉你更多关于深度复制java对象的信息。
o2rvlv0m7#
我只是尝试将id设置为null,并且成功了
将id设置为null使其保存到具有新id的新记录中,因为我已自动生成它。
bweufnob8#
ModelMapper库可用于此目的。
只需添加Maven依赖项