I'm trying to do pagination of query results in a webapp built with hibernate, spring and displaytag. Using displaytag the simplest way to do pagination seems to be implementing the
PaginatedList interface, which has, among others, these metods
Code:
/* 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();
That means I should do both a
count and a
select query, but I'd rather not use two distinct queries, or building the necessary HQL with string operations. To me the
Criteria API seems a perfect fit, I'd just pass a
Criteria to my
PaginatedList implementation and do something like
Code:
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());
}
My problem is that when rendering the page displaytag will call
getList first, and
getFullListSize after, and as soon as I have an ordering set on the
Criteria the subsequent call to
getFullListSize will fail because the SQL will look like
select count(*) ... order by something which is obviously wrong. Doing things the other way round (counting and caching the result, and then doing the select) doesn't seem to work either.
I think I need a way to reset my
Criteria object or to work on a different copy for the count and select queries, but I haven't found a way to do neither. Searching in the forums it looks like the only workaround is to serialize a
DetachedCriteria instance to a byte array and deserialize a new copy each time (done, works nicely but I wouldn't call that world class programming ;-)).
Am I missing something obvious? How do you do pagination around here? :-)