【问题标题】:Assigning a role to a user without FetchType.EAGER将角色分配给没有 FetchType.EAGER 的用户
【发布时间】:2021-09-16 03:42:45
【问题描述】:

我有一个 @ManyToMany 表 enter image

role 表包含角色 ROLE_USERROLE_ADMIN 等。

下面我将展示如何在 userrole 表之间创建关系。

角色.class

            @ManyToMany(mappedBy = "roleList", cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.EAGER)
            private List<User> userList = new ArrayList<>();


            public void addPerson(User user) {
                    userList.add( user );
                    user.getRoleList().add( this );
                }

User.class

            @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
            @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
            private List<RoleUser> roleUserList = new ArrayList<>();


            public void addRole(Role role) {
                    roleList.add(role);
                    role.getUserList().add( this );
                }

假设我已经在 role 表中有一个角色列表。现在我想创建一个用户并为其分配这些角色之一。

在这种情况下,我正在尝试执行以下操作:

我指定FetchType.EAGER(这对我来说是不可取的。否则它不起作用),然后我在控制器中编写以下内容:

            Role role = serviceJpa.findRoleByRoleName("ROLE_USER");
            role.addUser(user);
            serviceJpa.saveRole(role);

如果我们看一下,用户已被完美添加,角色已成功分配给该用户。

但正如我之前所说,FetchType.EAGER 不适合我,因为我不想在访问角色表时获得一百万用户。

但如果我使用 FetchType.LAZY 则会引发异常:

消息请求处理失败;嵌套异常是 org.hibernate.LazyInitializationException: failed to lazily initialize 角色集合:com.testmany.entity.Role.userList,可以 不初始化代理 - 没有会话

我马上有一个问题 - 也许我没有正确添加用户并错误地为他分配角色?

如果我以其他方式进行,例如:

            User user = new User("Иван");
             
            Role role = serviceJpa.findRoleByRoleName("ROLE_USER");

            user.addRole(role);
            serviceJpa.saveUser(user);

然后发生另一个异常:

消息请求处理失败;嵌套异常是 org.springframework.dao.InvalidDataAccessApiUsageException: detached 传递给持久化的实体:com.testmany.shop.entity.Role;嵌套的 异常是 org.hibernate.PersistentObjectException:分离的实体 传递给坚持:com.testmany.entity.Role

我做错了什么?如何使用 FetchType.LAZY 添加用户,即不使用 FetchType.EAGER。添加用户并为其分配角色的正确方法是什么?我究竟做错了什么。我已经查看并重新阅读了一堆信息、hibernate 文档,但没有任何帮助。你好吗,表演?

【问题讨论】:

    标签: java spring hibernate jpa


    【解决方案1】:
      @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
        @JoinTable(name = "user_role",
                joinColumns = {@JoinColumn(name = "user_id")},
                inverseJoinColumns = {@JoinColumn(name = "role_id")}
        )
    private List<RoleUser> roleUserList;
    

    你可以试试这个可能会有帮助

    【讨论】:

      【解决方案2】:

      在您的用户model 中设置惰性获取如下:

      @ManyToMany(fetch = FetchType.LAZY)
          @JoinTable(name = "app_user_role", joinColumns = @JoinColumn(name = "userid"), inverseJoinColumns = @JoinColumn(name = "roleid"))
          private List<Role> roles;
      

      为了补偿延迟加载,请在您的 controller 中的某处初始化它,如下所示(只是给您提示):

      @ModelAttribute("roles")
          public List<Role> initializeRoles() {
              return (List<Role>) roleJPARepository.findAll();
          }
      

      然后,在您的代码中的某处(比如Service),将角色设置为用户,如下所示:

      entity.setRoles(user.getRoles());
      

      有关通过 UI 设置/编辑用户角色的完整示例,请参见我的 GitHub 存储库 - https://github.com/ajkr195/springbootrocks

      这与您要查找的内容非常接近。

      【讨论】:

      • 我的一切都与你和你的 github 中显示的一样。
      • 在保存用户实体的同时尝试对角色使用 setter。也不要将角色保存在同一块中。我建议您将角色创建功能分开。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-14
      • 2015-08-01
      • 1970-01-01
      • 2019-08-11
      • 1970-01-01
      • 1970-01-01
      • 2018-06-13
      相关资源
      最近更新 更多