如何将 LEFT JOIN 和 Where 子句与 JPQL 结合使用?

2022-09-04 01:26:58

我有两个JPA实体:

  • 时间表(包含预订清单)
  • 预订(包含日期字段:日期 resDate)

我的目标是仅检索与日期参数(planningDate)匹配的预订,同时检索所有计划,无论预订在此给定日期是否存在。

所以我写了:

SELECT s FROM Schedule as s LEFT JOIN s.reservations as r WHERE r.resDate = :planningDate order by s.startHour

为什么没有预订的时间表,尽管我离开了加入,但仍然没有检索到这一天?

可能,与本机查询一样,在与 WHERE 子句组合时,LEFT JOIN 看起来像 INNER JOIN。

那么,如何更改查询以满足我的要求?我没有在JPQL中找到特定的功能。


答案 1

啊,这确实是JPA的经典之作。我提供的以下答案 - 我无法确切解释为什么它有效,但我可以为你解决这个问题

简短的回答,尝试:

SELECT s FROM Schedule as s LEFT JOIN s.reservations as r WHERE 
(r.resDate is null or r.resDate = :planningDate) order by s.startHour

(这里的关键是“r.resDate is null”部分)

长答案:这被明确说为冬眠/JPA人不起作用,但它确实如此。生成的 SQL 也非常高效。如果有人能解释为什么这有效,我会留下最深刻的印象。我多年前就学会了这种模式,但无法为我的生活记住在哪里。

一个注意:有一种情况是这不起作用的,那就是在这个时间表没有预订的情况下。在这种情况下,我能提供的唯一答案是,您可以将查询包装在“NoResultException”的try/catch中,并在没有where子句的情况下再次查询(显然,如果没有保留,则没有在planningDate上使用resDate的保留)


答案 2

在EclipseLink 2.5(Glassfish 4.0,Oracle 11g XE数据库)中:

不起作用(未分配给 r.assignee 的别名):

from Request r left join r.assignee 
order by case when r.assignee.id is null then 0 else r.assignee.id end desc

生成的查询部分(使用 decart 乘法):

从请求 t0 , 用户 t1其中 ((t1.ID = t0.assignee_id)) 按大小写排序,当 (t0.assignee_id 为空)时?ELSE t1.ID END DESC) A WHERE ROWNUM <= ?)rnum >哪里 ?

作品(为 r.assignee 添加了别名):

from Request r left join r.assignee as a
order by case when a.id is null then 0 else a.id end desc

生成的查询部分(使用左连接):

从请求 t1 左外部加入用户 t0ON (t0.ID = t1.assignee_id) 按大小写排序,当 (t0.ID 为空)时?ELSE t0.ID END DESC) WHERE ROWNUM <= ?)rnum >哪里 ?


推荐