JPQL:内部连接没有重复记录

时间:2011-11-20 04:43:58

标签: jpa duplicates inner-join jpql

以下是一个据称是Sun官方考试的一部分的问题:

  

Reader实体与a具有一对多的双向关系   书籍实体。两个Reader实体是持久的,每个实体都有两本Book   与它们相关的实体。例如,读者1有书a和   书b,而读者2有书c和书d。哪个查询返回一个   收集少于四个元素?
      A.从书中选择b.reader b
      B.从书中选择r INNER JOIN b.reader r
      C.选择r FROM Reader r INNER JOIN r.books b
      D.从书b中选择r LEFT JOIN b.reader r LEFT JOIN FETCH r.books

鉴于答案是C,我认为这是不正确的。据我所知,JPA提供者将生成两个表的内连接的SQL。因此,在所有情况下,我们将获得4条记录。我已经进行了一对多关系的测试,并且包含了重复项。

谁错了,我还是Sun?

2 个答案:

答案 0 :(得分:14)

来自Mike Keith的回答,EJB 3.0共同规范主管:

在规范中有一些与重复相关的陈述。

  1. JOIN FETCH是JOIN的变体,但它确实表明类似的JOIN语义适用(除了选择了更多数据)。规范(JPA v2.0的4.4.5.3节)给出了一个返回重复Department行的示例,尽管Employee对象不在select子句中。

  2. 更直接的引用是在SELECT部分​​(JPA v2.0的4.8节)中明确说明

  3. “如果未指定DISTINCT,则不会消除重复值。”

    实际上,许多JPA提供商确实删除了重复项,原因如下:

    a)用户的便利性,因为某些用户在SQL中不够了解并且不期望它们 b)通常不存在需要重复的用例 c)可以将它们添加到结果集中,如果维护了对象标识,则会自动消除重复

答案 1 :(得分:0)

C是正确的,加入ToMany关系不应该返回重复项。 JPA提供程序应自动使用distinct来过滤掉这些。我相信这是规范所要求的,尽管它可能是规范中定义不太明确的领域之一。

如果使用连接提取,我相信规范实际上需要返回重复项。这很奇怪,可以看出为什么你会想要重复。如果你在连接提取上添加了一个独特的,那么它们将被过滤(在内存中,因为需要选择所有行)。

这就是EclipseLink的工作方式。

所有其他案例选择书籍而不是读者,所以得到重复,C选择读者,所以不应该重复。

相关问题