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?
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.