我的Comment实体是具有subComment设置的自联接实体。

@Entity
public class Comment {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;

@OneToMany(mappedBy = "parentComment", cascade = CascadeType.ALL)
private Set<Comment> subComments = new HashSet<>();

@ManyToOne
@JoinColumn(referencedColumnName = "id")
private Comment parentComment;

在我的addComment方法中
public ResponseEntity<Comment> addComment(Comment comment) {
    Comment currComment = commentRepository.save(comment);
    if (currComment.getParentId() != null) {
        Comment parent = commentRepository.findById(currComment.getParentId()).orElse(null);
        if (parent != null) {
            parent.addSubComment(currComment);
            currComment.setParentId(parent.getId());
            currComment.setParentComment(parent);
            commentRepository.save(parent);
        }
    }
    Comment responseComment = commentRepository.save(currComment);
    return ResponseEntity.ok(responseComment);
}

当我尝试建立反向关系(所有者)时,comment.setParentComment(parent);导致错误
comment.setParentComment(parent);导致错误:java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
完整评论实体类
@OneToMany(mappedBy = "parentComment", cascade = CascadeType.ALL)
private Set<Comment> subComments = new HashSet<>();

@ManyToOne
@JoinColumn(referencedColumnName = "id")
private Comment parentComment;

private boolean isParent;
private String parentId;

public String getParentId() {
    return parentId;
}

public void setParentId(String parentId) {
    this.parentId = parentId;
}

public Set<Comment> getSubComments() {
    return subComments;
}

public void setSubComments(Set<Comment> subComments) {
    this.subComments = subComments;
}

public Comment addSubComment(Comment comment) {
    this.subComments.add(comment);
    return this;
}

public Comment getParentComment() {
    return parentComment;
}

public void setParentComment(Comment parentComment) {
    this.parentComment = parentComment;
}

public boolean getIsParent() {
    return isParent;
}

public void setIsParent(boolean isParent) {
    this.isParent = isParent;
}

最佳答案

您似乎过于复杂了。

1)您有@JoinColumn(referencedColumnName = "id"),但这是多余的。无论如何,这就是外键引用的内容,因此您无需对其进行明确说明。不用担心,但是不要编写不需要的代码。

2)如果在新的subComment中具有parentId,则无需查找它并将其添加到父注释的列表中。您在这里缺少的概念是“拥有”实体概念。在Javadoc中查找mappedBy。由于parentComment字段执行映射,因此它定义了拥有实体。当然,它是相同的实体,但要点是控制持久性的是parentComment字段。您无需在SetsubComments中添加任何内容即可保持关系。您可以根据需要这样做,但是JPA会忽略它。您只需要设置parentComment字段。例如。

编辑:此示例使用JPA而不是Spring Data,但实际上是相同的。

您的实体只需要是:

@Entity
public class Comment {
    @Id @GeneratedValue
    private Integer id;

    @OneToMany(mappedBy="parentComment")
    private Set<Comment> subComments;

    @ManyToOne
    private Comment parentComment;

然后像这样使用它:
private void run() {
    runWrite();
    runRead();
    Comment comment = new Comment();
    comment.setId(1);
    Comment subComment = new Comment();
    subComment.setParentComment(comment);
    runSaveSubComment(subComment);
    runRead();
}
private void runWrite() {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistence");
    em = emf.createEntityManager();
    tx = em.getTransaction();
    try {
        tx.begin();
        Comment comment = new Comment();
        Comment subComment = new Comment();
        subComment.setParentComment(comment);
        em.persist(comment);
        em.persist(subComment);

        tx.commit();
    } finally {
        emf.close();
    }
}
private void runRead() {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistence");
    em = emf.createEntityManager();
    try {
        Comment comment = em.createQuery("select c from Comment c left join fetch c.subComments where c.id = :id", Comment.class).setParameter("id", 1).getSingleResult();
        System.out.println(comment + Arrays.toString( comment.getSubComments().toArray()) );
    } finally {
        emf.close();
    }
}
private void runSaveSubComment(Comment subComment) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistence");
    em = emf.createEntityManager();
    tx = em.getTransaction();
    try {
        tx.begin();
        em.persist(subComment);
        tx.commit();
    } finally {
        emf.close();
    }
}

或者如果您想使用Spring Data。
Comment comment = new Comment();
Comment sub1 = new Comment();
sub1.setParentComment(comment);
repo.save(comment);
repo.save(sub1);
Comment parentComment = repo.fetchSubCommentsById(1);
System.out.println(parentComment + Arrays.toString(parentComment.getSubComments().toArray()));
Comment sub2 = new Comment();
sub2.setParentComment(parentComment);
repo.save(sub2);
parentComment = repo.fetchSubCommentsById(1);
System.out.println(parentComment + Arrays.toString(parentComment.getSubComments().toArray()));
// or
Comment p = new Comment();
p.setId(1);
Comment sub3 = new Comment();
sub3.setParentComment(p);
repo.save(sub3);
parentComment = repo.fetchSubCommentsById(1);
System.out.println(parentComment + Arrays.toString(parentComment.getSubComments().toArray()));

09-11 18:48