分享一个spring+hibernate的通用分页类

Posted on 2007-11-13 10:50 flustar 阅读(5346) 评论(6)  编辑  收藏 所属分类: Spring
    时间过得真快,已经半年没有更新自己的博客了。    好了,言归正传。大家都知道网上广为流传的一个分页类是:PaginationSupport.java其源代码如下:
    

public class PaginationSupport{

 public final static int PAGESIZE = 30;

 private int pageSize = PAGESIZE;

 private List items;

 private int totalCount;

 private int[] indexes = new int[0];

 private int startIndex = 0;

 public PaginationSupport(List items, int totalCount) {
  setPageSize(PAGESIZE);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(0);
 }

 public PaginationSupport(List items, int totalCount, int startIndex) {
  setPageSize(PAGESIZE);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(startIndex);
 }

 public PaginationSupport(List items, int totalCount, int pageSize,
   int startIndex) {
  setPageSize(pageSize);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(startIndex);
 }

 public List getItems() {
  return items;
 }

 public void setItems(List items) {
  this.items = items;
 }

 public int getPageSize() {
  return pageSize;
 }

 public void setPageSize(int pageSize) {
  this.pageSize = pageSize;
 }

 public int getTotalCount() {
  return totalCount;
 }

 public void setTotalCount(int totalCount) {
  if (totalCount > 0) {
   this.totalCount = totalCount;
   int count = totalCount / pageSize;
   if (totalCount % pageSize > 0)
    count++;
   indexes = new int[count];
   for (int i = 0; i < count; i++) {
    indexes[i] = pageSize * i;
   }
  } else {
   this.totalCount = 0;
  }
 }

 public int[] getIndexes() {
  return indexes;
 }

 public void setIndexes(int[] indexes) {
  this.indexes = indexes;
 }

 public int getStartIndex() {
  return startIndex;
 }

 public void setStartIndex(int startIndex) {
  if (totalCount <= 0)
   this.startIndex = 0;
  else if (startIndex >= totalCount)
   this.startIndex = indexes[indexes.length - 1];
  else if (startIndex < 0)
   this.startIndex = 0;
  else {
   this.startIndex = indexes[startIndex / pageSize];
  }
 }

 public int getNextIndex() {
  int nextIndex = getStartIndex() + pageSize;
  if (nextIndex >= totalCount)
   return getStartIndex();
  else
   return nextIndex;
 }

 public int getPreviousIndex() {
  int previousIndex = getStartIndex() - pageSize;
  if (previousIndex < 0)
   return 0;
  else
   return previousIndex;
 }

 public int getPageCount() {
  int count = totalCount / pageSize;
  if (totalCount % pageSize > 0)
   count++;
  return count;
 }

 public int getCurentPageNum() {
  return getStartIndex() / pageSize + 1;
 }

}
在这个分页类中设定了每页要显示的记录数以及开始索引,如果用普通的jsp来取这个分页类的数据还可以,但是使用spring+hibernate这种架构就显得比较麻烦(原因是spring MVC返回的是一个 PaginationSupport的对象,使用jstl作为前端显示的话,会在jsp页面中掺杂大量的计算,像下一页索引,共多少条记录,当前第几页,共多少页等等会使jsp很难维护)下面是对这个类的改进:

public class  PaginationSupport {
 public final static int PAGESIZE = 30;

 private int pageSize = PAGESIZE;
 
 private int totalCount;

 private int currentPage;

 private int startIndex;
 
 private int[] indexes = new int[0];
 
 private int nextIndex;

 private int previousIndex;

 private int pageCount;

 private List items;
 
 private int lastIndex;
 
 public  PaginationSupport(int pageSize,
   int startIndex) {
  setPageSize(pageSize);
  setStartIndex(startIndex);
  
 }

 public  PaginationSupport(List items, int totalCount) {
  setPageSize(PAGESIZE);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(0);
 
 }

 public  PaginationSupport(List items, int totalCount, int startIndex) {
  setPageSize(PAGESIZE);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(startIndex);
  
 }

 public  PaginationSupport(List items, int totalCount, int pageSize,
   int startIndex) {
  setPageSize(pageSize);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(startIndex);
  
 }

 
 public void setTotalCount(int totalCount) {
  if (totalCount > 0) {
   this.totalCount = totalCount;
   int count = totalCount / pageSize;
   if (totalCount % pageSize > 0)
    count++;
   indexes = new int[count];
   for (int i = 0; i < count; i++) {
    indexes[i] = pageSize * i;
   }
    } else {
   this.totalCount = 0;
  }
 }
 public int getTotalCount() {
  return totalCount;
 }
 public void setIndexes(int[] indexes) {
  this.indexes = indexes;
 }
 public int[] getIndexes() {
  return indexes;
 }

 
 public void setStartIndex(int startIndex) {
  if (totalCount <= 0)
   this.startIndex = 0;
  else if (startIndex >= totalCount)
   this.startIndex = indexes[indexes.length - 1];
  else if (startIndex < 0)
   this.startIndex = 0;
  else {
   this.startIndex = indexes[startIndex / pageSize];
  }
   }
 public int getStartIndex() {
  return startIndex;
 }

 
 public void setNextIndex(int nextIndex) {
  this.nextIndex = nextIndex;
 }
 public int getNextIndex() {
  int nextIndex = getStartIndex() + pageSize;
  if (nextIndex >= totalCount)
   return getStartIndex();
  else
   return nextIndex;
 }
 public void setPreviousIndex(int previousIndex) {
  this.previousIndex = previousIndex;
 }
 
 public int getPreviousIndex() {
  int previousIndex = getStartIndex() - pageSize;
  if (previousIndex < 0)
   return 0;
  else
   return previousIndex;
 }
 public void setPageCount(int pageCount) {
  this.pageCount = pageCount;
 }
 public int getPageCount() {
  int count = totalCount / pageSize;
  if (totalCount % pageSize > 0)
   count++;
  return count;
 }
 

 public int getCurrentPage() {
  return getStartIndex() / pageSize + 1;
 }

 public void setCurrentPage(int currentPage) {
  this.currentPage = currentPage;
 }

 public void setLastIndex(int lastIndex) {
  this.lastIndex =lastIndex ;
 }
 public int getLastIndex() {
  return indexes[indexes.length-1];
 }

 
 public int getPageSize() {
  return pageSize;
 }

 public void setPageSize(int pageSize) {
  this.pageSize = pageSize;
 }

 

 public List getItems() {
  return items;
 }

 public void setItems(List items) {
  this.items = items;
 }


}
以上是分页的封装类,下面是支持分页查询的方法:
1)
public PaginationSupport findPageByCriteria(
   final DetachedCriteria detachedCriteria, final int pageSize,
   final int startIndex) {
  return (PaginationSupport) getHibernateTemplate().execute(
    new HibernateCallback() {
     public Object doInHibernate(Session session)
       throws HibernateException {
      Criteria criteria = detachedCriteria
        .getExecutableCriteria(session);
      int totalCount = ((Integer) criteria.setProjection(
        Projections.rowCount()).uniqueResult())
        .intValue();
      criteria.setProjection(null);
      List items = criteria.setFirstResult(startIndex)
        .setMaxResults(pageSize).list();
      PaginationSupport ps = new PaginationSupport(items,
        totalCount, pageSize, startIndex);
      return ps;
     }
    }, true);
 }
2)
public  PaginationSupport findPageByQuery( final  String hsql,  final int pageSize,final int startIndex){
     return (PaginationSupport)getHibernateTemplate().execute(
     new  HibernateCallback() {
       public  Object doInHibernate(Session session)  throws  HibernateException, SQLException {
             Query query  =  session.createQuery(hsql);
             int totalCount=query.list().size();
             query.setFirstResult(startIndex);
             query.setMaxResults(pageSize);
             List items  = query.list();
          PaginationSupport ps = new PaginationSupport(items,
       totalCount, pageSize, startIndex);
          return ps;
            
             }
       },true);
  }
你也许会问分页查询为什么会提供两个方法,这两个方法有区别吗?其实这两个方法并无本质区别,DetachedCriteria 也是构造查询语句的与Query功能一致,但是它提供了更加面向对象的方法来写hsql语句。一般人们都倾向第一种方法,但是这种方法并不通用,它有一种查询并不支持,那就是当你要查询的对象并不是一个单一对象的话(例如 你在数据库中有两个表,一个是user,另一个是userinfo,这两个表所对应的对象在hiberante中被指定为共享主键的话,在执行查询的时候就会报类型转换异常,原因是查询出来的对象并不是user而是一个包含user 和userinfo的Object,你若强制把它转换成user类型,肯定会出错),这时你不得不采用第二个方法。当然这只是我个人见解,也许还有地方说的不是很准确,希望大家多多批评指正。
最后是这个分页类的前台显示源代码:
<%@ page language="java" contentType="text/html; charset=gbk"
    pageEncoding="GBK"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <link type="text/css" rel="stylesheet" href="../css/panel.css">
    <title>显示所有用户</title>
  </head>
 
  <body>
    <div style="margin:20px auto 30px; width:70%;"><a href="index.jsp" class="btn2">返回首页</a></div>
    <div style="margin:10px auto 0; width:70%;">
    <table width="100%" border="0" cellpadding="0" cellspacing="0">
    <caption>
      显示所有用户
    </caption>
    <tr>
      <td>用户ID</td>
      <td>用户名</td>
   <td>用户昵称</td>
      <td>电子邮件</td>
      <td>注册时间</td>
      <td>详细信息</td>
      <td>用户充值记录</td>
      <td>用户定制服务信息</td>
    </tr>
<c:forEach var="user" items="${userPage.items}">
 <tr>
   <td>${user.intId}</td>
      <td>${user.username}</td>
      <td>${user.name}</td>
      <td>${user.email}</td>
      <td><fmt:formatDate value='${user.creationTime}' pattern='yyyy-MM-dd HH:mm' /></td>
   <td><a href="user_getdetailUser.ado?userId=${user.intId}" class="btn">详细信息</a></td>
   <td><a href="orderService_getUserAccountAdds.ado?userId=${user.intId}" class="btn">用户充值记录</a></td>
   <td><a href="orderService_getUserChargeItems.ado?userId=${user.intId}" class="btn">用户定制服务信息</a></td>
 </tr>
</c:forEach>
  </table>
   <c:if test="${!empty userPage}">
     共${userPage.totalCount}记录
     <c:choose>
      <c:when test="${userPage.startIndex ne '0'}">
       <a href="user_getPage.ado?startIndex=0">首页</a>
      </c:when>
      <c:otherwise>
       首页
      </c:otherwise>
     </c:choose>
     <c:choose>
      <c:when test="${userPage.previousIndex lt userPage.startIndex}">
       <a href="user_getPage.ado?startIndex=${userPage.previousIndex }">上一页</a>
      </c:when>
      <c:otherwise>
       上一页
      </c:otherwise>
     </c:choose>
     <c:choose>
      <c:when test="${userPage.nextIndex>userPage.startIndex}">
       <a href="user_getPage.ado?startIndex=${userPage.nextIndex}">下一页</a>
      </c:when>
      <c:otherwise>
       下一页
      </c:otherwise>
     </c:choose>
     <c:choose>
      <c:when test="${userPage.lastIndex eq userPage.startIndex}">
       最后一页
      </c:when>
      <c:otherwise>
       <a href="user_getPage.ado?startIndex=${userPage.lastIndex}">最后一页</a>
      </c:otherwise>
     </c:choose>
     每页显示${userPage.pageSize}条记录
     当前第${userPage.currentPage }/${userPage.pageCount}页
  </c:if>
    </div>
  </body>
</html>


Feedback

# re: 分享一个spring+hibernate的通用分页类  回复  更多评论   

2007-11-13 19:01 by 千里冰封
呵呵,有点意思

# re: 分享一个spring+hibernate的通用分页类  回复  更多评论   

2007-11-13 19:51 by addday
springside 里,早就有了

# re: 分享一个spring+hibernate的通用分页类  回复  更多评论   

2008-03-18 11:26 by huangcq
烦请楼主发一个包括所有源码的压缩包过来

# re: 分享一个spring+hibernate的通用分页类  回复  更多评论   

2008-03-18 16:42 by flustar
@huangcq
不好意思 源码都没了 电脑重装 不小心给抹去了

# re: 分享一个spring+hibernate的通用分页类  回复  更多评论   

2008-04-12 08:44 by 人面桃花
呵呵 很好啊

# re: 分享一个spring+hibernate的通用分页类  回复  更多评论   

2015-10-06 23:34 by 暗夜百家
里面userPage是什么

只有注册用户登录后才能发表评论。


网站导航:
 

posts - 146, comments - 143, trackbacks - 0, articles - 0

Copyright © flustar