Say I have a unidirectional @ManyToOne
relationship like the following:
@Entity public class Parent implements Serializable { @Id @GeneratedValue private long id; } @Entity public class Child implements Serializable { @Id @GeneratedValue private long id; @ManyToOne @JoinColumn private Parent parent; }
If I have a parent P and children C1...Cn referencing back to P, is there a clean and pretty way in JPA to automatically remove the children C1...Cn when P is removed (i.e. entityManager.remove(P)
)?
What I'm looking for is a functionality similar to ON DELETE CASCADE
in SQL.
orphanRemoval is an entirely ORM-specific thing. It marks "child" entity to be removed when it's no longer referenced from the "parent" entity, e.g. when you remove the child entity from the corresponding collection of the parent entity.
Overview. JPA Relationships can be either unidirectional or bidirectional. This simply means we can model them as an attribute on exactly one of the associated entities or both. Defining the direction of the relationship between entities has no impact on the database mapping.
Such target entities are considered “orphans,” and the orphanRemoval attribute can be used to specify that orphaned entities should be removed. For example, if an order has many line items and one of them is removed from the order, the removed line item is considered an orphan.
In JPA we use the @ManyToMany annotation to model many-to-many relationships. This type of relationship can be unidirectional or bidirectional: In a unidirectional relationship only one entity in the relationship points the other. In a bidirectional relationship both entities point to each other.
If you are using hibernate as your JPA provider you can use the annotation @OnDelete
. This annotation will add to the relation the trigger ON DELETE CASCADE
, which delegates the deletion of the children to the database.
Example:
public class Parent { @Id private long id; } public class Child { @Id private long id; @ManyToOne @OnDelete(action = OnDeleteAction.CASCADE) private Parent parent; }
With this solution a unidirectional relationship from the child to the parent is enough to automatically remove all children. This solution does not need any listeners etc. Also a JPQL query like DELETE FROM Parent WHERE id = 1
will remove the children.
Relationships in JPA are always unidirectional, unless you associate the parent with the child in both directions. Cascading REMOVE operations from the parent to the child will require a relation from the parent to the child (not just the opposite).
You'll therefore need to do this:
@ManyToOne
relationship to a bi-directional @ManyToOne
, or a unidirectional @OneToMany
. You can then cascade REMOVE operations so that EntityManager.remove
will remove the parent and the children. You can also specify orphanRemoval
as true, to delete any orphaned children when the child entity in the parent collection is set to null, i.e. remove the child when it is not present in any parent's collection.ON DELETE CASCADE
. You'll need to invoke EntityManager.clear()
after calling EntityManager.remove(parent)
as the persistence context needs to be refreshed - the child entities are not supposed to exist in the persistence context after they've been deleted in the database.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With