4

私は熱心にフェッチしようとする多対多の関係を持っています:

*.CreateCriteria(typeof(Class1))
.SetFetchMode("Class2", FetchMode.Eager)
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.SetFirstResult(20)
.SetMaxResult(10)
.List<Class1>();

行 20 から 30 を返したいのですが、代わりに 12 から 18 を取得しています。なんで?SetResultTransformer は SetMaxResult の後に実行されるためです。行 20 から始まる 10 行を返しますが、それは区別され (それは単語ですか?)、結果として行 12 から 18 になります。何が起こっているのかは完全に理解していますが、基準を使用した解決策が思い浮かびません...

誰かがそれに対する解決策を持っていますか?

4

4 に答える 4

1

これは、SetMaxResults メソッドが「低レベル」で機能するためです。つまり、SetMaxResults により、NHibernate によって生成される SQL ステートメントにTOPorLIMIT句が含まれるようになります。

もちろん、熱心なフェッチモードを使用すると、JOIN が発生するため、これは奇妙な結果につながります。

したがって、1 対多の関係で結合された 2 つのテーブルがある場合、NHibernate によって返されるレコードセットは、たとえば次のようになります。

1 recordA-fromTable1  1 recordX-fromTable2
2 recordA-fromTable1  2 recordY-fromTable2
3 recordB-fromTable1  3 record2-fromTable2

上記のレコードセットで「TOP 2」が実行された場合、結果セットの最初の 2 つのレコードは実際には同じエンティティに対するものであるため、NHibernate はそこから 1 つのエンティティしか抽出できません。

TOP 句を含む独立したサブクエリを使用してこれを解決し、取得する必要があるエンティティの ID を取得します。

于 2011-08-31T21:13:27.043 に答える
0

私も同じ問題を抱えてる。切り離された基準とサブクエリを使用した以下の適応は、有望であるように思われます。時間があれば、もっと徹底的に試してみるつもりです。

http://blogs.taiga.nl/martijn/2008/11/20/nhibernate-criteria-queries-across-multiple-many-many-associations/

于 2009-03-06T18:21:25.270 に答える
0
 public List<Employee> getData(int to, int from,
        String searchField, String searchString, String searchOper,
        String sord, String sidx) {

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

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

        if (searchString != null && searchField != null
                && searchOper != null) {
            if (searchOper.equalsIgnoreCase("eq"))


                    hCriteria.add(Restrictions
                            .eq(searchField, searchString));


            if (searchOper.equalsIgnoreCase("ne"))
                hCriteria.add(Restrictions.ne(searchField, searchString));
            if (searchOper.equalsIgnoreCase("lt"))
                hCriteria.add(Restrictions.lt(searchField, searchString));
            if (searchOper.equalsIgnoreCase("le"))
                hCriteria.add(Restrictions.le(searchField, searchString));
            if (searchOper.equalsIgnoreCase("gt"))
                hCriteria.add(Restrictions.gt(searchField, searchString));
            if (searchOper.equalsIgnoreCase("ge"))
                hCriteria.add(Restrictions.ge(searchField, searchString));
            if (searchOper.equalsIgnoreCase("cn"))
                hCriteria.add(Restrictions.ilike(searchField, searchString,
                        MatchMode.ANYWHERE));

        }


        if (sord != null && sidx != null && !sidx.equals("")) {
            if (sord.equals("asc"))
                hCriteria.addOrder(Order.asc(sidx));
            else
                hCriteria.addOrder(Order.desc(sidx));

        }

        /*
                    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-04T06:21:05.497 に答える
0

私は実際にこれを試していませんが、うまくいくかもしれません。

  *.CreateCriteria(typeof(Class1))
    .SetFirstResult(20)
    .SetMaxResult(10)
    .CreateCriteria("Class2", JoinType.LeftOuterJoin)
    .SetResultTransformer(new DistinctRootEntityResultTransformer())
    .List<Class1>();

編集:これは機能しません。マルチクエリ、マルチ基準 (または NH の新しいビルドを使用する場合は Future) を使用する

于 2009-02-16T20:59:00.797 に答える