删除对象但将子项保留为孤儿而没有“外键约束失败”错误?
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 不会对关系进行任何级联操作,例如在Document
和Entry
之间定义的@ManyToOne
关系。由于映射中没有定义级联类型,级联删除很可能由外键约束指定的数据库执行。
我怀疑您收到的错误源自数据库。尝试在删除外键约束中的父级时更改在数据库中执行的级联操作。许多数据库允许您将外键设置为空。以下是 Oracle 的示例:
CONSTRAINT fk_column
FOREIGN KEY (column1, column2, ... column_n)
REFERENCES parent_table (column1, column2, ... column_n)
ON DELETE SET NULL
执行删除后,执行刷新以将持久性上下文与数据库重新对齐非常重要。
【讨论】:
同意。这可能是一个参照完整性问题。 我没有在数据库中看到任何外键的 ON 触发器。然而,我确实测试了不同的方法,我自己回答了。【参考方案2】:经过更多测试,我发现如果我在Document
和Entry
之间没有双向关系,则不会在数据库中添加外键,从而使删除保留孩子。如果我添加了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;
【讨论】:
以上是关于删除对象但将子项保留为孤儿而没有“外键约束失败”错误?的主要内容,如果未能解决你的问题,请参考以下文章