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

What's the difference between

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

and

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

This example is from Java EE Tutorial, but I still don't understand details.


Solution 1:

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.

Solution 2:

An easy way to understand the difference between CascadeType.REMOVE and orphanRemoval=true.

For orphan removal: If you invoke setOrders(null), the related Order entities will be removed in db automatically.

For remove cascade: If you invoke setOrders(null), the related Order entities will NOT be removed in db automatically.

Solution 3:

Suppose we have a child entity and a parent entity. A parent can have several children.

@Entity
class parent {
  //id and other fields
 @OneToMany (orphanRemoval = "true",cascade = CascadeType.REMOVE)
   Set<Person> myChildern;
}

The orphanRemoval is an ORM concept, it tells if the child is orphaned. it should also be removed from the database.

A child is orphaned when it can`t be accessed from its parent. For example, if we remove the Person objects set (setting it to an empty set) or replace it with a new set then the parent can no longer access the children in the old set and the children are orphaned so the children are doomed to be removed in the database also.

CascadeType.REMOVE is a database level concept and it tells if the parent is removed, all its related records in the child table should be removed.