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

JavaHibernateJpaCascading DeletesOrphan Removal

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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 - Java

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 - Java

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.

Solution 4 - Java

CascadeType.REMOVE

The CascadeType.REMOVE strategy, which you can configure explicitly:

@OneToMany(
	mappedBy = "post",
	cascade = CascadeType.REMOVE
)
private List<PostComment> comments = new ArrayList<>();

or inherit it implicitly from the CascadeType.ALL strategy:

@OneToMany(
	mappedBy = "post",
	cascade = CascadeType.ALL
)
private List<PostComment> comments = new ArrayList<>();

allows you to propagate the remove operation from the parent entity to its child entities.

So, if we fetch the parent Post entity along with its comments collection, and remove the post entity:

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments
    where p.id = :id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

entityManager.remove(post);

Hibernate is going to execute three delete statements:

DELETE FROM post_comment 
WHERE id = 2

DELETE FROM post_comment 
WHERE id = 3

DELETE FROM post 
WHERE id = 1

The PostComment child entities were deleted because of the CascadeType.REMOVE strategy, which acted as if we removed the child entities as well.

The orphan-removal strategy

The orphan-removal strategy, which needs to be set via the orphanRemoval attribute:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

allows you to remove the child table row upon removing the child entity from the collection.

So, if we load the Post entity along with its comments collection and remove the first PostComment from the comments collection:

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments c
    where p.id = :id
    order by p.id, c.id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

post.remove(post.getComments().get(0));

Hibernate is going to execute a DELETE statement for the associated post_comment table row:

DELETE FROM post_comment 
WHERE id = 2

Solution 5 - Java

Practically the difference lies in whether you are trying to update the data (PATCH) or entirely replace the data (PUT)

Let's say you delete the customer than using cascade=REMOVE will also remove that customers orders which seem intended and useful.

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

Now let's say you update a customer with orphanRemoval="true" it will delete all previous orders and replace them with the one provided. (PUT in terms of REST API)

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

Without orphanRemoval old orders would be kept. (PATCH in terms of REST API)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionrand0m86View Question on Stackoverflow
Solution 1 - JavaRahul TripathiView Answer on Stackoverflow
Solution 2 - JavastudyView Answer on Stackoverflow
Solution 3 - JavaMr.QView Answer on Stackoverflow
Solution 4 - JavaVlad MihalceaView Answer on Stackoverflow
Solution 5 - Javagarg10mayView Answer on Stackoverflow