为什么 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 会关心有两个顺序命名参数。
这不是一个大问题,因为它很容易解决(可以将 asc
或 desc
字符串值附加到 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,这可以通过使用字符串连接动态地编写查询来实现。
希望这能解决你的问题,祝你好运!
在使用 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 会关心有两个顺序命名参数。
这不是一个大问题,因为它很容易解决(可以将 asc
或 desc
字符串值附加到 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,这可以通过使用字符串连接动态地编写查询来实现。
希望这能解决你的问题,祝你好运!