如何用JPQL编写带WHERE子句的左连接查询无指定日期预订的工位
解决JPQL左连接查询工位的问题
正确查询语句(两种可行写法)
写法一:使用NOT EXISTS排除指定日期有预订的工位
@Query("SELECT DISTINCT desk FROM Desk desk LEFT JOIN desk.reservations reservation " + "WHERE reservation IS NULL OR NOT EXISTS (" + " SELECT r FROM Reservation r WHERE r.desk = desk AND r.date = :date" + ")") Page<Desk> findDesks(Pageable pageable, @Param("date") LocalDate date);
写法二:通过左连接指定日期预订后筛选空值
@Query("SELECT DISTINCT desk FROM Desk desk LEFT JOIN desk.reservations reservation " + "ON reservation.date = :date " + "WHERE reservation IS NULL") Page<Desk> findDesks(Pageable pageable, @Param("date") LocalDate date);
原查询的问题分析
- 第三个查询:
WHERE reservation.date <> :date会过滤掉无任何预订的工位,因为这类工位的reservation为null,null <> :date的结果是null,不满足WHERE条件,因此被排除。 - 第二个查询:
(desk.reservations is null or reservation.date <> :date)存在逻辑漏洞——如果某个工位既有指定日期的预订,又有其他日期的预订,会因为存在reservation.date <> :date的记录而被错误返回,不符合需求。 - 第一个查询:
LEFT JOIN ... ON reservation.date <> :date同样会错误包含有指定日期预订的工位(只要该工位还有其他日期的预订),无法准确排除这类工位。
逻辑说明
两种正确写法都精准覆盖了需求:
- 无任何预订的工位:左连接后
reservation为null,满足筛选条件。 - 有预订但指定日期无预订的工位:
- 写法一通过
NOT EXISTS判断该工位在指定日期没有任何预订记录。 - 写法二通过左连接指定日期的预订记录,若连接结果为
null,说明该工位在指定日期无预订。
- 写法一通过
内容的提问来源于stack exchange,提问作者TheBezwet
相关产品推荐
相关产品推荐

