2008-12-15 102 views
26

我试图做的查询结果分页与Hibernate和displaytag和Hibernate DetachedCriteria对象正在尽最大努力在路上的绊脚石。让我来解释......如何在Hibernate中重用Criteria对象?

做分页用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的实施标准的对象,让它沿着theese线工作...

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()通话修改的标准对象呈现它,我n可用于连续呼叫。我并不完全确定这些调用的顺序,但db在尝试执行“select count(*) ... order by ...”的getFullListSize()时会抛出一个错误,这显然是错误的。

我觉得我可以创造我自己的目的是跟踪的查询条件和重建对象的标准为每个呼叫解决这个问题,但感觉就像重新发明另一个轮子。有没有更聪明的方法,可能会复制最初传入并处理该副本的标准?

更新: 看起来getList首先调用,getFullListSize之后多次调用,所以,只要有传入的排序,getFullListSize将失败。它将使意义击中分贝只有一次(在getList我说)和缓存结果,而无需复制/重置Criteria对象,但仍...

更新(再次): 忘记的是,一旦我已经做了我count不能做select,反之亦然。我真的需要两个截然不同的对象。

回答

2

好,DetachedCriteria之后是序列化,所以你有内置的(如不雅)深克隆支持。您可以在构建时将初始条件序列化为byte [],然后在每次使用时将其反序列化。

+0

发现对hibernate论坛的建议,但我宁愿不:-) – agnul 2008-12-16 09:05:37

1

丑陋,因为它可能是我结束了使用序列化技巧。我只是将DetachedCriteria对象序列化到构造PaginatedList对象的字节数组,并在需要时对其进行反序列化。哎哟。

0

另一件事值得尝试:

实现一个通用的DAO像the one suggested on hibernate's site,并把它传递给PaginatedList对象,以限制对象一起。然后PaginatedList对象会做类似

Criteria.forClass(myDAO.getPersistentClass()) 
     .add(myRestrictions) 
     .addOrder(<someOrder>) 

Criteria.forClass(myDAO.getPersistentClass()) 
     .add(myRestrictions) 
     .setProjection(Projections.rowCount()); 

还没有尝试过呢,但它应该工作。

44
Criteria.setProjection(null); 
Criteria.setResultTransformer(Criteria.ROOT_ENTITY); 

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

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

+5

建议这是正确的答案 - 比深克隆更优雅。 – 2012-03-21 13:48:03

-1
public static DetachedCriteria Clone(this DetachedCriteria criteria) 
{ 
    var dummy = criteria.ToByteArray(); 
    return dummy.FromByteArray<DetachedCriteria>(); 
} 
相关问题