1

I have the following entities with a parent-child relationship:

public class Parent {
  @Id @GeneratedValue String id;

  @Version Long version;

  @OneToMany(mappedBy = "parent", orphanRemoval = true)
  @Cascade({CascadeType.ALL})
  Set<Child> children;

  // getters and setters
}

public class Child {
  @Id @GeneratedValue String id;

  @ManyToOne
  @JoinColumn("parent_id")
  Parent parent;

  // getters and setters
}
  1. I retrieve a Parent for edit on the web UI by copy properties to a ParentDto, which has a list of ChildDtos.
  2. Once I'm done editing, I send the ParentDto object back and copy all properties into a new Parent object (parent) with a new HashSet to store the Children created from the list of ChildDtos.
  3. Then I call getCurrentSession().update(parent);

The problem

I can add children, update children, but I can't delete children. What is the issue here and how do I resolve it?

Thanks in advance.

Koitoer
  • 18,778
  • 7
  • 63
  • 86
restassured
  • 1,008
  • 2
  • 9
  • 12

1 Answers1

1

You have a bidirectional association, you need to remove from Child class the link to the parent class, try to make Parent reference to null, and also set the Set<Child> to a new HashSet<Child> or whatever your implementation is. Then save the changes that will remove the children form the table.

This action can only be used in the context of an active transaction.

public void remove(Object entity);

Transitions managed instances to removed. The instances will be deleted from the datastore on the next flush or commit. Accessing a removed entity has undefined results.

For a given entity A, the remove method behaves as follows:

If A is a new entity, it is ignored. However, the remove operation cascades as defined below.
If A is an existing managed entity, it becomes removed.
If A is a removed entity, it is ignored.
If A is a detached entity, an IllegalArgumentException is thrown.

The remove operation recurses on all relation fields of A whose cascades include CascadeType.REMOVE. Read more about entity lifecycle

Koitoer
  • 18,778
  • 7
  • 63
  • 86
  • This does not apply since the delete is done on the UI. When ParentDto gets back to the server, it only has one ChildDto in the Set. Then I copy the ParentDto to Parent, which would also only have one Child. – restassured Feb 17 '15 at 20:14
  • but when your parentdto is in the server you take from the database the parent and update it, which it means you made managed the entity and then you could apply the changes according to the DTO, I believe the problem is the parent is not managed and the update is not being done – Koitoer Feb 17 '15 at 20:31
  • Yes, you're right. The Parent that I copy into is not managed. As a matter of fact, it is a brand new detached object with the same ID. My question is why does this work for adding and updating children, but not for delete? – restassured Feb 17 '15 at 20:40
  • Simple answer will be because delete operation does not nothing in not managed entity, http://image.slidesharecdn.com/introductiontojpaandhibernate-140518103646-phpapp01/95/introduction-to-jpa-and-hibernate-including-examples-37-638.jpg?cb=1400427830. Also you need to be in a transaction scope, check my update – Koitoer Feb 17 '15 at 20:48
  • Ok, we're getting somewhere. So are you saying that I have to 1) retrieve Parent from database, 2) copy all properties, 3) loop through getChildren() and copy all properties into those children, compare and remove the children that no longer exist in getChildren()? – restassured Feb 17 '15 at 21:04
  • yes take parent from database with the related collection, update the parent with the dto updates, then if you need to remove a child from that parent use the managed entity and remove from the collection, and then save the parent managed entity. If you need to update child properties, use the one that is retrieved from the collection – Koitoer Feb 17 '15 at 23:29