ChatGPT解决这个技术问题 Extra ChatGPT

JPA OneToMany 不删除孩子

我对父实体和子实体之间的简单 @OneToMany 映射有疑问。一切正常,只有当我从集合中删除子记录时不会删除它们。

家长:

@Entity
public class Parent {
    @Id
    @Column(name = "ID")
    private Long id;

    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "parent")
    private Set<Child> childs = new HashSet<Child>();

 ...
}

孩子:

@Entity
public class Child {
    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="PARENTID", nullable = false)
    private Parent parent;

  ...
}

如果我现在从子集中删除和子,它不会从数据库中删除。我尝试取消 child.parent 引用,但这也不起作用。

实体在 Web 应用程序中使用,删除作为 Ajax 请求的一部分发生。按下保存按钮时,我没有已删除子项的列表,因此我无法隐式删除它们。


m
musiKk

JPA 的行为是正确的(根据规范表示):对象不会因为您已从 OneToMany 集合中删除它们而被删除。有特定于供应商的扩展可以做到这一点,但本机 JPA 不适合它。

部分原因是 JPA 实际上并不知道它是否应该删除从集合中删除的内容。在对象建模方面,这是组合和“聚合*”之间的区别。

在组合中,子实体没有父实体就没有存在。一个典型的例子是 House 和 Room 之间。删除房屋,房间也随之消失。

聚合是一种较松散的关联,以课程和学生为代表。删除课程,学生仍然存在(可能在其他课程中)。

因此,您需要使用特定于供应商的扩展来强制执行此行为(如果可用)或显式删除子项并将其从父项的集合中删除。

我知道:

休眠:级联 delete_orphan。见 10.11。传递持久性;和

EclipseLink:称之为“私有制”。请参阅如何使用 @PrivateOwned 注解。


感谢很好的解释。就像我担心的那样。 (在我问之前我做了一些搜索/阅读,只是想保存)。不知何故,我开始后悔决定直接使用 JPA API 和 nit Hibernate .. 我将尝试 Chandra Patni 指针并使用 hibernate delete_orphan 级联类型。
我对此有一个类似的问题。请在这里看看这篇文章好吗? stackoverflow.com/questions/4569857/…
使用 JPA 2.0,您现在可以使用选项 orphanRemoval = true
关于 orphanRemoval 的很好的初步解释和很好的建议。不知道 JPA 没有考虑这种类型的删除。我对 Hibernate 的了解与 JPA 实际所做的事情之间的细微差别可能会让人抓狂。
通过揭示组合和聚合之间的差异很好地解释了!
m
mixel

除了 cletus 的回答之外,自 2010 年 12 月以来的最终版本 JPA 2.0@OneToMany 注释上引入了一个 orphanRemoval 属性。有关详细信息,请参阅此 blog entry

请注意,由于规范相对较新,并非所有 JPA 1 提供者都有最终的 JPA 2 实现。例如,Hibernate 3.5.0-Beta-2 release 尚不支持此属性。


博客条目 - 链接已损坏。
W
Willi Mentzel

你可以试试这个:

@OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true)


谢谢。但是问题是从 JPA 1 回来的。而且这个选项是不可用的。
不过很高兴知道,对于我们这些在 JPA2 时代寻找解决方案的人来说 :)
W
Willi Mentzel

正如解释的那样,用 JPA 做我想做的事是不可能的,所以我使用了 hibernate.cascade 注释,这样,Parent 类中的相关代码现在看起来像这样:

@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, mappedBy = "parent")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
            org.hibernate.annotations.CascadeType.DELETE,
            org.hibernate.annotations.CascadeType.MERGE,
            org.hibernate.annotations.CascadeType.PERSIST,
            org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
private Set<Child> childs = new HashSet<Child>();

我不能简单地使用'ALL',因为这也会删除父级。


C
Community
@Entity 
class Employee {
     @OneToOne(orphanRemoval=true)
     private Address address;
}

请参阅here


C
Chandra Patni

这里的级联,在删除的上下文中,意味着如果您删除父级,则删除子级。不是协会。如果您使用 Hibernate 作为您的 JPA 提供程序,您可以使用 hibernate specific cascade 来完成。


W
Willi Mentzel

你可以试试这个:

@OneToOne(cascade = CascadeType.REFRESH) 

或者

@OneToMany(cascade = CascadeType.REFRESH)

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅