如何在休眠状态下重用 Criteria 对象?

我正在尝试使用休眠和显示标记进行查询结果分页,而Hibernate对象正在尽最大努力阻止。让我解释一下...DetachedCriteria

使用 displaytag 进行分页的最简单方法似乎是实现具有以下方法的接口:PaginatedList

/* Gets the total number of results. */
int getFullListSize();

/* Gets the current page of results. */
List getList();

/* Gets the page size. */
int getObjectsPerPage();

/* Gets the current page number. */
int getPageNumber();

/* Get the sorting column and direction */
String getSortCriterion();
SortOrderEnum getSortDirection();

我正在考虑将我的PaginatedList实现扔给一个Standial对象,让它沿着这些路线工作......

getFullListSize() {
    criteria.setProjection(Projections.rowCount());
    return ((Long) criteria.uniqueResult()).intValue();
}

getList() {
    if (getSortDirection() == SortOrderEnum.ASCENDING) {
        criteria.addOrder(Order.asc(getSortCriterion());
    } else if (getSortDirection() == SortOrderEnum.DECENDING) {
        criteria.addOrder(Order.desc(getSortCriterion());
    }
    return criteria.list((getPageNumber() - 1) * getObjectsPerPage(),
                         getObjectsPerPage());
}

但这不起作用,因为 调用 或 调用 会 修改 criteria 对象,使其在连续调用中不可用。我不完全确定调用的顺序,但是db在尝试执行“”时会引发错误,这显然是错误的。addOrder()setProjection()getFullListSize()select count(*) ... order by ...

我认为我可以通过创建自己的对象来跟踪查询条件并为每个调用重新生成 Criteria 对象来解决此问题,但这感觉就像重新发明了另一个轮子。有没有更聪明的方法,可能复制最初传入的标准并处理该副本?

更新:它看起来像是先被调用,之后被调用多次,因此,一旦传递了排序,就会失败。只命中数据库一次(我会说)并缓存结果是有意义的,无需复制/重置对象,但仍然...getListgetFullListSizegetFullListSizegetListCriteria

更新(再次):忘记这一点,一旦我完成了我不能做,反之亦然。我真的需要两个不同的对象。countselectCriteria


答案 1
Criteria.setProjection(null);
Criteria.setResultTransformer(Criteria.ROOT_ENTITY);

将有效地“重置”rowCount 投影和条件本身的执行之间的条件。

我会在做rowCount之前确保没有添加你的订单,这会减慢速度。我的 PaginatedList 实现始终在查找结果之前运行计数查询,因此排序不是问题。


答案 2

好吧,DetachedCriteria是可序列化的,所以你有内置的(如果不雅的)深度克隆支持。您可以在构造时将初始条件序列化为byte[]一次,然后在每次要使用它时对其进行反序列化。