So that's a question which it seems there's no official answer to. At least I can't find one.

Situation: If I have a bidirectional One-to-many association and I want orphanRemoval=true to take action, do I now have to remove the association from both sides of the association or is it enough to just "break" the association by deleting the reference (to the opposite) in one of the entities?

Example:

class Parent {
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
List<Child> children;

 public void addChild(Child child) {
    child.setParent(this);
    children.add(child);
 }

 public void removeChild(Child child){
    //both statements neccessary or just one? Does it matter which one?
    children.remove(child);
    if (child != null) {
        child.setParent(null);
    }
 }
}

class Child {
 String name;
 @ManyToOne
 @JoinColumn(name="parentID")
 Parent parent;

 public void setParent(Parent p) {
  [...]
 }

}

I came across this explanation in my book "Pro JPA 2 by Mike Keith" (2nd ed., p. 287):

When specified, the orphanRemoval element causes the child entity to be removed when the relationship between the parent and the child is broken. This can be done either by setting to null the attribute that holds the related entity, or additionally in the one-to-many case by removing the child entity from the collection. The provider is then responsible, at flush or commit time (whichever comes first), for removing the orphaned child entity. In a parent-child relationship, the child is dependent upon the existence of the parent. If the parent is removed, then by definition the child becomes an orphan and must also be removed.

And then there are those posts which do both of them:

My questions:

1) What's correct / which one of both are necessary now?

2) What happens if the Child class has an @JoinColumn(name="parentID", nullable=false) and its parent reference will get set to null as seen above? My guess: the orphanRemoval would take place later and is based on the value in the database, so not until the Child entity was updated. But that update wouldn't happen, because of nullable=false, right?

1

There are 1 best solutions below

0
On

Had a similar issue, and couldn't really make sense of how this would, since the relation is owned by the many-side (due to mappedBy), while the orphanRemoval would have to be added to the non-owning one-side. I suspected that orphanRemoval would just be ignored, but after some testing it turns out that it actually does work.

So even if your one-to-many is bidirectional, you could use orphanRemoval=true and children.remove(child), with the result of child being completely removed from the database.