2008-09-17 8 views
18

これを短くするには:hibernateは、投影法や例によるクエリをサポートしていませんか?私はこの記事を見つけました:例と投影によるハイバネートクエリ

コードはこれです:他のポスターが言ったように

User usr = new User(); 
usr.setCity = 'TEST'; 
getCurrentSession().createCriteria(User.class) 
.setProjection(Projections.distinct(Projections.projectionList() 
.add(Projections.property("name"), "name") 
.add(Projections.property("city"), "city"))) 
.add(Example.create(usr)) 

、生成されたSQLが=だけy0_にクラスの参照元を持つ続けますか? this_cityの代わりに。

私はすでにいくつかのアプローチを試して、問題追跡ツールを検索しましたが、これについては何も見つかりませんでした。

私も投影エイリアスと変圧器を使用しようとしましたが、それは動作しません:

User usr = new User(); 
usr.setCity = 'TEST'; 
getCurrentSession().createCriteria(User.class) 
.setProjection(Projections.distinct(Projections.projectionList() 
.add(Projections.property("name"), "name") 
.add(Projections.property("city"), "city"))) 
.add(Example.create(usr)).setResultTransformer(Transformers.aliasToBean(User.class)); 

は、誰もが一例で投影して、クエリを使用していますか?

+0

完全に生成されたSQLは表示できますか? –

+0

同様の問題が発生したときに生成されたSQLを含むソリューションを追加しました。 –

答えて

15

Userクラスは表示できますか?これは以下の制限を使用しているだけです。なぜ制限が実際には例と異なるのかわかりません(例ではnullフィールドは無視されます)。

getCurrentSession().createCriteria(User.class) 
.setProjection(Projections.distinct(Projections.projectionList() 
.add(Projections.property("name"), "name") 
.add(Projections.property("city"), "city"))) 
.add(Restrictions.eq("city", "TEST"))) 
.setResultTransformer(Transformers.aliasToBean(User.class)) 
.list(); 

私はalaistToBeanを使用したことはありませんが、私はそれについて読んだだけです。結果をループすることもできます。

List<Object> rows = criteria.list(); 
for(Object r: rows){ 
    Object[] row = (Object[]) r; 
    Type t = ((<Type>) row[0]); 
} 

手動で手動で入力することができます。

問題を診断するための詳細情報がなくても、問題を調査するのは難しいです。

43

問題は、オブジェクトプロパティと同じ名前のエイリアスがある場合に発生すると考えられます。 HibernateはエイリアスをピックアップしてSQLで使用するようです。私はこれがherehereと書かれていることを発見しました。私はそれがHibernateのバグであると信じていますが、Hibernateチームが同意しているかどうかはわかりません。

いずれにしても、私のケースでは単純な回避策が見つかっています。あなたのマイレージは異なる場合があります。エラーの原因となった

select 
    this_.SECTION_HEADER as y1_, 
    this_.SUB_SECTION_HEADER as y2_, 
    this_.SECTION_NUMBER as y3_, 
from 
    MY_TABLE this_ 
where 
    (lower(y1_) like ?) 

Criteria criteria = session.createCriteria(MyClass.class) 
    .setProjection(Projections.projectionList() 
     .add(Projections.property("sectionHeader"), "sectionHeader") 
     .add(Projections.property("subSectionHeader"), "subSectionHeader") 
     .add(Projections.property("sectionNumber"), "sectionNumber")) 
    .add(Restrictions.ilike("sectionHeader", sectionHeaderVar)) // <- Problem! 
    .setResultTransformer(Transformers.aliasToBean(MyDTO.class)); 

はこのSQLを生成します:詳細は私が任意のエラーやタイプミスのために謝罪するように、このサンプルのコードを簡素化しようとした、以下の通りですのjava .sql.SQLException:ORA-00904: "Y1_":

:私はそうのように、 "これ" を使用するために私の制限を変更し、無効な識別子

しかし、

Criteria criteria = session.createCriteria(MyClass.class) .setProjection(Projections.projectionList() .add(Projections.property("sectionHeader"), "sectionHeader") .add(Projections.property("subSectionHeader"), "subSectionHeader") .add(Projections.property("sectionNumber"), "sectionNumber")) .add(Restrictions.ilike("this.sectionHeader", sectionHeaderVar)) // <- Problem Solved! .setResultTransformer(Transformers.aliasToBean(MyDTO.class)); 

これは次のSQLを生成し、私の問題は解決しました。

select 
    this_.SECTION_HEADER as y1_, 
    this_.SUB_SECTION_HEADER as y2_, 
    this_.SECTION_NUMBER as y3_, 
from 
    MY_TABLE this_ 
where 
    (lower(this_.SECTION_HEADER) like ?) 

Thats、it!苦しい問題に対するかなり簡単な修正。この修正プログラムがサンプルの問題によってどのようにクエリに変換されるのかわかりませんが、それはあなたを近づけるかもしれません。

+2

Paul:それが助けてくれてうれしいです。私は、この解決策が大きな問題であると思われる限り、この解答が気付かれなくなったことに驚いています。この解決策は直感的ではなく、文書化されていません。 –

+0

関連するHibernateバグはhttps://hibernate.onjira.com/browse/HHH-817であり、Hibernateのバージョン3.6.0Beta4で修正済みとマークされています。 – FGreg

+0

@RyanCookこんにちは!このソリューションは機能しますが、10個のフィルタ(つまり10個の制限)を持つことができるため、回避策があるかどうか疑問に思っていました。フィールドがnullまたは空の場合はそれぞれを確認する必要があります。 – Tarek

0

私は同様の問題に直面しています。私はQuery by Exampleを使用しており、カスタムフィールドで結果を並べ替える必要があります。 SQLでは、私は次のようなことをします:

select pageNo, abs(pageNo - 434) as diff 
from relA 
where year = 2009 
order by diff 

order-by-clauseなしでうまくいきます。私が得たことは

Criteria crit = getSession().createCriteria(Entity.class); 
crit.add(exampleObject); 
ProjectionList pl = Projections.projectionList(); 
pl.add(Projections.property("id")); 
pl.add(Projections.sqlProjection("abs(`pageNo`-"+pageNo+") as diff", new String[] {"diff"}, types)); 
crit.setProjection(pl); 

である。しかし、私は

crit.addOrder(Order.asc("diff")); 

を追加するとき、私はorg.hibernate.QueryException取得:プロパティを解決できませんでした:差分例外を。 の回避策このの回避策も機能しません。

PS:私は休止状態のためのQBEの使用上の任意の精巧なドキュメントを見つけることができなかったとして、上記のすべてのものは、主に試行錯誤のアプローチである

6

ここでの本当の問題は、休止状態にバグがあるということですどこでWHERE句で選択リストのエイリアスを使用しています。

http://opensource.atlassian.com/projects/hibernate/browse/HHH-817

は、念のために誰かがここにチケットを見に行く、答えを探して着地します。修正には5年かかりましたが、理論的には次のリリースの1つになり、問題が解決されると思われます。

-1

私は本当にそうは思わない、私が見つけることができるのは「これ」という言葉です。 hibernateにクエリの制限を含めないようにします。つまり、すべてのレコードリストを取得します。報告された休止状態のバグについて、私はそれが修正されたと報告されているのを見ることができますが、私は完全にパッチをダウンロードできませんでした。

0
ProjectionList pl = Projections.projectionList(); 
pl.add(Projections.property("id")); 
pl.add(Projections.sqlProjection("abs(`pageNo`-" + pageNo + ") as diff", new String[] {"diff"}, types), diff); ---- solution 
crit.addOrder(Order.asc("diff")); 
crit.setProjection(pl); 
+0

sqlProjectionの後にaliiasを追加します。これはOrderingで使用されます。 – singh

関連する問題