以下是一个据称是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?
答案 0 :(得分:14)
来自Mike Keith的回答,EJB 3.0共同规范主管:
在规范中有一些与重复相关的陈述。
JOIN FETCH是JOIN的变体,但它确实表明类似的JOIN语义适用(除了选择了更多数据)。规范(JPA v2.0的4.4.5.3节)给出了一个返回重复Department行的示例,尽管Employee对象不在select子句中。
更直接的引用是在SELECT部分(JPA v2.0的4.8节)中明确说明
“如果未指定DISTINCT,则不会消除重复值。”
实际上,许多JPA提供商确实删除了重复项,原因如下:
a)用户的便利性,因为某些用户在SQL中不够了解并且不期望它们 b)通常不存在需要重复的用例 c)可以将它们添加到结果集中,如果维护了对象标识,则会自动消除重复
答案 1 :(得分:0)
C是正确的,加入ToMany关系不应该返回重复项。 JPA提供程序应自动使用distinct来过滤掉这些。我相信这是规范所要求的,尽管它可能是规范中定义不太明确的领域之一。
如果使用连接提取,我相信规范实际上需要返回重复项。这很奇怪,可以看出为什么你会想要重复。如果你在连接提取上添加了一个独特的,那么它们将被过滤(在内存中,因为需要选择所有行)。
这就是EclipseLink的工作方式。
所有其他案例选择书籍而不是读者,所以得到重复,C选择读者,所以不应该重复。