加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – Spring数据jpa分离实体

发布时间:2020-12-15 04:28:25 所属栏目:Java 来源:网络整理
导读:我开始使用 Spring Data JPA在Spring Boot应用程序上设置用户和角色之间的ManyToMany关系. 此关系在User类中定义如下: @ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)@JoinTable(name="user_role",joinColumns = {@JoinColumn(name="user
我开始使用 Spring Data JPA在Spring Boot应用程序上设置用户和角色之间的ManyToMany关系.

此关系在User类中定义如下:

@ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
@JoinTable(name="user_role",joinColumns = {@JoinColumn(name="user_id")},inverseJoinColumns = {@JoinColumn(name="role_id")})
private Set<UserRole> roles;

我用以下方法创建角色

@Transactional
private void generateSeedRoles() {
    UserRole adminRole = new UserRole(RoleEnum.ADMIN.toString());
    userRoleRepository.save(adminRole);

    UserRole userRole = new UserRole(RoleEnum.USER.toString());
    userRoleRepository.save(userRole);
}

之后为用户分配角色失败:

@Transactional
private void generateSeedUsers() {
    UserRole adminRole = userRoleRepository.findUserRoleByRoleName("ADMIN");

    User user = User.createUser("user1","user1@user.com","pass");
    user.setRoles(new HashSet<UserRole>(Arrays.asList(adminRole)));

    userRepository.save(user);
}

抛出以下异常(为便于阅读而格式化):

org.springframework.dao.InvalidDataAccessApiUsageException: 
detached entity passed to persist: co.feeb.models.UserRole; 
nested exception is org.hibernate.PersistentObjectException: 
detached entity passed to persist: co.feeb.models.UserRole

但是,如果在创建关系之前保存用户,则它可以正常工作:

@Transactional
private void generateSeedUsers() {
    UserRole adminRole = userRoleRepository.findUserRoleByRoleName("ADMIN");

    User user = User.createUser("user1","pass");
    //Save user
    userRepository.save(user);

    //Build relationship and update user
    user.setRoles(new HashSet<UserRole>(Arrays.asList(adminRole)));
    userRepository.save(user);
}

必须保存/更新用户两次对我来说似乎有些不合理.有没有办法将收到的角色分配给新用户而不先保存用户?

解决方法

当您保存实体时,Spring会在内部检查实体是否是新的(我忘记确切的机制),并发出持久性(如果是新的)或合并(如果存在).

由于您已经使用Cascade.ALL定义了User与UserRole的关系,因此来自User的任何持久/合并也将级联到UserRole.

鉴于Spring如何实现保存以及上面级联的行为,以下是一些需要考虑的方案:

>如果User和UserRole都是新的 – 你在保存用户时会得到一个持久的动作,并且一个级联的持久存在UserRole,因为UserRole是新的,所以工作正常.
>如果User是新的但UserRole已经存在 – 再次保存User时会得到一个持久动作,并且级联持续存在UserRole,这会导致错误,因为UserRole已经存在!

如果您可以保证添加到用户关系的任何UserRole始终存在,您只需从级联选项中删除Cascade.Persist即可.否则,我相信在上述两种情况下保存用户时,您必须使用合并 – 通过自定义存储库和entityManager.

关于你使用Cascade.ALL,在这种情况下可能没有意义,因为你有一个@ManyToMany关系,从用户到UserRole级联ALL可能会产生一些不良影响(例如Cascade.Remove会每次删除UserRole用户被删除).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读