【问题标题】:JPQL: Inner Join without duplicate recordsJPQL:没有重复记录的内部联接
【发布时间】:2012-01-02 05:25:19
【问题描述】:

下面是一个问题,据说是 Sun 官方考试的一部分:

Reader 实体与 图书实体。两个 Reader 实体被持久化,每个实体有两个 Book 与他们相关的实体。例如,读者 1 有书 a 和 书 b,而读者 2 有书 c 和书 d。哪个查询返回一个 少于四个元素的集合?
A. 从​​书 b
中选择 b.reader B. SELECT r FROM Book b INNER JOIN b.reader r
C. SELECT r FROM Reader r INNER JOIN r.books b
D. SELECT r from Book b LEFT JOIN b.reader r LEFT JOIN FETCH r.books

给出的答案是 C,我认为这是不正确的。据我了解,JPA 提供程序将生成具有两个表内部连接的 SQL。因此,在所有情况下,我们都会得到 4 条记录。我已经用一对多关系运行了一个测试,并且包含了重复项。

谁错了,我还是孙?

【问题讨论】:

  • 我用 Hibernate 运行了测试,也有重复。 select distinct r 可用于删除重复项。
  • 感谢您的检查。我会使用 SELECT r FROM Reader r WHERE r.books is EMPTY 来获取已借书的独特读者......但是,他们声称 C 是正确的答案。
  • 当然,不是空的
  • 我查看了 Oracle 的教程并且更加困惑: >SELECT DISTINCT p FROM Player p, IN(p.teams) t 检索到的数据:属于一个团队的所有玩家。您也可以使用 JOIN 语句来编写相同的查询: SELECT DISTINCT p FROM Player p JOIN p.teams t 此查询也可以重写为: SELECT DISTINCT p FROM Player p WHERE p.team IS NOT EMPTY 为什么要使用 DISTINCT in后一种情况?
  • 我的测试也导致重复。使用 EclipseLink 2.7.7 和 MySQL 8.0.22

标签: jpa duplicates inner-join jpql


【解决方案1】:

来自 EJB 3.0 共同规范负责人 Mike Keith 的回答:

规范中有一些与重复项相关的声明。

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

  2. 更直接的参考是在 SELECT 部分(JPA v2.0 的第 4.8 节),它明确指出

"如果未指定 DISTINCT,则不会消除重复值。"

许多 JPA 提供者实际上出于以下几个原因删除了重复项:

a) 用户的方便,因为有些用户在 SQL 方面不够了解并且不期望他们 b) 通常没有要求复制的用例 c) 它们可能会被添加到结果集中,如果保持对象身份,则重复项会自动消除

【讨论】:

    【解决方案2】:

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

    如果使用连接提取,我相信规范实际上要求返回重复项。这很奇怪,可以看出为什么你每个人都想要重复。如果您在连接提取上放置一个 distinct,那么它们将被过滤(在内存中,因为需要选择所有行)。

    这就是 EclipseLink 的工作原理。

    所有其他情况都选择 Books not reader,因此获取重复项,C 选择 Readers,因此不应获取重复项。

    【讨论】:

    • James,我浏览了规范,但未能找到消除重复项的要求。但是,在 toplink (eclipse-link) 文档中,我确实看到提到了删除重复项:Join reading can result in returning duplicate data if a one-to-many or a shared one-to-one relationship is joined. Although TopLink correctly filters the duplicate results from the object result, the duplicate data still must be fetched from the database and can degrade performance, especially if multiple one-to-many relationships are joined. 您能否使用 JPA 运行类似的查询并分享结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多