HibernateクエリのUnicode文字列
-
22-07-2019 - |
質問
SQLでは、次のような人物の名前を検索するクエリを作成できます。
SELECT * FROM Person P WHERE P.Name LIKE N'%ike%'
このクエリは、ユニコード文字で実行されます(名前の列とデータベースがユニコードサポートを処理するように設定されていると仮定します)。
Hibernate(NHibernate)によって実行されるHQLに同様のクエリがあります。生成されたクエリは次のようになります。
SELECT P FROM SumTotal.TP.Models.Party.Person P join P.Demographics PD WHERE (PD.LastName LIKE '%カタカ%' )
残念ながら、HQLのリテラルの前に「N」を置くとエラーになります。文字列内のUnicode文字をエスケープしようとしましたが、まだ成功しませんでした。
データベースは、HibernateからUnicode文字を受け入れて保存しています。オブジェクトにUnicode文字列を正常に入力し、Hibernateで保存し、データベースで検証することができました。カスタムクエリでUnicode文字列を使用できないことは少し奇妙に思えます(または名前付きクエリも想定しています)。
これは、Hibernate(Nhibernate)の既知の問題または制限ですか? HQLでUnicodeをどのように使用しますか?
いくつかのサイトでは、基準クエリの使用が推奨されています。私が働いているフレームワークの制約のため、これは不可能です。
解決
パラメータを試してみました:
IList<Person> people = session
.CreateQuery("from Person p where p.Name like :name")
.SetParameter("name", "%カタカ%")
.List<Person>();
SQLインジェクションからクエリを保護する利点もあります。
他のヒント
機能する解決策を見つけました。私はそれが最善の解決策だとは非常に疑っています。しかし、私が取り組んでいるソフトウェアのクエリ作成セクション全体の書き換えを許可できるようになるまで、これは実装するソリューションです。
インスタンス内:
SELECT P FROM SumTotal.TP.Models.Party.Person P join P.Demographics PD WHERE (PD.LastName LIKE '%カタカ%')
where句には次のリテラルが含まれます:
'%カタカ%'
このリテラルは、Hibernate(Nhibernate)が無意識のうちに生成するSQLにパススルーするncharに分割できます。奇妙だが、うまくいく。したがって、前のクエリは次のように記述できます。
SELECT P FROM SumTotal.TP.Models.Party.Person P join P.Demographics PD WHERE (PD.LastName LIKE '%' + nchar(0x30AB) + nchar(0x30BF) + nchar(0x30AB)+ '%')
このソリューションは、各文字を調べてマルチバイト文字かどうかを判断する必要があるため、最適とはほど遠いものです。ただし、このコードがアプリ内に存在する場合、異なる操作の下で複数の異なる基準を処理する動的クエリジェネレーターで使用されます。私が与える例では、文字列内のどこでもユニコードを探しています。この関数は、特定の数値に等しい列のwhere句部分を返すか、文字列の開始文字を検索している可能性があります。演算子を作成するメソッドは、演算子の種類と用語を使用して文字列を返します。私はそれを書き換えることができますが、それは大きなタスクになります。上記の修正により、このメソッドに渡された文字列を処理できます。このソリューションは機能するため提供していますが、おそらくダリンの答えが私が見つけることができる最良の方法です。
NHibernateが型の長さなしで列にアクセスしようとするため、この問題が発生します。したがって、HBM.xmlでは、レガシーデータベースの長さを記載することが非常に重要です。そうしないと、UNIcode関連のもので失敗します。
ありがとう、 タニ