NHibernate ManyToMany和eager loading:SetFetchmode的奇怪结果集与SetResultTransformer和SetMaxResult相结合

时间:2009-02-16 11:47:36

标签: nhibernate many-to-many

我有一个多对多的关系,我试图获取渴望:

*.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 个答案:

答案 0 :(得分:1)

这是因为SetMaxResults方法在“低级别”工作。 我的意思是,SetMaxResults导致NHibernate生成的SQL语句包含TOPLIMIT子句。

当然,当你使用渴望的提取模式时,这会导致那些奇怪的结果,因为急切的fetchmode导致了JOIN。

因此,如果您有两个以一对多关系连接在一起的表,那么NHibernate返回的记录集就像这样

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

如果对上述记录集执行'TOP 2',NHibernate将只能从中提取一个实体,因为结果集中的前2个记录实际上是同一个实体。

我通过使用包含TOP子句的分离子查询解决了这个问题,并检索了必须检索的实体的ID。

答案 1 :(得分:0)

我实际上没有试过这个,但它可能会奏效。

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

编辑:这不起作用。 使用multiquery,multicriteria(或使用新的NH构建时的Future)

答案 2 :(得分:0)

我有同样的问题。使用分离标准和子查询对以下内容进行修改看起来可能很有希望。当我有时间的时候,我会对它进行更彻底的试验。

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

答案 3 :(得分: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;

}