24

I'm using JPA over Hibernate in my web-app. Here are two entities (only getters are shown):

class Child {
  private Parent parent;

  @ManyToOne(optional=false)
  @JoinColumn(name="parent_id", referencedColumnName="parent_id", nullable=false, updatable=false)
  public Parent getParent() {
    return parent;
  }
}

class Parent {
  private Collection<Child> children;

  @OneToMany(fetch=FetchType.EAGER, mappedBy="parent", cascade={CascadeType.ALL})
  public Collection<Child> getChildren() {
    return children;
  }
}

As you see Parent and Child relate as "one-to-many".

Now I need to load a Parent instance, remove some or all children and save the changes. Below is code which does not work for me:

Parent p = entityManager.find(Parent.class, 12345L); // load entity
p.getChildren().clear(); // remove all children
entityManager.merge(p); // try to save

Child entities are not remove in the example above. Now I have to manually call entityManager.remove() for each child.

Is there any easier way to manage child collection?

Please notice that I don't want to use Hibernate-specific functionality, only pure JPA.

Lii
  • 11,553
  • 8
  • 64
  • 88
Andrey
  • 3,667
  • 6
  • 27
  • 36
  • possible duplicate of [JPA CascadeType.ALL does not delete orphans.](http://stackoverflow.com/questions/306144/jpa-cascadetype-all-does-not-delete-orphans) – Pascal Thivent Sep 17 '10 at 21:40

1 Answers1

34

For JPA 2.0 you can set orphanRemoval=true of the @OneToMany

For JPA 1.0, you should use hibernate-specific annotations. That is the @Cascade annotation (instead of the cascade attribute), with a value of

@Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})

Hibernate 3.5+ implement JPA 2.0

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Is there any solution for JPA 1.0? I'm not ready to change JPA implementor. – Andrey Sep 17 '10 at 21:06
  • Thanks, that is a good way. set orphanRmoval, when merge can delete the orphan child – Scarlett Dec 08 '11 at 08:05
  • With regard to orphanRemoval how exactly does the EntityManager tell the difference between an object that was explicitly removed from the collection (and hence, needs to be deleted in the DB) versus an object that's not in the collection because it was never loaded to begin with? (i.e. because the one-to-many collection is lazy)? Or does it only work in EAGER collections? – Marcus Junius Brutus Nov 01 '12 at 18:09
  • it compares the state of the collection to the state of the database. So if something is missing in the collection (regardless of the reason) but it present in the database, it is deleted from the database – Bozho Nov 01 '12 at 19:44
  • Thanks. The @Cascade was the only solution for me, even using JPA2.0. Weird. – Bodosko Mar 23 '20 at 16:03