分页,这是Web应用中经常要涉及的问题,相信每一位开发人员都有这个自信解决这个问题,看了不少各式各样的分页实现代码,总觉得应该有一个比较好的规范来处理分页。有没有一个比较好、规范的分页接口,这样大家都可以围绕此接口做实现,这样分页处理就统一起来,简单多,而不我们看到现象:不同公司个人的不同版本的分页实现。个人非常欣赏aopalliance项目,虽然只是一些接口的定义,但定于规范化AOP确实做出不小的贡献,不然不同的AOP实现的互通如何实现?规范的作用就发挥出来啦。
在Hibernate的站点上有一个分页的参考实现(http://www.hibernate.org/248.html),定义了分页处理所需的接口Page,这个接口非常不错,至少是我目前看到最完善和合理的(关于分页处理),将分页的信息全部包含啦,简单明了,代码如下:
JavaZoo.com © 2006. Code Language:java.
-
-
-
public
interface Page {
-
boolean isFirstPage();
-
boolean isLastPage();
-
boolean hasNextPage();
-
boolean hasPreviousPage();
-
int getLastPageNumber();
-
List
getThisPageElements
();
-
Logger getLogger();
-
int getTotalNumberOfElements();
-
int getThisPageFirstElementNumber();
-
int getThisPageLastElementNumber();
-
int getNextPageNumber();
-
int getPreviousPageNumber();
-
int getPageSize();
-
int getPageNumber();
-
}
-
-
-
-
Parsed in 0.063 seconds, using GeSHi 1.0.7.12
这里可能要做一些调整,个人觉得getLogger()没有必要放在这个接口中,它是用于处理日志的,这个可以在具体的实现代码完成,getThisPageElements()获取当前页的数据,这里返回为List类型数据,这里可能需要更改一下返回类型,当前页的数据可能涉及许多种类型:数组、RowSet、List等等,所以我们拟定将其返回值定为Object,在具体的代码中再去考虑究竟返回何种类型,所以这个接口修改后如下:
JavaZoo.com © 2006. Code Language:java.
-
-
public
interface Page {
-
boolean isFirstPage();
-
boolean isLastPage();
-
boolean hasNextPage();
-
boolean hasPreviousPage();
-
int getLastPageNumber();
-
-
int getTotalNumberOfElements();
-
int getThisPageFirstElementNumber();
-
int getThisPageLastElementNumber();
-
int getNextPageNumber();
-
int getPreviousPageNumber();
-
int getPageSize();
-
int getThisPageNumber ();
-
}
-
-
-
-
Parsed in 0.066 seconds, using GeSHi 1.0.7.12
接口定义完毕后我们需要根据实际情况实现这个接口,这里主要讲三种情况:Hibernate的Query分页、Jdbc的ResultSet分页和List数据类型分页。在Hibernate的站点上提供了一个Hibernate分页的实现类HibernatePage,这个类处理从0开始,这可能与我们的实际情况不太一样,同时可能还有一些分页处理方面的bug,让我们看看HibernatePage的一个具体实现:
JavaZoo.com © 2006. Code Language:java.
-
-
-
/**
-
* Hibernate分页信息
-
*/
-
public
class HibernatePage implements Page
-
{
-
-
private
int pageSize;
-
private
int pageNumber;
-
private
int totalElements = 0;
-
-
-
/**
-
* 构建HibernatePage对象,完成Hibernate的Query数据的分页处理
-
*
-
* @param query Hibernate的Query对象
-
* @param pageNumber 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。
-
* 如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。
-
* 这两种情况将重新更改当前页的页码,为最后一页编码。
-
* @param pageSize 每一页显示的条目数
-
*/
-
public HibernatePage(Query query, int pageNumber, int pageSize)
-
{
-
this.pageNumber = pageNumber;
-
this.pageSize = pageSize;
-
try
-
{
-
ScrollableResults scrollableResults = query.scroll();
-
//get the total elements number
-
scrollableResults.last();
-
this.totalElements = scrollableResults.getRowNumber();
-
if
(
Integer
.
MAX_VALUE ==
this.
pageNumber ||
this.
pageNumber > getLastPageNumber
())//last page
-
{
-
this.pageNumber = getLastPageNumber();
-
}
-
elements = query.setFirstResult((this.pageNumber - 1) * this.pageSize).setMaxResults(this.pageSize + 1).list();
-
}
catch
(HibernateException e)
-
{
-
-
}
-
}
-
-
-
public
boolean isFirstPage()
-
{
-
return getThisPageNumber() == 1;
-
}
-
-
-
public
boolean isLastPage()
-
{
-
return getThisPageNumber() >= getLastPageNumber();
-
}
-
-
-
public
boolean hasNextPage()
-
{
-
return getLastPageNumber() > getThisPageNumber();
-
}
-
-
-
public
boolean hasPreviousPage()
-
{
-
return getThisPageNumber() > 1;
-
}
-
-
-
public
int getLastPageNumber()
-
{
-
return totalElements % this.pageSize == 0 ? totalElements / this.pageSize : totalElements / this.pageSize + 1;
-
}
-
-
-
/**
-
* 返回List类型数据
-
*
-
* @return List数据源
-
*/
-
public
Object
getThisPageElements
()
-
{
-
return elements;
-
}
-
-
-
public
int getTotalNumberOfElements()
-
{
-
return totalElements;
-
}
-
-
-
public
int getThisPageFirstElementNumber()
-
{
-
return
(getThisPageNumber() - 1) * getPageSize() + 1;
-
}
-
-
-
public
int getThisPageLastElementNumber()
-
{
-
int fullPage = getThisPageFirstElementNumber() + getPageSize() - 1;
-
return getTotalNumberOfElements() < fullPage ? getTotalNumberOfElements() : fullPage;
-
}
-
-
-
public
int getNextPageNumber()
-
{
-
return getThisPageNumber() + 1;
-
}
-
-
-
public
int getPreviousPageNumber()
-
{
-
return getThisPageNumber() - 1;
-
}
-
-
-
public
int getPageSize()
-
{
-
return pageSize;
-
}
-
-
-
public
int getThisPageNumber()
-
{
-
return pageNumber;
-
}
-
}
-
-
-
-
Parsed in 1.548 seconds, using GeSHi 1.0.7.12
当然上述只是参考实现,你可以依据自己的分页算法进行实现,只要遵循这个接口即可。这里就不在给出List和ResultSet分页的实现逻辑,附件包含了源代码,大家可以参考一下。
总结:分页处理并不难,关键是没有一个好的接口和指导如何去实现的思想,这样造成了许多不规范,Hibernate站点上的Page接口设计的非常不错,同时给出了如何去实现的指导,相信有了一个规范接口和相关的实现逻辑,这样就分页处理就规范化多啦。
附件为分页实例的源代码!
posted on 2006-10-03 21:14
马尔代夫 阅读(161)
评论(0) 编辑 收藏 所属分类:
框架学习 、
Hibernate