JPQL 查询以根据用户 ID 获取用户的所有角色

JPQL query to fetch all roles of user based on user id

在我的项目中,用户和角色之间存在多对多关系。出于这个原因,我还有连接这两个实体的新实体 UserRole

看起来像这样:

用户:

@Data
@Entity
@Table(NAME = "USERS")
public class User {
    @Id
    @Column(name = "USER_ID")
    private String userId;
    @Basic
    @Column(name = "EMAIL")
    private String email;
   
    @OneToMany(fetch = LAZY, mappedBy = "user")
    private Set<UserRole> userRoles;
}

角色:

@Data
@Entity
@Table(NAME = "ROLES")
public class Role {
    @Id
    @Column(name = "ROLE_ID")
    private String roleId;
    @Basic
    @Column(name = "NAME")
    private String name;
   
    @OneToMany(fetch = LAZY, mappedBy = "role")
    private Set<UserRole> userRoles;
}

用户角色:

@Data
@Entity
@IdClass(UserRolePK.class)
@Table(NAME = "USER_ROLES")
public class UserRole {
    @Id
    @Column(name = "USER_ID")
    private String userId; 

    @Id
    @Column(name = "ROLE_ID")
    private String roleId;
    
    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "USER_ID", insertable = false, updatable = false)
    private User user;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "ROLE_ID", insertable = false, updatable = false)
    private Role role;
}

在这种情况下,用户可以有多个角色。

问题: 如何使用一个查询 (JPQL) 通过他的 ID (userId) 获取用户以及所有分配给他的角色?

我知道我可以先通过 id 获取用户,然后我可以根据 UserRole 单独获取角色 table。

但我想在一次查询中完成。我想让用户拥有角色列表。

您可以使用 fetch 关键字:

@Query(
    "select u " +
    "from User u " +
    "left join fetch u.userRoles "+
    "where u.userId = :id "
)
List<User> getUsersByIdAndRoles(@Param("id") String id)

我建议您按以下方式更正您的映射:

@Data
@Entity
@Table(NAME = "USERS")
public class User {
    @Id
    @Column(name = "USER_ID")
    private String userId;

    @Column(name = "EMAIL")
    private String email;
   
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "USER_ROLES",
              joinColumns = @JoinColumn(name = "USER_ID"),
              inverseJoinColumns = @JoinColumn(name = "ROLE_ID"))
    private Set<Role> roles;
}

@Data
@Entity
@Table(NAME = "ROLES")
public class Role {
    @Id
    @Column(name = "ROLE_ID")
    private String roleId;

    @Column(name = "NAME")
    private String name;
   
    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "roles")
    private Set<User> users;
}

此更正不会影响仅休眠映射的数据库模式。 然后您将能够按照 Andronicus 答案中的建议进行操作:

@Query(
    "select u " +
    "from User u " +
    "left join fetch u.roles "+
    "where u.userId = :id "
)
List<User> getUsersWithFetchedRoles(@Param("id") String id)

如果您继续使用当前的映射,您将无法一次获取多个关联,如 this 文章中所述。

有关 @ManyToMany 协会的其他详细信息,请参阅 documentation