質問

どうしてこんなことが可能なのか、基準に従わなければなりません

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 になりました。

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


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

役に立ちましたか?

解決

ここで何が起こっている

は休止状態でデバッグすると生成されたクエリを比較するSQLをオンにすることで、非常にはっきりと見ることができます。

かなり単純SaleItem 1対多マッピング(できれば自明である)を使用し、

、このような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のようなDISTINCT_ROOT_ENTITYはSQLが実行されたの後のSQL列の結果を処理するJavaクラスです。したがって、あなたはSQLに行制限として適用されるmaxResultsを指定した場合、 SQLを使用すると、90 のサブ要素にあなたのSQLの結果を制限しているので、Collectionの要素に参加含んの。 DISTINCT_ROOT_ENTITY変圧器が適用されると、それは要素が90の接合結果に最初に出てくることが起こるどのルートに純粋に依存し、20未満のルート要素をもたらすことができる。

それは実際にの行の制限の前に適用されるSQL DISTINCTキーワード、を使用する点で

DISTINCT HQLで、非常に動作が異なります。したがって、この振る舞いは、あなたが期待するように、と2の違いを説明します。

理論的には

あなたはSQLレベルでの投影を適用するためにsetProjectionされているはずです - c.setProjection(Projections.distinct(Projections.rootEntity()))のようなもの - 残念ながらProjections.rootEntity()は、私はちょうどそれを作った、存在しません。おそらく、それが必要!

他のヒント

はsetMaxResultsは、外での仕事は、SQLクエリに参加していません。多分これはあなたの問題がある: Hibernateは、外でのクエリのための明確な結果を返さないAのために有効に結合フェッチコレクション(私は明確なキーワードを使用している場合でも)にはます。

・ホープ、このことができヘルプ

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

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

  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;

これがお役に立てば幸いです。
ステイン

このは、Hibernateにおける既知の問題です。生成されたSQLと問題の説明については@Cowanを見てください。そのJIRAで、このためのオープンなバグ要求があります。誰かがそれに沿って修正来ることをしてみましょう希望:)

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top