Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a bidirectional many-to-many relationship between a Role and Scope. Creating both entities and even their childs with the help of CascadeType.PERSIST is easy and straightforward.

The Role entity is simples as that:

@Entity
@Table(uniqueConstraints = @UniqueConstraint(name = "role_name", columnNames = "name"))
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;
    
    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST, mappedBy = "roles")
    private Set<Scope> scopes;

}

And the Scope:

@Entity
@Table(uniqueConstraints = @UniqueConstraint(name = "scope_name", columnNames = "name"))
public class Scope {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;

    @JoinTable(name = "role_scopes", joinColumns = @JoinColumn(name = "scope_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    @ManyToMany(cascade = CascadeType.REMOVE)
    private Set<Role> roles;

}

Their repositories are simply CrudRepository extensions:

public interface RoleRepository extends CrudRepository<Role, Long> {}
public interface ScopeRepository extends CrudRepository<Scope, Long> {}

The following snippet exemplifies the entities insertion:

Role adminRole = roleRepository.save(new Role("ADMIN"));
Scope allReadScope = scopeRepository.save(new Scope("all.read"));
Scope allWriteScope = scopeRepository.save(new Scope("all.write"));

Role and Scope can be both automatically easily persisted with the help of the CascadeType.PERSIST, as follows:

Role managedRole = roleRepository.save(new Role("ADMIN", new Scope("all.read"), new Scope("all.write")));

However... Updating managedRole leads to org.hibernate.PersistentObjectException: detached entity passed to persist exception:

managedRole.getScopes().remove(allReadScope);
roleRepository.save(managedRole); // PersistentObjectException!

I tried modifying the Role::scopes's CascadeType to also include DETACH, MERGE and/or REFRESH with no success. How do we get around this?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
324 views
Welcome To Ask or Share your Answers For Others

1 Answer

Most likely you face the problem, because you don't maintain both sides of the relationship in the bidirectional mapping. Lets say in Role:

void add(Scope scope) {
   this.scopes.add(scope);
   scope.getRoles().add(this);
}

To be honest with you, I'd resign fully from bidirectional mapping. Maintaining this is a real nightmare.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...