HibernateException: Found shared references to a collection 解决办法

问题现象

项目采用SpringBoot框架,数据库访问采用JPA。新增功能时出现HibernateException: Found shared references to a collection
具体情况是权限管理模型基于RBAC,有User,Role,Authority 三个实体以及上述三者的两两关联表,共计六张表。
当创建一个用户时,首先通过 Role 获取 Authority List,再赋值给 User
的 Authority List,最后将用户写入数据库时抛出以上异常。
数据模型如下,省略部分字段。

@Entity
public class User {
    @ManyToMany
    @JoinTable(name = "UserAuthority", joinColumns = { @JoinColumn(name = "userId") }, inverseJoinColumns = { @JoinColumn(name = "authorityId") })
    private List<Authority> authorities;

    @ManyToOne(fetch = FetchType.EAGER)
    private Role role;
}
@Entity
public class Role {
    @OneToMany(mappedBy = "role")
    private List<User> user;

    @ManyToMany
    @JoinTable(name = "RoleAuthority", joinColumns = { @JoinColumn(name = "roleId") }, inverseJoinColumns = { @JoinColumn(name = "authorityId") })
    private List<Authority> authorities;
}
@Entity
public class Authority {
    @ManyToMany(mappedBy = "authorities")
    private Set<Role> roles;

    @ManyToMany(mappedBy = "authorities")
    private Set<User> users;
}

问题代码如下:

    private User createUser(String name, String role) {
        User user = new User();
        user.setName(name);
        user.setRole(roleService.findByRole(role));
        List<Authority> authorities = roleService.getAuthoritiesByRole(role);
        user.setAuthorities(authorities);
        return user;
    }

问题原因

参见
Hibernate UserGuide 2.8.1. Collections as a value type 两个实体不可以共享同一个集合,上例中 Role 和 User 共用了同一个 Authority List,最终导致以上问题。

Two entities cannot share a reference to the same collection instance. Collection-valued properties do not support null value semantics because Hibernate does not distinguish between a null collection reference and an empty collection.

解决办法

新建一个集合,将原来的集合元素添加进去,并赋值给另一个实体

    private User createUser(String name, String role) {
        User user = new User();
        user.setName(name);
        user.setRole(roleService.findByRole(role));
        List<Authority> authorities = roleService.getAuthoritiesByRole(role);

        List<Authority> clonedAuthorities = new ArrayList<>(authorities.size());
        authorities.forEach(authority -> clonedAuthorities.add(authority));

        user.setAuthorities(clonedAuthorities);
        return user;
    }
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值