15

これはどのように可能ですか、次の基準に従う必要があります

Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();

リストのサイズは 20 になりました。条件に最大結果を追加すると、

Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.setMaxResults(90);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();

.. これでリストのサイズは 18 になりました!

行の量が定義された最大値よりも小さいため、最大結果を定義した後に結果セットのサイズを小さくする方法がわかりません。これは確かにバグのように思えますか、それとも私が気付いていない休止状態のいくつかの奇妙な側面がありますか?


この質問に対する回答を探している場合は、受け入れられた回答とそのコメントを必ず読んでください。

4

5 に答える 5

9

ここで何が起こっているかは、HibernateでSQLデバッグをオンにし、生成されたクエリを比較することで非常に明確に確認できます。

かなり単純なSaleItem1対多のマッピング(うまくいけば自明です)を使用して、次のCriteriaようなベースのクエリ:

Criteria c = sessionFactory.getCurrentSession().createCriteria(Sale.class);
c.createAlias("items", "i");
c.add(Restrictions.eq("i.name", "doll"));
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.setMaxResults(2);

次のようなSQLを生成します。

select top ? this_.saleId as saleId1_1_, ... 
from Sale this_ 
inner join Sale_Item items3_ on this_.saleId=items3_.Sale_saleId 
inner join Item items1_ on items3_.items_id=items1_.id 
where items1_.name=?

一方、Queryこのような:

Query q = sessionFactory.getCurrentSession().createQuery("select distinct s from Sale s join s.items as i where i.name=:name");
q.setParameter("name", "doll");
q.setMaxResults(2);

次のようなものを生成します:

select top ? distinct hibernated0_.saleId as saleId1_ 
from Sale hibernated0_ 
inner join Sale_Item items1_ on hibernated0_.saleId=items1_.Sale_saleId 
inner join Item hibernated2_ on items1_.items_id=hibernated2_.id 
where hibernated2_.name=?

最初の行(DISTINCT)の違いに注意してください。ResultTransformer同様に、SQLが実行されたにSQL行の結果を処理するDISTINCT_ROOT_ENTITYJavaクラスがあります。したがって、を指定すると、SQLの行制限として適用されます。SQLには、の要素への結合が含まれているため、SQLの結果を90個のサブ要素に制限しています。トランスフォーマーが適用されると、ルート要素が20未満になる可能性があります。これは、90の結合された結果で最初に出てくるルート要素に完全に依存します。maxResultsCollectionDISTINCT_ROOT_ENTITY

DISTINCTHQLでは、行制限のDISTINCTに適用されるSQLキーワードを実際に使用するという点で、動作が大きく異なります。したがって、これは期待どおりに動作し、2つの違いを説明します。

理論的にはsetProjection、SQLレベルでプロジェクションを適用することを検討する必要があります-のようなものc.setProjection(Projections.distinct(Projections.rootEntity()))-しかし、残念ながらProjections.rootEntity()存在しないので、私はそれを作り上げました。おそらくそれはすべきです!

于 2010-02-02T23:14:50.987 に答える
2

setMaxResultsは、外部結合SQLクエリでは機能しません。おそらくこれがあなたの問題です:Hibernateは、コレクションに対して外部結合フェッチが有効になっているクエリに対して個別の結果を返しません(個別のキーワードを使用している場合でも)?

于 2010-02-02T11:57:52.713 に答える
1

これが助けになることを願っています

public List<Employee> getData(int to, int from) {

    Criteria hCriteria = null;
    List<Employee> viewDataList = null;
    List<Employee> exactDataList = null;
    try {

        hSession = HibernateSessionFactory.getSession();
        hTransaction = hSession.beginTransaction();
        hCriteria = hSession.createCriteria(Employee.class);

        /*
        hCriteria.setFirstResult(to);
        hCriteria.setFirstResult(from);
        */
        hCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        viewDataList = hCriteria.list();

        // for limit
        exactDataList=viewDataList.subList(from,to);

        hTransaction.commit();
    } catch (Exception e) {
        hTransaction.rollback();

    } finally {
        try {
            hSession.flush();
            HibernateSessionFactory.closeSession();
        } catch (Exception hExp) {
        }

}

    return exactDataList;
}
于 2012-07-04T07:10:15.083 に答える
1

別の解決策は次のとおりです。

  1. エイリアスを設定せずに実行しますcriteria.list()=>ルートエンティティの参照セット/リストはプロキシで満たされます=>ここで最大結果などを正しく設定します
  2. 同じ休止状態セッションでエイリアス基準を単独で実行します => 上記のプロキシが初期化されます

このようなもの:

Criteria criteria = this.getSession().createCriteria(User.class);
criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
criteria.setMaxResults(10);

// First get the results without joining with the other tables
List<User> results = criteria.list();

// at this point the set roles is filled with proxies
// we'll now create and execute the join so these proxies are filled since we're still in the same session
getSession().createCriteria(User.class, "u")
        .createAlias("u.roles", "r", CriteriaSpecification.LEFT_JOIN)
        .list();

return results;

これが役に立てば幸いです、
Stijn

于 2010-11-29T16:22:25.520 に答える
0

これは休止状態の既知の問題です。生成された SQL と問題の説明については、@Cowan を参照してください。彼らのジラには、これに対する未解決のバグ リクエストがあります。誰かが来て修正してくれることを願いましょう:)

https://hibernate.atlassian.net/browse/HB-520

于 2013-11-06T16:28:33.707 に答える