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

Spring Data和JPA中的递归关系?

文嘉禧
2023-03-14

我的注释实体是自连接的,它有一个子元素集合。

@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(家长) 导致错误

comment.set父母评论(父);正在导致一个错误:java.lang.IllegalStateExcture:在响应提交后不能调用sendError()

完整注释实体类

@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;
}

共有2个答案

诸葛皓
2023-03-14

你似乎把事情复杂化了。

1) 您有@JoinColumn(referencedColumnName=“id”),但这是多余的。这就是外键引用的内容,所以不需要明确说明。不用担心,但不要编写你不需要的代码。

2) 如果在a new子命令中有parentId,则无需查找它并将其添加到父注释列表中。这里缺少的概念是“拥有”实体概念。查看Javadoc中的mappedBy。由于parentComment字段进行映射,因此它定义了所属实体。诚然,它是同一个实体,但关键是控制持久性的是parentComment字段。不需要向子命令的集合中添加任何内容,就可以保持关系。你可以这样做,如果你想,但JPA会忽略它。只需设置parentComment字段。例如。

编辑:这个例子使用JPA而不是Spring数据,但在引擎盖下是一样的。

您的实体只需要:

@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数据。

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

梁成双
2023-03-14
@ManyToOne
@JoinColumn(referencedColumnName = "id")
@JsonBackReference
private Comment parentComment;

添加了@JsonBackReference来解决java问题。lang.IllegalStateException:在提交响应后无法调用sendError()error。父级注释也可以查看子命令集。

 类似资料:
  • 我试图创建一个包含问题的SQL关系,每个问题可以有一个或多个备选项,但当我从REST API调用它时,看看发生了什么:REST调用 以下是我的问题和备选模式: 模型

  • 问题内容: 我接下来的两个实体之间具有OneToOne关系: 我正在尝试运行以下代码: 但是我得到这个错误: 我可以“解决”它,将代码更改为: 我的问题是,哪种方法可以持久保持OneToOne关系?在我的代码中,为什么要保存关系的两个部分以使其起作用? 问题答案: 再来一次。 每个双向关联都具有两个方面:所有者方面和相反方面。反面是具有属性的那一面。所有者方是另一方。JPA / Hibernate

  • 问题内容: JPA 2是否具有运行递归查询的任何机制? 这是我的情况:我有一个实体E,其中包含一个整数字段x。它还可能具有通过@OneToMany映射的E类型的子代。我想做的是通过主键找到一个E,并获取其x的值以及所有后代的x值。有没有办法在单个查询中执行此操作? 我正在使用Hibernate 3.5.3,但我不希望在Hibernate API上没有任何明确的依赖关系。 编辑:根据这一项目,Hib

  • 我得到了错误下的无限递归。 下面是我的代码 另一个班 我无法理解为什么在UI上获取此值时会出现此错误。

  • 问题背景 之前做springboot项目在操作数据库方面一直在使用的是Mybatis,最近在查阅资料的时候接触到了SpringData JPA与SpringData JDBC,想问一下大佬们,这三个框架如何选型

  • 当尝试将具有双向关联的JPA对象转换为JSON时,我不断得到 我所发现的就是这条线索,它的基本结论是建议避免双向关联。有没有人有办法解决这个spring bug? ------编辑2010-07-24 16:26:22------- 代码片段: 业务对象1: 业务对象2: 控制器: JPA-见习DAO的实施: 坚持不懈xml