【问题标题】:Spring how to manage a mapping table (Many to Many)Spring如何管理映射表(多对多)
【发布时间】:2016-06-17 18:14:07
【问题描述】:

我正在开发一个用户可以拥有一个或多个角色的应用程序,为此我决定创建一个映射(中间)表,所以我以UserRoleUserRole 结束,如下所示:

在此应用中,用户所拥有的角色决定了他何时可以访问前端中的某些视图或操作。我唯一需要的是检索用户拥有的角色并添加/删除它们。 JPA Tools 为我创建了他遵循 EJB(简化):

用户

/**
 * The persistent class for the usuario database table.
 * 
 */
@Entity
@NamedQuery(name="Usuario.findAll", query="SELECT u FROM Usuario u")
public class Usuario implements Serializable {

    private static final long serialVersionUID = 1L;

    private int idUsuario;

    private List<RolUsuario> rolUsuarios;

    public Usuario() {
    }


    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    public int getIdUsuario() {
        return this.idUsuario;
    }

    public void setIdUsuario(int idUsuario) {
        this.idUsuario = idUsuario;
    }


    //bi-directional many-to-one association to RolUsuario
    @OneToMany(mappedBy="usuario")
    public List<RolUsuario> getRolUsuarios() {
        return this.rolUsuarios;
    }

    public void setRolUsuarios(List<RolUsuario> rolUsuarios) {
        this.rolUsuarios = rolUsuarios;
    }

    public RolUsuario addRolUsuario(RolUsuario rolUsuario) {
        getRolUsuarios().add(rolUsuario);
        rolUsuario.setUsuario(this);

        return rolUsuario;
    }

    public RolUsuario removeRolUsuario(RolUsuario rolUsuario) {
        getRolUsuarios().remove(rolUsuario);
        rolUsuario.setUsuario(null);

        return rolUsuario;
    }

}

USER_ROLE

/**
 * The persistent class for the rol_usuario database table.
 * 
 */
@Entity
@Table(name="rol_usuario")
@NamedQuery(name="RolUsuario.findAll", query="SELECT r FROM RolUsuario r")
public class RolUsuario implements Serializable {
    private static final long serialVersionUID = 1L;
    private int idRol_Usuario;
    private Usuario usuario;
    private Rol rol;

    public RolUsuario() {
    }


    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    public int getIdRol_Usuario() {
        return this.idRol_Usuario;
    }

    public void setIdRol_Usuario(int idRol_Usuario) {
        this.idRol_Usuario = idRol_Usuario;
    }


    //bi-directional many-to-one association to Usuario
    @ManyToOne(fetch=FetchType.LAZY)
    public Usuario getUsuario() {
        return this.usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }


    //bi-directional many-to-one association to Rol
    @ManyToOne(fetch=FetchType.LAZY)
    public Rol getRol() {
        return this.rol;
    }

    public void setRol(Rol rol) {
        this.rol = rol;
    }

}

在我的项目中,我使用 EJB 为前端创建 POJO。当我询问给定用户的完整角色列表时,我应该如何去做:

  1. 使用 CrudRepository 创建一个 UserRole 存储库,方法如下 List&lt;RolUsuario&gt; findByUsuario(Usuario user);
  2. UserRole 的列表返回给我的User Service 并查看 将每个角色提取到 UserPOJO

  3. 的列表
  4. 发送到前端。

或者有什么方法可以直接在表UserRole 中获得Roles 的列表,其中User(Id?) = something?

这对我来说很难描述。我的应用只关心用户的角色,而不关心映射表实体,所以底线是我必须以某种方式获取它们,但我不知道从哪里开始。

任何指针都会非常有用。

编辑:

或者我可以...

  1. 为用户添加新角色创建 UserRole。
  2. 将 UserRole 添加到 User 内部的列表中。
  3. 要获取用户的角色,请改为获取 UserRolelist。

【问题讨论】:

  • 一种选择是没有 UserRole 模型,而只有 User 和 Role。您可以指定是用户拥有角色列表,并在角色表中拥有用户列表。
  • 这里是一个例子:mkyong.com/hibernate/…
  • 问题是中间表可能有一天会自己变成一个实体。

标签: java spring hibernate jpa


【解决方案1】:

UserrolUsuarios 列表中的角色。在您的User 服务中,查找用户,通常使用id。如果你有idUsuario,那么用户EntityManger.find(Usuario.class, idUsuario),你可以通过getRolUsuarios读取用户角色,或者至少这是典型的做法。

在您的表设计中,您有一个用于 user_role 表 (iduserrole) 的 id,这对于 join table 是不典型的。通常,您只需使用 OneToMany 注释创建您的实体,然后为您创建 join table

@Entity
public class User {
    @Id @GeneratedValue private Long id;

    @ManyToMany
    Set<Role> roles;
}

@Entity
public class Role {
    @Id @GeneratedValue private Long id;

}

这两个类将创建三个表,User 表、Role 表和 User_RoleJoin Table。连接表将包含来自用户的每个 id 和其中的角色表,仅此而已。

编辑:roles 更改为 ManyToMany,因为否则将向数据库添加一个约束,这将阻止 Role 被添加到多个用户。通常,角色表中只有唯一的角色,例如USERADMIN 等,因此您希望能够将它们分配给多个用户。

这是你要找的吗?

【讨论】:

  • 看起来 UserRole 应该有 many-to-many 关系。
  • many-to-many 表示两个用户可以拥有ADMIN 角色,例如。这与角色表通常只有唯一角色这一事实并不矛盾。
  • 是的,你是对的。在我喝咖啡之前,我在想 ManyToOne。再次感谢。
【解决方案2】:

您的用户和角色架构不常用。我建议你建立一个从用户到角色的@ManyToMany 关联。如果您需要将连接表映射到实体(不太可能),您可以稍后再做。并且,请使用英文标识符和 Java 命名约定 (idRol_Usuario)。它将帮助您和其他人。

@Entity
@Table
public class User {

    @Id
    @GeneratedValue
    private Long pid;

    @ManyToMany(fetch = FetchType.LAZY)
    private List<Role> roles;

}

@Entity
@Table
public class Role {

    @Id
    private Long pid;

    @Column
    private String name;

}

你也可以使用Set&lt;Role&gt;

@ManyToMany(fetch = FetchType.LAZY)
private Set<Role> roles;

【讨论】:

  • 是的,名字很抱歉,我在西班牙国家学习,所以有时会忘记换名字。现在很晚了,所以我明天试试,只有一个问题;使用这是否意味着摆脱中间表?喜欢去 sqlWorkbench 并删除所述表并添加新的多对多关系?
  • @CodeGrasshopper No. Hibernate 将为many-to-many 关系创建一个连接表。您可以使用 @JoinTable 注释指定它的名称和列名。
  • @CodeGrasshopper 您可以参考this answer 以获取@JoinTable 示例。但是,也许,你不需要使用这么复杂的东西(不需要指定约束的名称)。
猜你喜欢
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 2023-03-14
  • 2018-02-26
  • 1970-01-01
  • 2018-06-01
  • 2021-05-17
  • 2020-06-25
相关资源
最近更新 更多