2

我可以为“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) "
4

2 回答 2

6

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

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

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);
于 2012-04-07T16:37:04.153 回答
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 注入)查询。

于 2012-04-07T16:38:34.743 回答