JPA OneToMany not deleting child

这一生的挚爱 提交于 2019-11-26 18:09:56
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.

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 composition and "aggregation*.

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.

Aggregation is 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:

Louis Jacomet

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

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 release does not yet support this attribute.

Maciel Bombonato

You can try this:

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

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:

@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.

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.

Amit Ghorpade

You can try this:

@OneToOne(cascade = CascadeType.REFRESH) 

or

@OneToMany(cascade = CascadeType.REFRESH)
Chang
@Entity 
class Employee {
     @OneToOne(orphanRemoval=true)
     private Address address;
}

See here.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!