JPA CascadeType.ALL 不删除孤儿

Posted

技术标签:

【中文标题】JPA CascadeType.ALL 不删除孤儿【英文标题】:JPA CascadeType.ALL does not delete orphans 【发布时间】:2010-09-23 07:09:02 【问题描述】:

我在使用具有以下映射的 JPA 删除孤立节点时遇到问题

@OneToMany (cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "owner")
private List<Bikes> bikes;

我遇到了数据库中存在孤立角色的问题。

我可以使用注解 org.hibernate.annotations.Cascade Hibernate 特定标签,但显然我不想将我的解决方案绑定到 Hibernate 实现中。

编辑:似乎 JPA 2.0 将包含对此的支持。

【问题讨论】:

【参考方案1】:

如果您将它与 Hibernate 一起使用,则必须显式定义注释 CascadeType.DELETE_ORPHAN,它可以与 JPA CascadeType.ALL 一起使用。

如果您不打算使用 Hibernate,则必须先显式删除子元素,然后再删除主记录以避免任何孤立记录。

执行顺序

    获取要删除的主行 获取子元素 删除所有子元素 删除主行 关闭会话

使用 JPA 2.0,您现在可以使用选项 orphanRemoval = true

@OneToMany(mappedBy="foo", orphanRemoval=true)

【讨论】:

感谢我最终选择了这条路线,我认为这对于 JPA 规范来说有点过分了。 JPA 2.0 标准现在将 deleteOrphan 作为@OneToMany 的属性如果您使用的是最新的休眠,您可以使用@OneToMany(..., deleteOrphan=true) 更新子元素时的执行顺序是什么?孤儿记录会被删除吗?【参考方案2】:

如果您使用的是 JPA 2.0,您现在可以使用 @xxxToMany 注释的 orphanRemoval=true 属性来删除孤儿。

实际上,CascadeType.DELETE_ORPHAN 在 3.5.2-Final 中已被弃用。

【讨论】:

其实我认为 orphanRemoval=true 意味着别的东西,即当我从它的父集合中删除一个对象时删除它。见download.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy 请通过 Archie 的链接。 orphanRemoval=true 也不起作用。它必须以旧方式完成。【参考方案3】:
╔═════════════╦═════════════════════╦═════════════════════╗
║   Action    ║  orphanRemoval=true ║   CascadeType.ALL   ║
╠═════════════╬═════════════════════╬═════════════════════╣
║   delete    ║     deletes parent  ║    deletes parent   ║
║   parent    ║     and orphans     ║    and orphans      ║
╠═════════════╬═════════════════════╬═════════════════════╣
║   change    ║                     ║                     ║
║  children   ║   deletes orphans   ║      nothing        ║
║    list     ║                     ║                     ║
╚═════════════╩═════════════════════╩═════════════════════╝

【讨论】:

如果我有cascade = CascadeType.ALL, orphanRemoval = false 并删除父级会怎样?即使我明确告知不要这样做,它会删除孩子吗?【参考方案4】:

如果您将 JPA 与 EclipseLink 一起使用,则必须设置 @PrivateOwned 注释。

文档:Eclipse Wiki - Using EclipseLink JPA Extensions - Chapter 1.4 How to Use the @PrivateOwned Annotation

【讨论】:

【参考方案5】:

您可以使用@PrivateOwned 删除孤儿 例如

@OneToMany(mappedBy = "masterData", cascade = 
        CascadeType.ALL )
@PrivateOwned
private List<Data> dataList;

【讨论】:

感谢@reshma 应该注意@PrivateOwned 是一个eclipselink JPA 扩展。【参考方案6】:

我只是找到了这个解决方案,但在我的情况下它不起作用:

@OneToMany(cascade = CascadeType.ALL, targetEntity = MyClass.class, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true) 

orphanRemoval = true 无效。

【讨论】:

我需要在更改生效之前进行清理和构建。 哇,我一直在寻找一个小时,为什么在我的 ManyToOne 上添加 CascadeType.ALL 不是级联删除。清洁和建造,它的工作原理。谢谢@maralbjo。【参考方案7】:

根据Java Persistence with Hibernate,级联孤儿删除 不能用作 JPA 注释。

JPA XML 也不支持它。

【讨论】:

【参考方案8】:

我有同样的问题,我想知道为什么下面的这个条件没有删除孤儿。当我执行命名删除查询时,Hibernate(5.0.3.Final)中的菜肴列表没有被删除:

@OneToMany(mappedBy = "menuPlan", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Dish> dishes = new ArrayList<>();

然后我记得我不能使用命名删除查询,而是使用 EntityManager。当我使用EntityManager.find(...) 方法获取实体然后EntityManager.remove(...) 删除它时,菜肴也被删除了。

【讨论】:

【参考方案9】:

只需@OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true)

删除targetEntity = MyClass.class,效果很好。

【讨论】:

【参考方案10】:

据记载,在 JPA2 之前的 OpenJPA 中,它是 @ElementDependant。

【讨论】:

【参考方案11】:

我使用的是一对一映射,但孩子没有被删除 JPA 给出了外键违规

使用 orphanRemoval = true 后,问题得到解决

【讨论】:

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "CHILD_OID") private Child child;

以上是关于JPA CascadeType.ALL 不删除孤儿的主要内容,如果未能解决你的问题,请参考以下文章

JPA OneToMany 不删除孩子

JPA/Hibernate 级联删除不起作用

JPA 2 / Hibernate 孤儿删除仍然无法与@OneToMany 一起使用?

JPA 孤儿删除不适用于 OneToOne 关系

在 Spring JPA 中删除实体

一对多 JPA 注释不会删除孤儿