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

问题描述 投票:28回答:7

我正在尝试使用hibernate和displaytag进行查询结果分页,并且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实现扔给Criteria对象,并使其沿着主题行...

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

但是这不起作用,因为addOrder()setProjection()调用会修改条件对象,使其无法在后续调用中使用。我不能完全确定调用的顺序,但是数据库在尝试执行“ getFullListSize()”时会在select count(*) ... order by ...上引发错误,这显然是错误的。

我想我可以通过创建自己的对象来跟踪查询条件并为每个调用重建Criteria对象来解决此问题,但这就像在重新发明另一个轮子。有没有更聪明的方法,可以复制最初传入的条件并对其进行处理?

更新:好像先调用getList,然后再调用getFullListSize多次,因此,一旦传递了顺序,getFullListSize就会失败。仅一次命中数据库(在我要说的getList中)并缓存结果是有意义的,无需复制/重置Criteria对象,但是仍然...

再次更新(再次):忘记了这一点,一旦完成count,就无法执行select,反之亦然。我确实需要两个不同的Criteria对象。

java hibernate spring-mvc pagination displaytag
7个回答
2
投票

嗯,DetachedCriteria是可序列化的,因此您具有内置的(如果不好的话)深度克隆支持。您可以在构造后将初始条件序列化为byte [],然后在每次使用它时将其反序列化。


49
投票
Criteria.setProjection(null);
Criteria.setResultTransformer(Criteria.ROOT_ENTITY);

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

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


2
投票

http://weblogs.asp.net/stefansedich/archive/2008/10/03/paging-with-nhibernate-using-a-custom-extension-method-to-make-it-easier.aspx

在那篇文章中,我发现了CriteriaTransformer.clone方法。

应该复制条件对象。

您还可以在getlist方法上设置投影。

糟糕,我没有注意到您指的是Java休眠。无论如何,此http://forum.hibernate.org/viewtopic.php?t=939039

论坛帖子应该能够回答您的问题。


1
投票

可能很糟糕,我最终使用了序列化技巧。我只是在构造DetachedCriteria对象时将PaginatedList对象序列化为字节数组,并在需要时对其进行反序列化。哎呀。


0
投票

另一件事值得尝试:


0
投票

有一种更好,更简单的克隆条件的方法,简单来说就是:


-1
投票
public static DetachedCriteria Clone(this DetachedCriteria criteria)
{
   var dummy = criteria.ToByteArray();
   return dummy.FromByteArray<DetachedCriteria>();
}
© www.soinside.com 2019 - 2024. All rights reserved.