【问题标题】:Remove dynamically an ordering to the result set in org.hibernate.Criteria动态删除对 org.hibernate.Criteria 中结果集的排序
【发布时间】:2011-01-23 03:15:35
【问题描述】:

我有一个标准:

Criteria criteria= session.createCriteria(Libro.class).addOrder( Order.asc("ID") );

但是,当我想获取行数失败时:

criteria.setProjection(Projections.rowCount());  

因为查询中有 order by。

如何动态移除 Criteria 中的排序?

我的意思是,我正在寻找 criteria.removeOrder("ID") 之类的东西。

【问题讨论】:

  • 嗯...如果你不想要,为什么要打电话给addOrder()
  • @PascalThivent 好点。有时您可能会返回一个带有内置顺序的 Criteria 对象(例如,来自工厂方法),您可能希望删除该预定义的顺序。这就是我提出这个问题的原因。

标签: hibernate criteria


【解决方案1】:

大多数 Criteria 实际上是 CriteriaImpl 的实例。如果您将 Criteria 转换为 CriteriaImpl 并获取订单的迭代器,则可以通过这种方式删除它们。

Criteria criteria= session.createCriteria(Libro.class).addOrder( Order.asc("ID") );
Iterator<Order> orderIter = ((CriteriaImpl)criteria).iterateOrderings();
while (orderIter.hasNext()) {
    orderIter.next();
    orderIter.remove();
}

Long totalRows = (Long)criteria.setProjection(Projections.rowCount()).uniqueResult();

【讨论】:

  • 也有用于投影的迭代器吗?我有同样的问题,我想访问我的 projectionsList
【解决方案2】:

您不能从条件中删除 order by。我的分页解决方案是将 Order[] 作为参数传递给执行分页的方法。

只有当 db 是 db2 as400 或其他不允许在select count(*) 内排序的数据库时,您才需要这样做。

【讨论】:

    【解决方案3】:

    criteria.ClearOrders() 是 NHibernate 提供的删除订单的方法。

    在 Java 中没有这样的方法。我对这个问题的解决方案是使用Order 作为另一个参数与Criteria 一起传递给分页查询函数。

    【讨论】:

      【解决方案4】:

      我也遇到过同样的问题..但我通过以下方式实现了,

      在申请订单之前我查询了记录的数量,

      criteria.addOrder(pageCriteria.isSortDescending() ? Order
                                  .desc(pageCriteria.getSortBy()) : Order
                                  .asc(pageCriteria.getSortBy()));
      
      pageCriteria.setTotalRecords(((Integer) criteria
                                  .setProjection(Projections.rowCount())
                                  .uniqueResult()).intValue());
                      criteria.setProjection(null);
                      criteria.setFirstResult(
                              pageCriteria.getFirstRecordOfCurrentPage())
                              .setMaxResults(pageCriteria.getRecordsPerPage());
                      criteria
                              .setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
      

      上面的代码很适合我。

      【讨论】:

        【解决方案5】:

        如果您收到标准作为参数并使用它进行一些计算,您可以在此处使用 .Clone():

            private static int GetTotalRows(ICriteria criteria)
            {
                var countCriteria = (ICriteria)criteria.Clone();
                return Convert.ToInt32(countCriteria.SetProjection(Projections.RowCount()).UniqueResult());
            }
        

        其他解决方案是使用 ClearOrders,它将删除所有订单列表。

            private static int GetTotalRows(ICriteria criteria)
            {
                criteria.ClearOrders();
                ...
            }
        

        问候

        【讨论】:

        • criteria.ClearOrders() 是什么??
        【解决方案6】:

        听起来您正在尝试重用为获取有序列表而制定的标准来获取计数。

        与其尝试使用相同的标准来检索数据和进行计数,最好还是简单地创建独立的标准。

        使用

        Criteria orderCriteria= session.createCriteria(Libro.class)
                                       .addOrder( Order.asc("ID") );
        

        按顺序检索列表,并使用

        Criteria countCriteria= session.createCriteria(Libro.class)
                                       .setProjection(Projections.rowCount());
        

        获取计数。

        为了将相同的 Criteria 用于两个目的,您必须更改用法之间的状态。我不确定如何删除订单(或者如果您确实需要进行计数)。删除投影只需要setProjection(null)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多