如何在 hibernate 中重用 Criteria 对象?
-
21-08-2019 - |
题
我正在尝试使用 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
对象。
解决方案
很好,DetachedCriteria之后是序列化,所以你有内置的(如不雅)深克隆支持。你可以序列化的初始标准,一个byte []一次施工,那么你要使用它,每次反序列化。
其他提示
Criteria.setProjection(null);
Criteria.setResultTransformer(Criteria.ROOT_ENTITY);
将有效“复位”的标准本身根据rowCount投影和执行之间的标准。
我会确保你的订单还没有被添加做rowCount时之前,它会慢下来。我PaginatedList的实现寻找的结果之前,一定要先运行数查询,所以排序是不是一个问题。
在那篇文章中,我发现了 CriteriaTransformer.clone 方法。
那应该复制条件对象。
您还可以在 getlist 方法上设置投影。
糟糕,我没有注意到你指的是 java hibernate。无论如何,这个 http://forum.hibernate.org/viewtopic.php?t=939039
论坛帖子应该可以回答你的问题。
丑陋因为它可能是我结束了使用序列特技。在需要的时候我只是序列化DetachedCriteria
对象上建设PaginatedList
对象和一个字节数组反序列化。哎哟。
还有一件事值得尝试:
实现一个通用的DAO如在Hibernate的网站的一个建议,并把它传递给PaginatedList对象,沿着与限制对象。然后将PaginatedList对象会做类似
Criteria.forClass(myDAO.getPersistentClass())
.add(myRestrictions)
.addOrder(<someOrder>)
和
Criteria.forClass(myDAO.getPersistentClass())
.add(myRestrictions)
.setProjection(Projections.rowCount());
有没有尝试过呢,但它应该工作。
public static DetachedCriteria Clone(this DetachedCriteria criteria)
{
var dummy = criteria.ToByteArray();
return dummy.FromByteArray<DetachedCriteria>();
}