如何搭配@PrimaryKeyJoinColumn使用QueryDsl查询无关联子表记录
QueryDSL 筛选无关联子表记录解决方案
问题原因
直接通过QBooking.booking.editor.id访问关联属性时,QueryDSL默认会生成内连接(INNER JOIN),内连接会直接过滤掉没有匹配editor关联的booking记录,后续再加editor.id is null的条件自然不可能匹配到任何结果。
你预期的SQL使用CROSS JOIN会生成笛卡尔积,执行效率极低,并不推荐使用,以下两种方案生成的SQL逻辑更合理、性能更优。
前置修正
首先确认关联注解配置正确,可选关联需要显式指定optional属性:
class Booking { @Id long id; String status; // 显式指定关联为可选 @OneToOne(optional = true) @PrimaryKeyJoinColumn public Editor editor; }
实现方案
方案1:左连接 + 空值判断
手动指定左连接逻辑,保留无关联的booking记录后再做空值筛选。
注:该方案需要先注入JPAQueryFactory,Spring Boot默认会自动配置该Bean,直接
@Autowired注入即可。
QBooking booking = QBooking.booking; QEditor editor = QEditor.editor; List<Booking> result = new JPAQueryFactory(entityManager) .selectFrom(booking) .leftJoin(booking.editor, editor) .where( booking.status.eq(2), editor.id.isNull() ) .fetch();
方案2:NOT EXISTS 子查询(无需调整原有调用逻辑)
用子查询实现不存在关联判断,执行效率更高,完全兼容你现有QuerydslPredicateExecutor的调用方式,不需要调整DAO层代码:
QBooking booking = QBooking.booking; QEditor editor = QEditor.editor; BooleanBuilder booleanBuilder = new BooleanBuilder(predicate) .and(booking.status.eq(2)) .and(JPAExpressions.selectFrom(editor) .where(editor.id.eq(booking.id)) .notExists() ); dao.findAll(booleanBuilder.getValue());
生成的SQL逻辑如下:
select * from booking where booking.status = ? and not exists (select 1 from editor where editor.id = booking.id)
内容的提问来源于stack exchange,提问作者membersound
相关产品推荐
相关产品推荐

