【问题标题】:How can I do a join using the same table with JPA Repository?如何使用与 JPA 存储库相同的表进行连接?
【发布时间】:2017-12-14 05:41:51
【问题描述】:

我用 MySQL 编写了这个查询,它可以工作:

select c.*
from macchine.check_list c
join (select pratica, documentazione, max(versione) as versione
      from macchine.check_list
      group by pratica, documentazione) c2
  on c.pratica = c2.pratica
  and c.documentazione = c2.documentazione
  and c.versione = c2.versione;

然后我尝试使用 JPA 存储库在我的网络应用程序上移动此查询:

@Query("select t1 from CheckList as t1 join "
        + "(select pratica, documentazione, max(versione) as versione from CheckList group by pratica, documentazione) as t2 "
        + "on t1.pratica = t2.pratica  and "
        + "t1.documentazione = t2.documentazione and "
        + "t1.versione = t2.versione")

但它不起作用,因为我知道,要创建与 JPA 存储库的连接,您必须执行以下操作:

form table1 t1 join t1.table2 t2 on etc.

但在这种情况下,我需要在同一张表上进行连接,那么我该怎么做呢?

【问题讨论】:

  • 但是您没有加入同一个表(在您的原始查询中)。您正在加入涉及该表的聚合查询的内联视图。这根本不是一回事。
  • 并且 JPQL 不会对子查询执行 JOIN,因为任何有信誉的 JPA 文档都会告诉您
  • @NeilStockton 好的,所以我的问题是:有没有办法做到这一点?还是不可能?

标签: java spring spring-mvc spring-data-jpa jpql


【解决方案1】:

我解决了添加nativeQuery = true

这是我的查询:

@Query(value = "select t1.* from macchine.check_list as t1 join "
        + "(select pratica, documentazione, max(versione) as versione from macchine.check_list group by pratica, documentazione) as t2 "
        + "on t1.pratica = t2.pratica  and "
        + "t1.documentazione = t2.documentazione and "
        + "t1.versione = t2.versione where t1.pratica = :pratica", nativeQuery = true)

要清楚这是我的桌子:

+----+----------------+---------+----------+---------+
| id | documentazione | pratica | versione | ....... |
+----+----------------+---------+----------+---------+
| 1  | 1              | 1       | 1        |         |
+----+----------------+---------+----------+---------+
| 2  | 2              | 1       | 1        |         |
+----+----------------+---------+----------+---------+
| 3  | 3              | 1       | 1        |         |
+----+----------------+---------+----------+---------+
| 4  | 1              | 1       | 2        |         |
+----+----------------+---------+----------+---------+

使用这个查询,结果是这样的:

+----+----------------+---------+----------+---------+
| id | documentazione | pratica | versione | ....... |
+----+----------------+---------+----------+---------+
| 4  | 1              | 1       | 2        |         |
+----+----------------+---------+----------+---------+
| 2  | 2              | 1       | 1        |         |
+----+----------------+---------+----------+---------+
| 3  | 3              | 1       | 1        |         |
+----+----------------+---------+----------+---------+

【讨论】:

    【解决方案2】:

    JPA 不支持 JOIN 内联视图。通过这种连接过滤结果的主要替代方法(在 JPQL 和 SQL 中)是通过 WHERE 子句中的相关子查询过滤它们:

    select t1
    from CheckList t1
    where t1.versione = (
      select max(versione)
      from CheckList t2
      where t2.pratica = t1.pratica
        and t2.documentazione = t1.documentazione
    )
    

    【讨论】:

    • 但如果我这样做,我无法提取所有行,但只有那些 versione 等于 max(versione)
    • 嗯,是的,@Teo。这也正是您的原始 SQL 查询所做的。这是JOIN那里的整个可见效果。
    • JPQL(= JPA 查询语言)是表达 JPA 查询的语言,@Teo。您可以直接在 @Query 注释中使用它。
    • 通过我的查询,我得到了表格中的所有行,如果有超过 1 行具有相同的 pratica 和 documentazione,我只得到具有最大版本的行
    • 所以不,@Teo,您的查询没有获取表中的所有行。正如您所说,它会获取所有versione 等于其 (pratica, documentazione) 值最大值的人。这与我提出的查询相同。如果您无法通过分析我的查询看到这一点,那么数据库项目可能不是目前最适合您的类型。
    【解决方案3】:

    您可以从 MySQL 中的子选择创建一个视图,然后将该视图映射到 Java 实体并在 CheckList 中添加必要的映射:

    @OneToOne
    @JoinColumns(
    {
        @JoinColumn(name="pratica"),
        @JoinColumn(name="documentazione"),
        @JoinColumn(name="versione")
    }
    private MaxCheckList maxCheckList;
    
    @Query("select t1 from CheckList as t1 join maxCheckList t2")
    

    【讨论】:

      猜你喜欢
      • 2021-04-06
      • 2013-05-04
      • 2011-12-20
      • 2012-10-20
      • 2021-02-17
      • 2021-09-13
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      相关资源
      最近更新 更多