为啥 Hibernate 会为此 HQL 抛出 QuerySyntaxException?

Posted

技术标签:

【中文标题】为啥 Hibernate 会为此 HQL 抛出 QuerySyntaxException?【英文标题】:Why does Hibernate throw a QuerySyntaxException for this HQL?为什么 Hibernate 会为此 HQL 抛出 QuerySyntaxException? 【发布时间】:2015-11-10 17:01:21 【问题描述】:

在使用 Hibernate 构建查询时,我注意到一些很奇怪的事情。如果我对ORDER BY 子句使用顺序命名参数,Hibernate 会抛出一个QuerySyntaxException(冒号前缀是一个意外的标记):

createQuery("FROM MyEntity ORDER BY :orderProperty :orderDirection");

但是,如果使用纯 SQL 查询完成此操作,则创建查询时不会出现问题:

createSQLQuery("SELECT * FROM my_entity_table ORDER BY :orderProperty :orderDirection");

我知道 Hibernate 正在对 HQL 查询进行更多的字符串评估,这可能是 SQL 查询创建时没有错误的原因。我只是想知道为什么 Hibernate 会关心有两个连续的命名参数。

这不是一个大问题,因为它很容易解决(只需将 ascdesc 字符串值附加到 HQL,而不是为其使用命名参数),但我很好奇为什么Hibernate 正在阻止它(可能仅仅是因为 99% 的时间顺序命名参数像这样导致无效的 SQL/HQL)。

【问题讨论】:

***.com/questions/17510034/… 【参考方案1】:

我一直在本地对此进行测试,但使用 HQL 无法获得您想要的结果。

这是我链接的帖子的引用:

您不能将列名绑定为参数。只有一个列值。在计算执行计划、绑定参数值和执行查询之前,必须知道该名称。如果您真的想要这样的动态查询,请使用 Criteria API 或其他动态创建查询的方式。

Criteria API 看起来对您来说是更有用的工具。

这是一个例子:

    Criteria criteria = session.createCriteria(MyEntity.class);

    if (orderDirection.equals("desc")) 
        criteria.addOrder(Order.desc(orderProperty));
    
    else 
        criteria.addOrder(Order.asc(orderProperty));
    

【讨论】:

我认为这不会起作用,因为:orderDirection 不是列,它是修改列排序方向的升序/降序字符串值。您的建议会导致 ORDER BY columnName, asc 导致错误,因为 ASC(同样是 DESC)不是列名。 啊,我以为 orderDirection 是一个专栏,那么让我修改一下我的答案。 是的,Criteria 可能效果最好。这是一个简单的转换,让我对它不喜欢的东西有点失望。但我认为你是对的,使用列名作为命名参数是一个问题。即使没有 :orderDirection 参数,它也会失败(查询构建,但生成的实际 SQL 不正确)。感谢您的意见!【参考方案2】:

根据this问题接受的答案,只能在WHERE和HAVING子句中定义参数。

同样的答案也为您提供了一些解决问题的方法,但是我将添加另一种方法:

在您的 ORDER BY 中使用 CASE - WHEN 子句,这将通过以下方式起作用:

SELECT u FROM User u
ORDER BY 
CASE WHEN '**someinputhere**' = :orderProperty 
AND '**someotherinput**' = :orderDirection 
THEN yourColumn asc 
ELSE yourColumn desc END

请注意,在这种方法中,您需要编写所有可能的订购输入。不是很漂亮但很有用,尤其是因为您不需要编写具有不同顺序的多个查询,而且通过这种方法,您可以使用 NamedQueries,这可以通过使用字符串连接以动态方式编写查询来实现。

希望这能解决你的问题,祝你好运!

【讨论】:

以上是关于为啥 Hibernate 会为此 HQL 抛出 QuerySyntaxException?的主要内容,如果未能解决你的问题,请参考以下文章

为啥得到 org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join!加入 3 个表时

hibernate之HQL查询

Hibernate之HQL基本用法

Hibernate 抛出奇怪的错误:类未映射

HQL查询会使用Hibernate二级缓存吗

Hibernate(十四):HQL查询