0

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?

EasterBunnyBugSmasher
  • 1,507
  • 2
  • 15
  • 34
  • I'm confused on how any of this is getting persisted. Are you saving your updated Person object back into some existing repository or in code that we are not seeing? Your changing the roles on the Person object but, mergeInto() is a void method so, your not returning anything or saving somewhere inside that method before calling clear() on the dieing roles. – duppydodah Apr 24 '21 at 23:02
  • the Person entities are attached to my EntityManager, so any change is persisted into the database – EasterBunnyBugSmasher Apr 25 '21 at 10:00

1 Answers1

0

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.

EasterBunnyBugSmasher
  • 1,507
  • 2
  • 15
  • 34