我有两个JPA实体:
我的目标是只检索与日期参数(planningDate)匹配的预订,同时检索所有时间表,无论在此给定日期是否存在预订。
所以我写道:
SELECT s FROM Schedule as s LEFT JOIN s.reservations as r WHERE r.resDate = :planningDate order by s.startHour
为什么不在这个日期没有预订的时间表,尽管我的LEFT JOIN已经检索到了?
可能与本机查询一样,LEFT JOIN在与WHERE子句组合时看起来像INNER JOIN。
那么,如何更改查询以满足我的要求?我没有在JPQL中找到特定的功能。
答案 0 :(得分:13)
简短回答,请尝试:
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为null”部分)
答案很长: 明确表示这不是由hibernate / JPA人员工作的,但确实如此。生成的SQL也非常有效。如果有人能解释为什么会这样,我会留下最深刻的印象。我多年前就学会了这种模式,但不能为我的生活记住哪里。
一个注意事项:有一种情况,这将不工作,并且在没有预约此计划的情况下。在这种情况下,我可以提供的唯一答案是您可以将查询包装在try / catch中以获取“NoResultException”,并在没有where子句的情况下再次查询(显然,如果没有预留,则不会对resDate进行保留) planningDate)
答案 1 :(得分:2)
在EclipseLink 2.5(Glassfish 4.0,Oracle 11g XE数据库)中:
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 WHERE((t1.ID = t0.assignee_id))按顺序排序(t0.assignee_id为空)那么? ELSE t1.ID END DESC)WHERE ROWNUM< =?)WHERE rnum> ?
from Request r left join r.assignee as a
order by case when a.id is null then 0 else a.id end desc
生成的查询部分(使用左连接):
FROM requests t1 LEFT OUTER JOIN users t0 ON(t0.ID = t1.assignee_id) 按顺序排序(t0.ID为空)那么? ELSE t0.ID END DESC)WHERE ROWNUM< =?) 在哪里> ?
答案 2 :(得分:1)
最后,我认为JPA中LEFT JOIN的概念不适用。
提醒最初的目标:
检索所有计划,无论发生什么,只有在匹配给定的planningDate时才填充预订集合(在这些相应的计划中)。
实际上,即使我设法检索其预订与我的标准不匹配的日程安排,无论如何,这些日程安排将分别重新加载他们的预订集合,如果这些日程表以fetch类型声明为“eager”,那么no限制条款对精确的“规划日期”的影响。这种行为与选择所有日程安排完全相似,没有任何其他限制。
因此,在JPA中解决我的问题的最简单的解决方案是提出2个请求:首先选择计划,然后选择匹配保留到planningDate,然后独立。因此,结果可以重新组合成一个列表并返回。缺点是预订集合会加载到时间。
如果你看到更好的解决方案,我将不胜感激。