为什么 Hibernate 会为此 HQL 抛出 QuerySyntaxException?

Why does Hibernate throw a QuerySyntaxException for this HQL?

在使用 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)。

我一直在我的本地测试这个,但我无法得到你想要的结果来使用 HQL。

这是我链接的 post 的引用:

You can't bind a column name as a parameter. Only a column value. This name has to be known when the execution plan is computed, before binding parameter values and executing the query. If you really want to have such a dynamic query, use the Criteria API, or some other way of dynamically creating a query.

条件 API 看起来是对您的目的更有用的工具。

这是一个例子:

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

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

根据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,这可以通过使用字符串连接动态地编写查询来实现。

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