JPQL 的 INNER JOIN 问题(即使 SQL 请求正在运行)

Posted

技术标签:

【中文标题】JPQL 的 INNER JOIN 问题(即使 SQL 请求正在运行)【英文标题】:INNER JOIN issue with JPQL (even if the SQL request is working) 【发布时间】:2018-12-05 03:25:01 【问题描述】:

“bonjour à tous”(大家好)

我来自这个线程: How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?

这个人正在做我项目中需要的几乎所有事情。 事实上,我正在尝试做一些类似 Git 的事情:检索上一个版本中的所有实例。 目前,我有一个表“UM”,具有这些属性:

int id(主键,自动生成) 字符串名称(可重复) int 版本(1、2、3、[...]) 字符串 fmr [其他属性,本例未使用]

我在 SQL 中也有这个请求(运行良好并检索到想要的结果):

SELECT * FROM agrid.um AS u INNER JOIN
        (SELECT u2.name, max(u2.version) AS MaxVersion, u2.fmr
         FROM agrid.um AS u2 WHERE u2.fmr = 'CZ2ABVIMG0000' GROUP BY u2.name, u2.fmr) umVersion
         ON u.name = umVersion.name AND u.version = umVersion.MaxVersion
         WHERE u.fmr = 'ABCDE';

但是当我尝试在 JPQL 中做同样的事情时,我遇到了一些“JOIN”错误:

TypedQuery<UmEty> q = getManager().getEntityManager().createQuery(
            "SELECT u FROM UmEty u INNER JOIN"
            + " (SELECT u2.name, max(u2.version) AS MaxVersion, u2.fmr "
            + " FROM UmEty u2 WHERE u2.fmr = :fmr GROUP BY u2.name, u2.fmr) umVersion"
            + " ON u.name = umVersion.name AND u.version = umVersion.MaxVersion WHERE u.fmr = :fmr", UmEty.class);
    q.setParameter("fmr", fmr);
    return q.getResultList();

以下例外:

Exception Description: Syntax error parsing
[SELECT u FROM UmEty u INNER JOIN (SELECT u2.name, max(u2.version)
AS MaxVersion, u2.fmr 
FROM UmEty u2 WHERE u2.fmr = :fmr GROUP BY u2.name, u2.fmr) umVersion
ON u.name = umVersion.name
AND u.version = umVersion.MaxVersion WHERE u.fmr = :fmr].
[33, 147] The join association path is not a valid expression.

我也尝试过简单地使用“JOIN”而不是“INNER JOIN”,以及其他一些测试(删除“WHERE”子句,...),但我总是抛出这个异常。 我对 JPQL 不是很熟悉,而且我已经阅读过 Objectdb 上的“INNER JOIN”主题(==> https://www.objectdb.com/java/jpa/query/jpql/from)。但即使有这些信息,我也无法成功请求

谁能告诉我为什么我的 SQL 请求翻译成 JPQL 不能正常工作?

提前致谢:)

【问题讨论】:

不是问题,就像这个问题,之前问过 问题是:如何将此 SQL 请求转换为 JPQL 请求?为什么我有“加入”问题? 检查JPA: JOIN in JPQL 感谢您的帮助。但我已经尝试只使用“JOIN”和 ObjectDB 页面中列出的所有内容。但仍然没有工作:/ SQL 比 JPQL 强大得多 - 只有很小的 SQL 语言子集可以直接转换为像 JPQL 这样的混淆层。 【参考方案1】:

要在 JPQL 中进行连接,您的对象图中必须直接依赖于要连接的实体。

这个例子来自规范本身:

SELECT c FROM Customer c JOIN c.orders o WHERE c.status = 1

其中Customer 是通过customer.orders 列表对象与Order 实体建立关系的实体。

您可以在Java Persistence Spec 的第 4.4.5 章中阅读有关联接的更多信息

编辑:

您可能希望重写查询以符合以下格式:

select * from agrid.um u where u.fmr = 'ABCDE' and not exists (select * from agrid.um u2 where u.name = u2.name and u.version < u2.version) ;

【讨论】:

好的,我明白了,但这不是我的“情况”。我只想在同一张表上工作,并通过预先选择的表(第二个 SELECT 子句)进行 JOIN。有可能吗? afaik 如果没有在实体模型中声明的显式关系,您将无法执行该查询。但是您可以翻译您的查询以使用 EXISTS 条件。 好吧,对不起,如果我错了,但是使用 jpql,您不能创建子选择查询(使用 where 和 having 子句除外) 嗨。有人已经对我说过了,但我已经在另一个(更简单的)案例中做到了。所以这不是这里的问题:/ 我已经编辑了我的答案,以使我对使用 EXISTS 的评论更加清晰。如果您想要的只是该表中条目的最大版本。

以上是关于JPQL 的 INNER JOIN 问题(即使 SQL 请求正在运行)的主要内容,如果未能解决你的问题,请参考以下文章