首页 > 解决方案 > Cascade.Type = ALL 在尝试删除自己的行之前不会删除所有“子行”

问题描述

我正在尝试删除用户,但在休眠尝试删除用户之前,数据库中引用该用户的每一行都不会被删除。

我对应用程序中的每个其他实体都有相同的结构,它工作得很好,首先删除所有子行,然后删除行本身,但正如您在下面看到的,尝试删除用户时并非如此。Hibernate 进入这个声明:

Hibernate: delete from users where user_id=?

在删除所有 comment_votes 之前。(之前也应该删除帖子,但我猜comment_votes错误首先出现)。

根据控制台报错前执行了这一系列sql语句:

Hibernate: delete from comment_vote where vote_id=?
Hibernate: delete from comment where comment_id=?
Hibernate: delete from comment_vote where vote_id=?
Hibernate: delete from comment where comment_id=?
Hibernate: delete from comment_vote where vote_id=?
Hibernate: delete from comment where comment_id=?
Hibernate: delete from users where user_id=?

这是我得到的错误:

org.postgresql.util.PSQLException: ERROR: update or delete on table "users" violates foreign key constraint "fkjf73ixvt1jv3wdv4ah0hkpewf" on table "comment_vote"
  Detail: Key (user_id)=(2) is still referenced from table "comment_vote".

用户.java:

@Entity
@Table(name = "users") // because User is a keyword in some DBs
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id", columnDefinition = "serial")
    private Long id;

    @NotEmpty
    @Column(unique = true)
    private String username;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    @JsonIgnore
    private List<Post> posts = new ArrayList<>();

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    @JsonIgnore
    private List<Comment> comments = new ArrayList<>();

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    @JsonIgnore
    private List<CommentVote> comment_votes = new ArrayList<>();

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    @JsonIgnore
    private List<PostVote> post_votes = new ArrayList<>();

    // getters and setters
}

这是 CommentVote.java :

@Entity
@Table(name = "comment_vote")
public class CommentVote {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "vote_id", columnDefinition = "serial")
    private Long id;

    @Min(value = -1, message = "A vote can not be less than -1")
    @Max(value = 1, message = "A vote can not be greater than 1")
    @Column(name = "actual_vote")
    private int actualVote;

    @ManyToOne()
    @JoinColumn(name="user_id", nullable=false)
    @JsonIgnore
    private User user;

    // getters and setters
}

我在 User.java 中的每个子字段上都尝试了 orphanRemoval = true ,但这似乎并没有改变任何东西。

标签: springpostgresqlhibernatejpaspring-data-jpa

解决方案


您可以尝试使用@OnDelete. 正如文档中所述:

...@OnDelete级联是 DDL 级别的 FK 功能,它允许您在删除父行时删除子记录。

因此,当用 注释@ManyToOne关联时@OnDelete(action = OnDeleteAction.CASCADE),自动模式生成器会将ON DELETE CASCADESQL 指令应用于外键声明。

考虑到这一点,您可以通过以下方式更正映射:

@Entity
@Table(name = "comment_vote")
public class CommentVote {

    // ...

    @ManyToOne()
    @JoinColumn(name="user_id", nullable=false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JsonIgnore
    private User user;

    // ...
}

推荐阅读