【问题标题】:JPA ManyToMany updating recordJPA 多对多更新记录
【发布时间】:2019-11-20 23:05:36
【问题描述】:

我有SpringBoot 2.1.3 应用程序。我使用的是Spring Security,而不是我有两个实体UserRoles,类似于以下内容:

@Entity
@Data
@Table(name = "USER")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private boolean enabled;
    @ManyToMany(mappedBy = "users")
    private List<Roles> role;
}

@Entity
@Data
@Table(name = "ROLES")
public class Roles {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private Role ruolo;
    @ManyToMany
    private List<User> users;
}

角色是一个简单的enum,如下:

public enum Role {
   ROLE_ADMIN,
   ROLE_USER;
}

现在让SpringBoot 创建空的database 并假设添加一些默认记录:

现在考虑Roles 表将最多包含 2 个角色:ROLE_ADMINROLE_USER。我设法用Roles 添加新的User,我设法用各自的Role 删除User(检索User -> 从User 获取Roles -> 迭代Roles 并为每个一删除User -> 删除User:

User user = userService.getByPk(Id);

List<Roles> roles = user.getRoles(); // this list size should be always 1
for (Rolesr : roles) {
   r.getUsers().remove(user);
}

utenteService.deleteByPk(opeId);

将同时删除 User 记录和各自的 Roles_User 记录。

不能做的是CHANGE用户角色。正如我们在图片中看到的那样,我有一个UserROLE_ADMIN Roles.

我想将 Roles,对于这个 User,从 ROLE_ADMIN 更改为 ROLE_USER!该函数应修改Roles_User如下:

roles_id  user_id
   2         1

我已经尝试了所有方法,但没有按预期工作。获得的最佳结果是在User 中添加两个Roles(ROLE_ADMIN 和ROLE_USER):

roles_id  user_id
   2         1
   1         1

在该应用程序中,ROLES 是分层的,User 最多可以有一个Role。我使用了ManyToMany 关系,因为是默认的SpringSecurity DB 实现(我不知道我是否可以使用OneToMany 关系)。

我要疯了!你能帮帮我吗?

谢谢

【问题讨论】:

  • 你试过什么?发布您的代码。您必须从 ADMIN 角色的用户中删除该用户,并将其添加到 USER 角色的用户中。

标签: hibernate spring-boot jpa


【解决方案1】:

更好,保存新列表或Check this link

User user = userService.getByPk(Id);
// Add your code to delete all association of an user
// Add below code to assign new role
List<Roles> roles = new ArrayList<>();
roles.add(Role.ROLE_USER);
user.setRoles(roles);

utenteService.updateByPk(user);

【讨论】:

    【解决方案2】:

    感谢大家的回答。 @Atul Jain 我已经尝试过你的代码,但是如果没有级联,肯定不会工作。

    我终于成功了,这是解决方案:

    // getting my User and removing all his roles (max one)
    User user = userRepository.findById(1L).get();
    user.getRoles().clear();
    
    // get ROLE_ADMIN Role
    Roles adminRole = rolesRepository.findById(1L).get();
    
    // get all users with ROLE_ADMIN role and removing my user
    List<User> adminUsers = adminRole.getUsers();
    adminUsers.remove(user); 
    
    List<Roles> roles = new ArrayList<>();
    // get ROLE_USER Role and adding my User
    Roles role = rolesRepository.findById(2L).get();
    role.getUsers().add(user);
    roles.add(role);
    
    user.setRoles(roles);
    
    userRepository.save(user);
    rolesRepository.save(adminRole);
    rolesRepository.save(role);
    

    我想记住JPA 接口在他的Repository 中没有update 方法,在这种情况下我无法实例化Role,因为这个table 应该被视为@987654327 @,在应用程序启动时填写,并且从不(可能很少..:))更新。

    因此我必须获取我要添加的Role

    谁能告诉我原因:

    User user = userRepository.findById(1L).get();
    List<User> adminUsers = adminRole.getUsers(); // adminUser CONTAIN user of previous line
    adminUsers.remove(user) // user IS NOT REMOVED, if debugging I select whole line and Watch result is false
    

    谢谢大家

    【讨论】:

      【解决方案3】:

      问题是您将Roles.users 设置为mappedBy='users'Users 表中的拥有实体。仅保留对拥有实体所做的更改。相反,请尝试将mappedBy='roles' 放入Roles 表中。

      当然,您应该使用Set&lt;Role&gt; role 而不是List。列表是有序的,JPA/Spring-Data 将尝试保留顺序,这可能是性能开销。此外,在 JPA 中使用 Lists 定义的多个 XToMany 关系可能会出现问题。

      虽然您可能只想为任何用户提供一个角色,但 Spring Security 定义并处理 ManyToMany 关系。

      JPA 有一个更新——persist,既可以保存也可以更新。此外,对附加实体所做的更改会自动持久化(更新)。

      【讨论】:

      • 是的,我知道JPA 更新实体...他会使用save 方法自动完成,如果Entity 设置了主键JPA 执行update 或者insert 手术。我刚刚对@Atul 说updateByPk() 方法在JpaRepository 接口中不存在。
      猜你喜欢
      • 2011-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-15
      相关资源
      最近更新 更多