Java JPA OneToMany 不删除子项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2011519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:29:29  来源:igfitidea点击:

JPA OneToMany not deleting child

javajpajpa-1.0

提问by bert

I have a problem with a simple @OneToManymapping between a parent and a child entity. All works well, only that child records are not deleted when I remove them from the collection.

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

The parent:

家长:

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

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

 ...
}

The child:

孩子:

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

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

  ...
}

If I now delete and child from the childs Set, it does not get deleted from the database. I tried nullifying the child.parentreference, but that did not work either.

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

The entities are used in a web application, the delete happens as part of an Ajax request. I don't have a list of deleted childs when the save button is pressed, so I can't delete them implicitly.

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

采纳答案by cletus

JPA's behaviour is correct (meaning as per the specification): objects aren't deleted simply because you've removed them from a OneToMany collection. There are vendor-specific extensions that do that but native JPA doesn't cater for it.

JPA 的行为是正确的(意思是按照规范):对象不会仅仅因为您已从 OneToMany 集合中删除它们而被删除。有一些特定于供应商的扩展可以做到这一点,但本机 JPA 不能满足它。

In part this is because JPA doesn't actually know if it should delete something removed from the collection. In object modeling terms, this is the difference between compositionand "aggregation*.

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

In composition, the child entity has no existence without the parent. A classic example is between House and Room. Delete the House and the Rooms go too.

composition 中,没有父实体,子实体就不存在。一个经典的例子是在 House 和 Room 之间。删除房子,房间也去。

Aggregationis a looser kind of association and is typified by Course and Student. Delete the Course and the Student still exists (probably in other Courses).

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

So you need to either use vendor-specific extensions to force this behaviour (if available) or explicitly delete the child AND remove it from the parent's collection.

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

I'm aware of:

我知道:

回答by Chandra Patni

Here cascade, in the context of remove, means that the children are removed if you remove the parent. Not the association. If you are using Hibernate as your JPA provider, you can do it using hibernate specific cascade.

这里的级联,在 remove 的上下文中,意味着如果您删除父级,则子级将被删除。不是协会。如果你使用 Hibernate 作为你的 JPA 提供者,你可以使用Hibernate 特定的级联来实现

回答by bert

As explained, it is not possible to do what I want with JPA, so I employed the hibernate.cascade annotation, with this, the relevant code in the Parent class now looks like this:

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

@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>();

I could not simple use 'ALL' as this would have deleted the parent as well.

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

回答by Louis Jacomet

In addition to cletus' answer, JPA 2.0, final since december 2010, introduces an orphanRemovalattribute on @OneToManyannotations. For more details see this blog entry.

除了 cletus 的回答之外,自 2010 年 12 月以来的最终版本JPA 2.0 还引入了注释orphanRemoval属性@OneToMany。有关更多详细信息,请参阅此博客条目

Note that since the spec is relatively new, not all JPA 1 provider have a final JPA 2 implementation. For example, the Hibernate 3.5.0-Beta-2 releasedoes not yet support this attribute.

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

回答by Maciel Bombonato

You can try this:

你可以试试这个:

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

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

回答by Amit Ghorpade

You can try this:

你可以试试这个:

@OneToOne(cascade = CascadeType.REFRESH) 

or

或者

@OneToMany(cascade = CascadeType.REFRESH)

回答by Chang

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

See here.

这里