Let’s say we have two entities, A and B. B has a many-to-one relationship to A like follows:
@Entity
public class A {
@OneToMany(mappedBy="a_id")
private List<B> children;
}
@Entity
public class B {
private String data;
}
Now, I want to delete the A object and cascade the deletions to all its children B. There are two ways to do this:
-
Add
cascade=CascadeType.ALL, orphanRemoval=trueto the OneToMany annotation, letting JPA remove all children before removing the A-object from the database. -
Leave the classes as they are and simply let the database cascade the deletion.
Is there any problem with using the later option? Will it cause the Entity Manager to keep references to already deleted objects? My reason for choosing option two over one is that option one generates n+1 SQL queries for a removal, which can take a prolonged time when object A contains a lot of children, while option two only generates a single SQL query and then moves on happily. Is there any "best practice" regarding this?
In EclipseLink you can use both if you use the
@CascadeOnDeleteannotation. EclipseLink will also generate the cascade DDL for you.See,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/DeleteCascade
This optimizes the deletion by letting the database do it, but also maintains the cache and the persistence unit by removing the objects.
Note that
orphanRemoval=truewill also delete objects removed from the collection, which the database cascade constraint will not do for you, so having the rules in JPA is still necessary. There are also some relationships that the database cannot handle deletion for, as the database can only cascade in the inverse direction of the constraint, aOneToOnewith a foreign key, or aOneToManywith a join table cannot be cascaded on the database.