JPA:使用 JoinTable 删除 OneToMany 关系的所有实体

时间:2021-06-23 21:37:44

标签: hibernate jpa

在我的 Spring/MySql 系统中,我有一些 Jpa 实体,它们通过父关系上的 joinTable 加入一个 OneToMany 关系。在这种情况下,一个帖子有很多评论。

@Data
@Entity
@Table(name = "post")
public class Post implements Serializable {

    @Id
    @Column(name = "post_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval = true)
    @JoinTable(
            name = "post_comments",
            joinColumns = @JoinColumn(name = "post_id"),
            inverseJoinColumns = @JoinColumn(name = "comment_id")
    )
    @OrderBy("date ASC")
    private List<Comment> scores = new ArrayList<>();
}

@Entity
@Table(name = "comment")
@EqualsAndHashCode(of = {"id","date","value"},callSuper = false)
public class Comment implements Serializable {

    @Id
    @Column(name = "comment_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "date")
    private LocalDate date;

    @Column(name = "value")
    private String value;
}

如果我然后尝试删除 Post 实体,我遇到的问题是生成的 SQL 尝试删除仍在连接表中的注释,从而触发外键冲突。

org.springframework.dao.DataIntegrityViolationException: could not execute batch; SQL [delete from comment where comment_id=?]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute batch
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:296)
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`ci_cadreon_reach_optimization`.`post_comments`, CONSTRAINT `fk_post_comments_comment_id` FOREIGN KEY (`comment_id`) REFERENCES `comment` (`comment_id`) ON DELETE RESTRICT ON UPDAT)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)

什么是正确的方法:

  1. 删除连接表条目
  2. 删除连接表左侧父关系实体
  3. 删除连接表右侧的子关系实体

注意事项:

  1. 还有其他实体通过 oneToMany 关系进行评论,但实体之间不共享评论。
  2. 这就是通过连接表建立关系而不是将帖子的 ID 直接放在评论上的原因。

我将尝试从 Post 端的集合中删除评论,然后保存以查看这是否可以作为一种解决方法,但如果可能的话,我希望通过 JPA 配置自动执行此操作。

1 个答案:

答案 0 :(得分:0)

调用 post.getComments().clear(),保存帖子,然后删除帖子是对我有用的过程(如果有更好的方法,请告诉我!)。 >

我相信,当 @JoinTable 存在时,告诉 Hibernate 首先删除连接表条目然后删除实体的唯一方法是从列表中删除元素并保存该操作。

然后可以通过级联或手动单独删除父子项。