web-dev-qa-db-ja.com

Hibernate Query by Example and Projections

短くするために: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は、this_.cityの代わりに---(y0_ =?.

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

プロジェクションエイリアスとトランスフォーマーを使用しようとしましたが、動作しません。

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

誰もが例によって投影とクエリを使用していますか?

21
Miguel Ping

ユーザークラスを表示できますか?これは、以下の制限を使用しているだけです。制限が実際に例とはまったく異なる理由がわかりません(例ではデフォルトで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]);
}

必要に応じて、そのように自分でユーザーを手動で設定できます。

問題を診断するための追加情報なしでは、問題を調査するのは困難です。

16
Arthur Thomas

この問題は、オブジェクトプロパティと同じ名前のエイリアスがある場合に発生するようです。 Hibernateはエイリアスを取得し、SQLで使用するようです。これは here および here と文書化されており、Hibernateのバグであると信じていますが、Hibernateチームが同意するかどうかはわかりません。

いずれにせよ、私は私のケースで動作する簡単な回避策を見つけました。あなたのマイレージは異なる場合があります。詳細は以下のとおりです。このサンプルのコードを簡素化して、エラーやタイプミスをおaびします。

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を生成します:

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

エラーの原因:Java.sql.SQLException:ORA-00904: "Y1_":invalid identifier

しかし、「this」を使用するように制限を変更すると、次のようになります:

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

それでおしまい!痛みを伴う問題に対する非常に簡単な修正。この修正が問題例ごとにクエリにどのように変換されるかはわかりませんが、より近くなるかもしれません。

44
Ryan Cook

ここでの実際の問題は、where-clauseでselect-listエイリアスを使用するhibernateのバグがあることです。

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

誰かが答えを求めてここに着いた場合に備えて、チケットを見てください。修正には5年かかりましたが、理論的には次のリリースの1つに含まれるので、問題はなくなると思います。

6

同様の問題に直面しています。例によるクエリを使用していますが、カスタムフィールドで結果を並べ替えます。 SQLでは、私は次のようなことをします:

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

句ごとになくても正常に機能します。私が得たのは

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:プロパティを解決できませんでした:diff例外が発生します。 thisの回避策も機能しません。

PS:HibernateでのQBEの使用に関する詳細なドキュメントを見つけることができなかったため、上記のすべては主に試行錯誤のアプローチです

0
VHristov
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
singh