Search code examples
javahibernatejpahibernate-cascadeorphan-removal

moving an entity into another owned OneToMany Collection


In my application, there is a Person entity that has numerous roles of type PersonRole.

@Entity
public class Person {

    @OneToMany(mappedBy = "person",
               cascade=CascadeType.ALL, 
               orphanRemoval=true, 
               fetch=FetchType.LAZY)
     protected Set<PersonRole> roles;

    ...
}

@Entity
public abstract class PersonRole {

    @ManyToOne
    protected Person person;

    ...
}

Occassionally there are duplicate persons in the database and I'm trying to implement a function to merge those two persons into one. Since the PersonRole also has some Permissions attached to it, I don't want to delete and recreate it, I want to move it from the dieing Person to the surviving Person:

for (PersonRole role : dieing.getRoles()) {
    role.mergeInto(surviving);
}
dieing.getRoles().clear();

the Method in PersonRole looks like this:

public void mergeInto(Person surviving ) {
    this.person = surviving;
    surviving.getRoles().add(this);
}

Unfortunately it doesn't work. When I run it, the PersonRoles are deleted and not added to the surviving person.

What do I need to change, so they are added and persisted through the surviving.roles relationship?


Solution

  • I found the solution:

    dieing.getRoles().clear();
    

    was wrong. I removed that line and now it works.

    While this is a solution, I'm not happy with the way JPA / Hibernate work here. The surviving Person is "stealing" the entities from the "dieing" Person without the "dieing" Person first releasing them. So if I don't em.update(dieing) after a flush, I have a contradictory model.