【问题标题】:Cascade.Type = ALL does not delete all "child rows" before trying to delete its own rowCascade.Type = ALL 在尝试删除自己的行之前不会删除所有“子行”
【发布时间】:2021-09-05 18:20:28
【问题描述】:

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

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

Hibernate: delete from users where user_id=?

在所有评论投票被删除之前。 (之前也应该删除帖子,但我猜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 但这似乎没有任何改变。

【问题讨论】:

    标签: spring postgresql hibernate jpa spring-data-jpa


    【解决方案1】:

    您可以尝试使用@OnDelete。正如documentation 中所述:

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

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

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

    @Entity
    @Table(name = "comment_vote")
    public class CommentVote {
    
        // ...
    
        @ManyToOne()
        @JoinColumn(name="user_id", nullable=false)
        @OnDelete(action = OnDeleteAction.CASCADE)
        @JsonIgnore
        private User user;
    
        // ...
    }
    

    【讨论】:

    • 这样就解决了问题!我认为这是 CascadeType.ALL 应该做的,但我想我错了
    • 是的,CascadeType.*** 级联类型传播 entity state transitions@OnDelete 级联是 DDL 级别的 FK 功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-11
    • 2021-09-16
    • 2014-11-06
    • 2011-09-13
    • 2022-01-07
    • 1970-01-01
    相关资源
    最近更新 更多