JPA CascadeType.ALL does not delete orphans
Question
I am having trouble deleting orphan nodes using JPA with the following mapping
@OneToMany (cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "owner")
private List<Bikes> bikes;
I am having the issue of the orphaned roles hanging around the database.
I can use the annotation org.hibernate.annotations.Cascade
Hibernate specific tag but obviously I don't want to tie my solution into a Hibernate implementation.
EDIT: It seems JPA 2.0 will include support for this.
Solution
If you are using it with Hibernate, you'll have to explicitly define the annotation CascadeType.DELETE_ORPHAN
, which can be used in conjunction with JPA CascadeType.ALL
.
If you don't plan to use Hibernate, you'll have to explicitly first delete the child elements and then delete the main record to avoid any orphan records.
execution sequence
- fetch main row to be deleted
- fetch child elements
- delete all child elements
- delete main row
- close session
With JPA 2.0, you can now use the option orphanRemoval = true
@OneToMany(mappedBy="foo", orphanRemoval=true)
OTHER TIPS
If you are using JPA 2.0, you can now use the orphanRemoval=true
attribute of the @xxxToMany
annotation to remove orphans.
Actually, CascadeType.DELETE_ORPHAN
has been deprecated in 3.5.2-Final.
╔═════════════╦═════════════════════╦═════════════════════╗
║ Action ║ orphanRemoval=true ║ CascadeType.ALL ║
╠═════════════╬═════════════════════╬═════════════════════╣
║ delete ║ deletes parent ║ deletes parent ║
║ parent ║ and orphans ║ and orphans ║
╠═════════════╬═════════════════════╬═════════════════════╣
║ change ║ ║ ║
║ children ║ deletes orphans ║ nothing ║
║ list ║ ║ ║
╚═════════════╩═════════════════════╩═════════════════════╝
If you are using JPA with EclipseLink, you'll have to set the @PrivateOwned annotation.
Documentation: Eclipse Wiki - Using EclipseLink JPA Extensions - Chapter 1.4 How to Use the @PrivateOwned Annotation
you can use @PrivateOwned to delete orphans e.g
@OneToMany(mappedBy = "masterData", cascade = {
CascadeType.ALL })
@PrivateOwned
private List<Data> dataList;
According to Java Persistence with Hibernate, cascade orphan delete is not available as a JPA annotation.
It is also not supported in JPA XML.
I just find this solution but in my case it doesn't work:
@OneToMany(cascade = CascadeType.ALL, targetEntity = MyClass.class, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true)
orphanRemoval = true has no effect.
I had the same problem and I wondered why this condition below did not delete the orphans. The list of dishes were not deleted in Hibernate (5.0.3.Final) when I executed a named delete query:
@OneToMany(mappedBy = "menuPlan", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Dish> dishes = new ArrayList<>();
Then I remembered that I must not use a named delete query, but the EntityManager. As I used the EntityManager.find(...)
method to fetch the entity and then EntityManager.remove(...)
to delete it, the dishes were deleted as well.
Just @OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true)
.
Remove targetEntity = MyClass.class, it works great.
For the records, in OpenJPA before JPA2 it was @ElementDependant.
I was using one to one mapping , but child was not getting deleted JPA was giving foreign key violation
After using orphanRemoval = true , issue got resolved