2012-04-07 7 views
2

私は「」restrictivesための変数値を設定することができるよ:HQL:変数列

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. 
    ... 

はUPDATE(使用液):

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) " 

答えて

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インジェクションなど)には、このアイデアを別のユーティリティ/エンティティベースのクラスにリファクタリングする必要があります。

+0

ありがとうございますが、 'メソッドの置き換え(String、String)はQuery型'のために定義されていません。私は誤って別の方法でドキュメントを見つけました。私は数分で私の質問を更新します。 – gaffcz

+1

私の提案したコードで述べたように、 'query'はHQLを保持する文字列です。 – nobeh

+0

Omg、それは動作し、それは私のソリューションよりもクリーンであるようです、もう一度ありがとう! – gaffcz

5

あなたは文字列の一部として列名を設定することができます。セキュリティのために、SQLを手動でエスケープすることもできますが、最後にこれを実現できます。

あなたがcommonsクラスを使用することができますSQLインジェクションを避けるために:

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); 
+0

ありがとうございます、私はそれをチェックします:-) – gaffcz