Differencebetween Cascadetype.Remove and Orphanremoval in JPA

What is the difference between CascadeType.REMOVE and orphanRemoval in JPA?

From here:-

Cascading Remove

Marking a reference field with CascadeType.REMOVE (or CascadeType.ALL,
which includes REMOVE) indicates that remove operations should be
cascaded automatically to entity objects that are referenced by that
field (multiple entity objects can be referenced by a collection
field):

@Entity
class Employee {
:
@OneToOne(cascade=CascadeType.REMOVE)
private Address address;
:
}

Orphan Removal

JPA 2 supports an additional and more aggressive remove cascading mode
which can be specified using the orphanRemoval element of the
@OneToOne and @OneToMany annotations:

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

DIFFERENCE:-

The difference between the two settings is in the response to
disconnecting a relationship. For example, such as when setting the
address field to null or to another Address object.

  • If orphanRemoval=true is specified the disconnected Address instance is automatically removed. This is useful for cleaning up
    dependent objects (e.g. Address) that should not exist without a
    reference from an owner object (e.g. Employee).
  • If only cascade=CascadeType.REMOVE is specified no automatic action is taken since disconnecting a relationship is not a remove

    operation.

JPA: 'CascadeType.REMOVE' or 'orphanRemoval = true', which use in a n:n relation that generate new table/class with EmbeddeId class?

Let's assume that you have a parent -> child relationship.

If you set CacadeType.REMOVE on the relationship every EntityManager.remove call on the parent will also remove the children.

orphanRemoval = true is used to delete orphan children.

So if remove a child from the parent reference or collection and save the parent the child will be deleted because its no longer attached to the parent.

How does JPA orphanRemoval=true differ from the ON DELETE CASCADE DML clause

orphanRemoval has nothing to do with ON DELETE CASCADE.

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.

ON DELETE CASCADE is a database-specific thing, it deletes the "child" row in the database when the "parent" row is deleted.

JPA (orphanRemoval = true) Implementation

The problem is caused by the following line:

p.setPhones(new ArrayList<>());

In Hibernate, you cannot overwrite a collection retrieved from the persistence context if the association has orphanRemoval = true specified. If your goal is to end up with an empty collection, use p.getPhones().clear() instead.

JPA - is Cascade and Orphan Removal redundant

orphanRemoval would only cover the CascadeType.REMOVE.

If you remove the cascade = CascadeType.ALL and leave only the orphanRemoval = true, then you would miss out on the following operations which would not be cascaded anymore:

{PERSIST, MERGE, REFRESH, DETACH}.

Doctrine: cascade=remove vs orphanRemoval=true

The basic difference between them is:

When using the orphanRemoval=true option Doctrine makes the assumption
that the entities are privately owned and will NOT be reused by other
entities. If you neglect this assumption your entities will get
deleted by Doctrine even if you assigned the orphaned entity to
another one.

Say your User has one-to-many relation to Comment. If you are using cascade="remove", you can remove the reference for Comment from one User, and then attach that Comment to another User. When you persist them, they will be correctly saved. But if you are using orphanRemoval=true, even if you will remove given Comment from one User, and then attach to another User, this comment will be deleted during persist, because the reference has been deleted.

JPA CascadeType.ALL does not delete orphans

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

  1. fetch main row to be deleted
  2. fetch child elements
  3. delete all child elements
  4. delete main row
  5. close session

With JPA 2.0, you can now use the option orphanRemoval = true

@OneToMany(mappedBy="foo", orphanRemoval=true)


Related Topics



Leave a reply



Submit