删除对象但将子项保留为孤儿而没有“外键约束失败”错误?

Posted

技术标签:

【中文标题】删除对象但将子项保留为孤儿而没有“外键约束失败”错误?【英文标题】:Delete object but keep children as orphans without "a foreign key constraint fails" error? 【发布时间】:2013-07-17 08:26:53 【问题描述】:

我有一个用户。该用户有一个文档。该文档有几个条目。如果我删除一个文档,那么我想保留子条目,这将是孤儿,用于调试目的。使用底部描述的类,当我删除一个文档时,我得到一个外键错误:

无法删除或更新父行:外键约束失败 (relation.entry,约束FK4001852ED0B1AFE外键 (document_id) 参考资料document (id))

我正在使用基于模型创建表的框架。使用cascade = CascadeType.REMOVE 使其工作,但我不想删除孩子。我应该使用特殊的CascadeType 吗?

用户

@Entity
public class User 
    public String name;

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
    public Document document;

文档

@Entity
public class Document 
    public String title;

    @OneToOne
    public User user;

    @OneToMany(mappedBy = "document")
    public List<Entry> entries;

参赛作品

@Entity
public class Entry 
    public String data;

    @ManyToOne
    public Document document;

【问题讨论】:

我个人不会硬删除文档。我会添加一个布尔/位列“已删除”并将其标记为已删除。 @PaulSullivan 为什么不选择删除文档?如果表必须保持在我真正必须删除文档的最少行数怎么办? 如果您的系统将来必须具有“取消删除”或存档功能会怎样?还。由于它仅用于“调试”目的,因此您可以稍后实现硬删除。此外,您可以在以后当表格变得庞大时运行脚本来清除“已删除”的文档。 @PaulSullivan 是的,这听起来确实很有未来保障。不过我想把它删除。 【参考方案1】:

默认情况下,JPA 不会对关系进行任何级联操作,例如在DocumentEntry 之间定义的@ManyToOne 关系。由于映射中没有定义级联类型,级联删除很可能由外键约束指定的数据库执行。

我怀疑您收到的错误源自数据库。尝试在删除外键约束中的父级时更改在数据库中执行的级联操作。许多数据库允许您将外键设置为空。以下是 Oracle 的示例:

CONSTRAINT fk_column
     FOREIGN KEY (column1, column2, ... column_n)
     REFERENCES parent_table (column1, column2, ... column_n)
     ON DELETE SET NULL 

执行删除后,执行刷新以将持久性上下文与数据库重新对齐非常重要。

【讨论】:

同意。这可能是一个参照完整性问题。 我没有在数据库中看到任何外键的 ON 触发器。然而,我确实测试了不同的方法,我自己回答了。【参考方案2】:

经过更多测试,我发现如果我在DocumentEntry 之间没有双向关系,则不会在数据库中添加外键,从而使删除保留孩子。如果我添加了CascadeType.REMOVE,那么它也会删除孩子并且不会留下任何孤儿。但是,这会在数据库中创建一个新表 document_entry

更新文档

@Entity
public class Document 
    public String title;

    @OneToOne
    public User user;

    @OneToMany
    public List<Entry> entries;

更新条目

@Entity
public class Entry 
    public String data;

【讨论】:

以上是关于删除对象但将子项保留为孤儿而没有“外键约束失败”错误?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL插入数据因外键约束失败?

无法删除表:外键约束失败

如何解决这个问题 - 无法删除或更新父行:外键约束失败

Laravel 关于删除完整性约束违规:1451 无法删除或更新父行:外键约束失败

无法删除或更新父行:外键约束失败

传播级联删除引发外键约束失败