HQL:变量列

时间:2012-04-07 16:27:04

标签: java hibernate hql

我可以为“where”限制条件设置变量值:

Query criteria = session.createQuery(
  "select test.col1, test.col2, test.col3
  "from Test test " +
  "where test.col = :variableValue ");
criteria.setInteger("variableValue", 10);

但是可以像这样设置变量列吗?

String variableColumn = "test.col1";
Query criteria = session.createQuery(
  "select test.col1, test.col2, test.col3
  "from Test test " +
  "where :variableColumn = :variableValue ");
criteria.setInteger("variableValue", 10);
criteria.setString("variableColumn", variableColumn);

结果如下:

Exception in thread "main" Hibernate: select .... where ?=? ...
org.hibernate.exception.SQLGrammarException: could not execute query
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
    ...
    at _test.TestCriteria.main(TestCriteria.java:44)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting the nvarchar value 'test.col1' to data type int.
    ...

更新(工作解决方案):

Query criteria = session.createQuery(
  "select test.col1, test.col2, test.col3
  "from Test test " +
  "where (:value1 is null OR test.col1 = :value1) AND 
         (:value2 is null OR test.col2 = :value2) "

2 个答案:

答案 0 :(得分:6)

这在您的应用程序中是否有意义:

String query =  "select test.col1, test.col2, test.col3" + 
  "from Test test " +
  "where {columnName} = :variableValue ";
Object variableValue = // retrieve from somewhere
String columnName = // another retrieve from somewhere
query = query.replace("{columnName}", columName);
// Now continue as always

这通常是一个天真的查询构造函数。您可能需要将此想法重构为单独的基于实用程序/实体的类,以便在执行之前优化(例如SQL注入)查询。

答案 1 :(得分:5)

您可以将列名设置为字符串的一部分。为了安全起见,您可以手动执行SQL转义,但最后您可以实现此目的。

为避免SQL注入,您可以使用commons class:

String escapedVariableColumn = org.apache.commons.lang.StringEscapeUtils.escapeSql(variableColumn);

Query criteria = session.createQuery(
  "select test.col1, test.col2, test.col3
  "from Test test " +
  "where " + escapedVariableColumn + " = :variableValue ");
criteria.setInteger("variableValue", 10);