【问题标题】:JPA: Left join not working with "is null" in where clauseJPA:左连接不适用于 where 子句中的“is null”
【发布时间】:2014-08-26 15:30:49
【问题描述】:

我在一个非常简单的项目中使用 EclipseLink(2.4、2.5 和 2.6),其中我有一个 Department 实体,每个 Department 链接到一个 Employee 实体,它是 Departmentmanager .

我目前无法使这个简单的查询工作:

select d from Department d where d.manager is null

返回 1 行

select d from Department d left join fetch d.manager where d.manager is null

返回 0 行

我在 H2 数据库上使用 Eclipselink。生成的 SQL 查询似乎没有创建左连接,而是创建了显然会失败的内连接。

SELECT t1.ID, t1.MANAGER_ID, t0.ID, t0.NAME FROM EMPLOYEE t0, DEPARTMENT t1
WHERE ((t1.MANAGER_ID IS NULL) AND (t0.ID = t1.MANAGER_ID))

这是一个错误还是需要什么?或者有人可以帮我解决这个问题吗?

如果有人需要,很乐意提供代码和示例,或者更多信息。

【问题讨论】:

  • 尝试使用此处描述的 fetch-join 查询提示:wiki.eclipse.org/EclipseLink/UserGuide/JPA/…,而不是在 JPQL 中使用它。解析器似乎在那里看到了 d.manager 两次,因此构建了一个内部连接 ​​- 您可能会为此提交一个错误,因为这两个连接应该是独立的
  • @Chris 添加此query.setHint(QueryHints.LEFT_FETCH, "d.manager"); 并没有改变结果。然而,使用这个查询select d from Department d left join d.manager m where m is null 确实有效,但似乎有点牵强。
  • 它起作用的原因是在 where 子句中指定 d.manager 需要一个内连接。当关系没有在其他地方使用时,EclipseLink 可以判断出不需要关系本身,只需要外键,因此不需要加入。当您在其他地方使用关系时,d.manager 内连接胜过任何其他连接,因此使用内连接。通过使用 m 为 null,您将强制它使用外连接逻辑。指定外连接是在 JPA 中执行此操作的正确方法,因为某些关系需要连接来解决。

标签: java jpa eclipselink left-join isnull


【解决方案1】:

使用FETCH JOIN 引用作为副作用在查询中返回的实体似乎不安全。 JPA 规范试图至少对多值关联禁止此类查询(JSR 338,第 4.4.5.3 节):

不允许为FETCH JOIN 子句右侧引用的对象指定标识变量,因此对隐式获取的实体或元素的引用不能出现在查询的其他地方.

您在 EclipseLink 和 Hibernate 上执行的查询会产生不同的结果(EclipseLink 2.6.3:没有结果,Hibernate 4.3.11:所有部门都没有经理):

select d from Department d left join fetch d.manager where d.manager is null

为了解决您的问题,可以使用子查询。可移植的 JPQL 查询可能如下所示(EclipseLink 和 Hibernate 中的结果相同):

select d1 from Department d1 left join fetch d1.manager where exists 
(select d2 from Department d2 where d2.manager is null and d1 = d2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    相关资源
    最近更新 更多