我有两个实体的关系为OneToMany
@Entity
class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", insertable = false, updatable = false)
private Long id;
@OneToMany(mappedBy = "post", fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
Set<Comment> comments = new HashSet();
public void addComment(Comment c) {
c.setPost(this);
comments.add(c);
}
}
@Entity
class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", insertable = false, updatable = false)
private Long id;
@ManyToOne
@JoinColumn(name = "post_id")
private Post post;
}
CREATE TABLE post(
id BIGINT NOT NULL DEFAULT nextval('post_id_seq') PRIMARY KEY,
title VARCHAR(50)
);
CREATE TABLE comment (
id BIGINT NOT NULL PRIMARY KEY,
post_id BIGINT NOT NULL,
text VARCHAR(255),
CONSTRAINT fk_comment_post_id
FOREIGN KEY (post_id)
REFERENCES post (id)
);
保存此实体时,一切正常,savedPost是包含注释的完整实体。
Post post = new Post();
post.setId(1L);
post.setTitle("Hello post test");
post.addComment(new Comment("Hi There");
Post savedPost = postRepository.save(post);
但是,从我决定删除该序列以在Post表中生成Post Id,并删除注释@GenerateValue并用我生成的数字设置Id的那一刻起,事情就开始陷入
CREATE TABLE post(
id BIGINT NOT NULL PRIMARY KEY,
title VARCHAR(50)
);
@Entity
class Post {
@Id
@Column(name = "id", updatable = false)
private Long id;
...
}
现在,保存帖子后,savedPost对象不再包含注释(实际上它包含一个所有字段为null的Comment(。连接似乎断了。
知道它发生在哪里以及为什么发生吗?
更新基于Simon Martinelli的代码:github.com/simasch/69978943
如果不是.save(post)
,而是调用.saveAndFlush(post)
,则注释仅返回其ID集,其余字段为空。这比我描述的行为要好,但仍然不好。
但是,如果我用@GeneratedValue
注释Post.id
并使用.save(post)
,那么一切都可以完美地工作。
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false)
private Long id;
问题可以在SimpleJpaRepository
save()
方法中找到
@Transactional
@Override
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null.");
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
在那里,它正在检查实体是否是新的。但是,当您手动设置ID时,它不会被认为是新的,因此不会调用EntityManger.persist()
,而是调用EntityManager.merge()
。
因此,您需要将CascadeType.MERGE添加到映射中
@OneToMany(mappedBy = "post", fetch = FetchType.EAGER,
cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<Comment> comments = new HashSet<>();