【发布时间】:2017-02-02 10:32:37
【问题描述】:
使用 Spring Data REST 和 Spring Data JPA,我想更新聚合根上的子实体集合。作为一个演示示例,假设我有一个 Post 实体,它与 Comment 实体具有一对多的关系。 Post 拥有自己的 Spring Data 存储库; Comment 没有,因为它只能通过 Post 访问。
由于现有的数据库设计,令人讨厌的转折是Comment 有一个复合键,包括Post 的外键。因此,即使我不需要双向关系,我也无法找到一种方法让外键成为 Comment 中复合键的一部分而没有双向关系。
带有 Lombok 注释的类如下所示:
@Entity
@Data
public class Post {
@Id
@GeneratedValue
private long id;
@OneToMany(mappedBy = "post", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Comment> comments = new HashSet<>();
private String title;
}
还有评论:
@Entity
@IdClass(Comment.CommentPk.class)
@Data
@EqualsAndHashCode(exclude = "post")
@ToString(exclude = "post")
public class Comment {
@Id
private long id;
@Id
@ManyToOne(fetch = FetchType.LAZY)
@RestResource(exported = false)
@JsonIgnore
private Post post;
private String content;
@Data
static class CommentPk implements Serializable {
private long id;
private Post post;
}
}
还有存储库:
public interface PostRepository extends JpaRepository<Post, Long> {
}
如果我尝试使用Comment 创建Post,则会发生POST_ID 不能为NULL 的异常。换句话说,它在它试图坚持的Comment 中缺少对父Post 的反向引用。
这可以通过将@PrePersist 方法添加到维护此反向引用的Post 来解决:
@PrePersist
private void maintainParentBackreference() {
for (Comment comment : this.comments) {
comment.setPost(this);
}
}
上述方法在创建新的Post 时可以正常工作,但在尝试将Comment 添加到现有的Post 时(例如使用 PUT 请求)并没有帮助,因为尝试添加时会出现以下错误插入评论:
NULL not allowed for column "POST_ID"; SQL statement:
insert into comment (content, id, post_id) values (?, ?, ?) [23502-193]
回顾一下,重现的步骤是:
- 发布一个
Post没有Comments - PUT 到创建的
PostwithComment
使用 Spring Data REST 将Comments 更新/添加到现有的Post 时,最简单的方法是什么?
可以在此处找到演示此功能的示例项目:https://github.com/shakuzen/aggregate-child-update-sample/tree/composite-key
此特定设置位于存储库的 composite-key 分支中。要使用此代码重现上述故障,您可以按照自述文件中的手动重现步骤或运行集成测试AggregateCompositeKeyUpdateTests.canAddCommentWithPut
【问题讨论】:
标签: hibernate jpa spring-data-jpa spring-data-rest