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 不删除孤儿的主要内容,如果未能解决你的问题,请参考以下文章