使用@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); }
我现在的疑问和求助点
- 为什么
@WhereJoinTable会把过滤条件加到中间表?应该怎么修改才能让它正确过滤keycloak_role表的client_role字段? - 原生查询明明SQL执行正确,但返回的实体却没过滤角色,这是为什么?有没有办法让原生查询返回的实体只包含符合条件的角色?
希望各位大佬能帮忙指点一下,谢谢!
备注:内容来源于stack exchange,提问作者iamzexy
相关产品推荐
相关产品推荐

