微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Spring Data:管理双向多对多关系

如何解决Spring Data:管理双向多对多关系

我在 RoleScope 之间存在双向多对多关系。在 CascadeType.PERSIST 的帮助下创建两个实体甚至其子实体既简单又直接。

Role 实体很简单:

@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;

}

还有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;

}

他们的存储库只是 CrudRepository 扩展:

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

以下代码段举例说明了实体插入:

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

RoleScope 都可以在 CascadeType.PERSIST 的帮助下轻松自动持久化,如下所示:

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

但是...更新 managedRole 会导致 org.hibernate.PersistentObjectException: detached entity passed to persist 异常:

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

我尝试修改 Role::scopesCascadeType 以包含 DETACHMERGE 和/或 REFRESH,但没有成功。我们如何解决这个问题?

解决方法

您很可能会遇到问题,因为您没有在双向映射中维护关系的双方。让我们在 Role 中说:

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

老实说,我会完全放弃双向映射。保持这种状态真是一场噩梦。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。