You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@JoinTable关联User与Role时,@WhereJoinTable错误引用中间表字段导致角色过滤失效的问题求助

@JoinTable关联User与Role时,@WhereJoinTable错误引用中间表字段导致角色过滤失效的问题求助

大家好,我最近在使用Hibernate处理多对多关联查询时遇到了一个头疼的问题,想请教一下各位:

我有一个UserEntity对应数据库的user_entity表,通过中间表user_role_mapping和keycloak_role表关联,一个用户可以拥有多个角色。我的需求是查询出仅包含client_role = false的角色的用户,但现在不管怎么查,返回的用户都会带上所有角色,过滤完全没生效。

我尝试的做法和遇到的问题

首先,因为中间表名称和Hibernate默认的不一致,我用@JoinTable指定了正确的中间表信息,然后给角色列表加上了@WhereJoinTable(clause = "client_role = false")来过滤角色,但Hibernate生成的SQL却搞错了过滤的表——它去中间表user_role_mapping里找client_role字段,可这个字段明明是在keycloak_role表中的!

我的实体类代码

UserEntity类

@Entity
@Table(name = "user_entity")
@Getter
@Setter
@EqualsAndHashCode
public class UserEntity {

    @Id
    @Column(name = "id")
    private String id;

    private String email;

    @Column(name = "email_constraint")
    private String emailConstraint;

    @Column(name = "email_verified")
    private String emailVerified;

    private boolean enabled;

    @Column(name = "federation_link")
    private String federationLink;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    private String username;

    @Column(name = "created_timestamp")
    private Long createdAt;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "user_group_membership",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "group_id")
    )
    private List<Group> groups;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "user_role_mapping",
        joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
    )
    @WhereJoinTable(clause = "client_role = false")
    private List<Role> realmRoles;
}

Role类

@Entity(name = "keycloak_role")
@Table(name = "keycloak_role")
@Getter
@Setter
public class Role {

    @Id
    private String id;

    private String name;
    // 补充说明:后来发现这里漏了client_role字段的映射,已经加上了@Column(name = "client_role") private boolean clientRole;
}

Hibernate生成的错误SQL片段

可以看到,过滤条件错误地加在了中间表user_role_mapping上:

select
    realmroles0_.user_id as user_id1_5_0_,
    realmroles0_.role_id as role_id2_5_0_,
    role1_.id as id1_1_1_,
    role1_.name as name2_1_1_
from
    user_role_mapping realmroles0_
inner join
    keycloak_role role1_
on realmroles0_.role_id=role1_.id
where
    (
        realmroles0_.client_role = false
    )
and realmroles0_.user_id=?

尝试原生查询遇到的问题

我后来改用原生查询在Repository里实现,直接写了过滤keycloak_role.client_role的SQL,可运行后返回的UserEntity还是带着所有角色,但我把这段SQL直接拿到数据库控制台执行,是能得到正确的3条角色记录的。

Repository代码:

@Repository
public interface UserRepository extends JpaRepository<UserEntity> {

    @Query(value = "select * from user_entity ue " +
        "join user_group_membership ugm on ugm.user_id = ue.id " +
        "join keycloak_group kg on kg.id = ugm.group_id " +
        "join realm r on r.id = ue.realm_id " +
        "join user_role_mapping urm on ue.id = urm.user_id " +
        "join keycloak_role kr on urm.role_id = kr.id " +
        "where username = :username " +
        "and r.id = 'REALM' " +
        "and kr.client_role = false " +
        "and kg.name in :groups ",
        nativeQuery = true)
    Optional<UserEntity> findByUsernameAndGroups(@Param("username") String username,
                                                @Param("groups") List<String> groups);
}

我现在的疑问和求助点

  1. 为什么@WhereJoinTable会把过滤条件加到中间表?应该怎么修改才能让它正确过滤keycloak_role表的client_role字段?
  2. 原生查询明明SQL执行正确,但返回的实体却没过滤角色,这是为什么?有没有办法让原生查询返回的实体只包含符合条件的角色?

希望各位大佬能帮忙指点一下,谢谢!

备注:内容来源于stack exchange,提问作者iamzexy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 14:22:31