Hibernate一对一映射关联问题:强制Query2生成LEFT JOIN
强制Hibernate在JPQL查询中生成LEFT JOIN而非INNER JOIN
实体定义
我创建了两个单向关联的实体:
User实体
class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "user_id", unique = true, nullable = false) private String userId; @Column("email") private String email; @OneToOne @JoinColumn(name = "user_id",insertable=false, updatable=false) private UserAccountStatus accountStatus; }
UserAccountStatus实体
public class UserAccountStatus { @Id private String userId; private String status; }
现有查询及生成的SQL
我定义了以下两个查询:
查询1
@EntityGraph(attributePaths = {"accountStatus"}) Optional<UserEntity> findByEmail(String email);
Hibernate为该查询生成了LEFT JOIN语句:
select * from user_entity ue1_0 left join cs_customer_status as1_0 on as1_0.user_id=ue1_0.user_id where ue1_0.email=?
查询2
@EntityGraph(attributePaths = {"accountStatus"}) @Query("SELECT u FROM UserEntity u WHERE u.kycVerified = true and u.accountStatus.status = 'ACTIVE'") Slice<UserEntity> findAllVerifiedAndActiveUsers(Pageable pageable);
Hibernate为该查询生成了INNER JOIN语句:
select * from user_entity ue1_0 join cs_customer_status as1_0 on as1_0.user_id=ue1_0.user_id where ue1_0.kyc_verified=1 and as1_0.status='ACTIVE' limit ?, ?
问题
我需要让查询2也生成LEFT JOIN语句,同时筛选出accountStatus不为null且状态为'ACTIVE'的用户,期望两个查询都使用LEFT JOIN。
解决方案
要强制Hibernate在JPQL中使用LEFT JOIN,必须显式指定LEFT JOIN关联,不能依赖隐式引用关联属性的方式。修改查询2的JPQL语句,显式LEFT JOIN关联的accountStatus并使用别名引用其属性:
@EntityGraph(attributePaths = {"accountStatus"}) @Query("SELECT u FROM UserEntity u LEFT JOIN u.accountStatus ac WHERE u.kycVerified = true AND ac.status = 'ACTIVE'") Slice<UserEntity> findAllVerifiedAndActiveUsers(Pageable pageable);
说明
- 显式
LEFT JOIN u.accountStatus ac会让Hibernate生成LEFT JOIN语句,替代默认的INNER JOIN。 - 虽然使用了LEFT JOIN,但
ac.status = 'ACTIVE'的条件会自动排除掉没有匹配accountStatus的用户(因为NULL值无法满足等于'ACTIVE'的条件),最终结果和原INNER JOIN一致,但SQL语句会符合要求。
内容的提问来源于stack exchange,提问作者Sridar G
相关产品推荐
相关产品推荐

