花了两天时间才整理好的分页类,共享一下。
说明:该方法是参考了一下网上广为流传的DetachedCriteria查询方法后改进而来的。按照自己觉得满意呈现和重用方式。
按钮的效果可以简单的做到附件图片上的效果
虽然不敢说完美的分页按钮,但是很多大型网站都是用这样的吧。
------------------------------------
分页Bean类:
import java.util.List; import org.hibernate.criterion.DetachedCriteria; /** * 分页常用的bean类。<br> * 里面包含搜索返回的List,查询条件DetachedCriteria及分页菜单用到的数据等。 * * @author KennyLee E-mail:[email protected] 2008-10-25 */ public class KPaginationSupport implements Cloneable { // Default page size public static final int PAGESIZE = 20; public static final int MENU_SIZE = 7; // total Rows private int totalRowsAmount; private int pageSize = PAGESIZE; private int totalPages; // current page number private int currentPage = 1; // next page number private int nextPage; // previous page number private int previousPage; // is has next page private boolean hasNext; // is has previous page private boolean hasPrevious; // current page start row number private int pageStartRow = 0; // current page end row number private int pageEndRow; private String[] pageMenuNum; private int menuSize = MENU_SIZE; // Pagination values private List items; // select detachedCriteria private DetachedCriteria detachedCriteria; public KPaginationSupport() { } public String[] getPageMenuNum() { return pageMenuNum; } public void setPageMenuNum(String[] pageMenuNum) { this.pageMenuNum = pageMenuNum; } public DetachedCriteria getDetachedCriteria() { return detachedCriteria; } public void setDetachedCriteria(DetachedCriteria detachedCriteria) { this.detachedCriteria = detachedCriteria; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public void setTotalPages(int totalPages) { this.totalPages = totalPages; } public void setNextPage(int nextPage) { this.nextPage = nextPage; } public void setPreviousPage(int previousPage) { this.previousPage = previousPage; } public void setHasNext(boolean hasNext) { this.hasNext = hasNext; } public void setHasPrevious(boolean hasPrevious) { this.hasPrevious = hasPrevious; } public void setPageStartRow(int pageStartRow) { this.pageStartRow = pageStartRow; } public List getItems() { return items; } public void setItems(List items) { this.items = items; } public void setPageEndRow(int pageEndRow) { this.pageEndRow = pageEndRow; } /** * 构造函数。 * * @param totalRows * 总行数 * @param currentPage * 当前页数 */ public KPaginationSupport(int totalRows, int currentPage) { setPaginationSupport(totalRows, currentPage); } /** * 构造函数。 * * @param totalRows * 总行数 * @param currentPage * 当前页数 * @param pageSize * 每页显示数量。 */ public KPaginationSupport(int totalRows, int currentPage, int pageSize) { this.pageSize = pageSize; this.setPaginationSupport(totalRows, currentPage); String[] pageNums = getPageMenuNums(currentPage); this.setPageMenuNum(pageNums); } public void setPaginationSupport(int totalRows, int currentPage) { // 获取总页码,通过对象总数还是每页多少行的关系 setTotalRowsAmount(totalRows); setCurrentPage(currentPage); } public KPaginationSupport(List items, int totalCount) { setPageSize(PAGESIZE); setItems(items); int currentPage = 1; this.setPaginationSupport(totalCount, currentPage); } public KPaginationSupport(List items, int totalCount, int startIndex) { setPageSize(PAGESIZE); setItems(items); int currentPage = (startIndex / pageSize) + 1; this.setPaginationSupport(totalCount, currentPage); } /** * @param items * 保存的目标List * @param totalCount * 查找的总行数 * @param pageSize * 每页显示的行数 * @param startIndex * 第几行开始 * */ public KPaginationSupport(List items, int totalCount, int pageSize, int startIndex) { setPageSize(pageSize); setItems(items); int currentPage = (startIndex / pageSize) + 1; this.setPaginationSupport(totalCount, currentPage); } /** * * 构造PS时的初始化方法。 * * @param items * 保存的目标List * @param totalCount * 查找的总行数 * @param pageSize * 每页显示的行数 * @param startIndex * 第几行开始 * */ public KPaginationSupport(List items, int totalCount, int pageSize, int startIndex, DetachedCriteria detachedCriteria) { setPageSize(pageSize); setItems(items); int currentPage = (startIndex / pageSize) + 1; this.setPaginationSupport(totalCount, currentPage); setDetachedCriteria(detachedCriteria); String[] pageNums = getPageMenuNums(currentPage); this.setPageMenuNum(pageNums); } /** * 分页导航按钮 * * @param currentPage * @return */ private String[] getPageMenuNums(int currentPage) { String[] pageNums = null; if (totalPages > menuSize) {// 总页数大于导航显示的页数 pageNums = new String[menuSize]; int lastMenuNum = totalPages - menuSize + 1;// 最后一列导航栏按钮 int beginMumNum = menuSize; int x = menuSize - 1;// 导航显示系数 if ((currentPage < lastMenuNum) && (currentPage > beginMumNum)) { for (int i = 0; i < menuSize; i++) { pageNums[i] = String.valueOf(currentPage + i - x / 2); } } else if (currentPage > lastMenuNum) { for (int i = 0; i < menuSize; i++) { pageNums[i] = String.valueOf(lastMenuNum + i); } } else if (currentPage == lastMenuNum) { if ((lastMenuNum - x / 2) < 1) { lastMenuNum = x / 2 + 1; } for (int i = 0; i < menuSize; i++) { pageNums[i] = String.valueOf(lastMenuNum + i - x / 2); } } else if (currentPage == beginMumNum) { for (int i = 0; i < menuSize; i++) { pageNums[i] = String.valueOf(1 + i + x / 2); } } else { for (int i = 0; i < menuSize; i++) { pageNums[i] = String.valueOf(1 + i); } } } else {// 总页数小于等于导航显示的页数,直接显示。 pageNums = new String[totalPages]; // 分页数比总页数少 for (int i = 0; i < totalPages; i++) { pageNums[i] = String.valueOf(i + 1); } } return pageNums; } /** * 设置总行数。 * * @param rows * 总行数。 */ private void setTotalRowsAmount(int rows) { if (rows < 0) { totalRowsAmount = 0; } else { totalRowsAmount = rows; } if (totalRowsAmount % pageSize == 0) { totalPages = totalRowsAmount / pageSize; } else { totalPages = totalRowsAmount / pageSize + 1; } } /** *设置当前页数。 * * @param curPage */ private void setCurrentPage(int curPage) { if (curPage <= 0) { currentPage = 1; } else if (curPage > totalPages) { currentPage = totalPages; } else { currentPage = curPage; } if (currentPage == 1) { hasPrevious = false; } else { hasPrevious = true; } if (currentPage == totalPages) { hasNext = false; } else { hasNext = true; } nextPage = currentPage + 1; previousPage = currentPage - 1; // 计算当前页开始行和结束行 pageStartRow = (currentPage - 1) * pageSize + 1; // pageStartRow = (currentPage - 1) * pageSize; // 记录索引从0开始 pageStartRow -= 1; pageEndRow = pageStartRow + pageSize; } public int getCurrentPage() { return currentPage; } public boolean isHasNext() { return hasNext; } public boolean isHasPrevious() { return hasPrevious; } public int getNextPage() { return nextPage; } public int getPageSize() { return pageSize; } public int getPreviousPage() { return previousPage; } public int getTotalPages() { return totalPages; } public int getTotalRowsAmount() { return totalRowsAmount; } public int getPageStartRow() { return pageStartRow; } public int getPageEndRow() { return pageEndRow; } public String description() { String description = "Total:" + this.getTotalRowsAmount() + " items " + this.getTotalPages() + " pages,Current page:" + this.currentPage + " Previous " + this.hasPrevious + " Next:" + this.hasNext + " start row:" + this.pageStartRow + " end row:" + this.pageEndRow; return description; } public void init() { // do some initialization work } @Override public KPaginationSupport clone() throws CloneNotSupportedException { return (KPaginationSupport) super.clone(); } public int getMenuSize() { return menuSize; } public void setMenuSize(int menuSize) { this.menuSize = menuSize; } }
----------------------
DAO层,其实不需要局限用Criteria查询的。查询好需要的数据后,构造bean类,如下。
附上完整的DetachedCriteria查询方法供参考。在网上找到的,然后参考改进了一下,因为找到的都存在BUG,下面是修正后的版本。测试,并且正常使用中。
/** * @param detachedCriteria * @param pageSize * @param startIndex */ public PaginationSupport findPageByCriteria( final DetachedCriteria detachedCriteria, final int pageSize, final int startIndex) { log.info("in findByPage..."); return (PaginationSupport) getHibernateTemplate().execute( new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Criteria criteria = detachedCriteria .getExecutableCriteria(session); CriteriaImpl impl = (CriteriaImpl) criteria; // 先把Projection和OrderBy条件取出来,清空两者来执行Count操作 Projection projection = impl.getProjection(); int totalCount = ((Integer) criteria.setProjection( Projections.rowCount()).uniqueResult()) .intValue(); log.info("totalCount:" + totalCount); // 将之前的Projection和OrderBy条件重新设回去 criteria.setProjection(projection); if (projection == null) { criteria .setResultTransformer(CriteriaSpecification.ROOT_ENTITY); } List items = criteria.setFirstResult(startIndex) .setMaxResults(pageSize).list(); PaginationSupport ps = new PaginationSupport(items, totalCount, pageSize, startIndex, detachedCriteria); // Set default status criteria.setFirstResult(0).setMaxResults(totalCount); return ps; } }); }
----------------------
view层使用struts标签,代码有点长,供参考。注意css效果。
注意,action的方法其实需要两个即可,一个是第一次搜索的时候查询方法。另外一个是跳转到任何一页的方法。就算向前向后这样的方法其实并不需要。
<!-- pagination menu begin by KennyLee 2008-9-16 --> <logic:present name="pageController" scope="request"> <tr> <td colspan="6"> <div id="pagination_info"> [共${pageController.totalRowsAmount} 个账号] ${pageController.currentPage}/${pageController.totalPages}页(每页显示${pageController.pageSize}) </div> <div class="pagination"> <logic:equal value="true" name="pageController" property="hasPrevious"> <html:link action="/mailbox/controller/list/pre" paramId="toPageGo" paramName="pageController" paramProperty="previousPage"><Perv</html:link> </logic:equal> <logic:notEqual value="true" name="pageController" property="hasPrevious"> <span class="disabled"><Perv</span> </logic:notEqual> <logic:iterate id="num" name="pageController" property="pageMenuNum" indexId="index"> <logic:equal value="0" name="index"> <logic:equal value="2" name="num"> <html:link page="/mailbox/controller/list/current.jspx?toPageGo=1">1</html:link> </logic:equal> <logic:greaterThan value="2" name="num"> <html:link page="/mailbox/controller/list/current.jspx?toPageGo=1">1</html:link> <span>...</span> </logic:greaterThan> </logic:equal> <logic:equal value="${num}" property="currentPage" name="pageController"> <span class="current">${pageController.currentPage}</span> </logic:equal> <logic:notEqual value="${num}" property="currentPage" name="pageController"> <html:link page="/mailbox/controller/list/current.jspx?toPageGo=${num}">${num}</html:link> </logic:notEqual> <logic:equal value="${pageController.menuSize-1}" name="index"> <logic:equal value="${pageController.totalPages-1}" name="num"> <html:link page="/mailbox/controller/list/current.jspx?toPageGo=${pageController.totalPages}">${pageController.totalPages}</html:link> </logic:equal> <logic:lessThan value="${pageController.totalPages-1}" name="num"> <span>...</span> <html:link page="/mailbox/controller/list/current.jspx?toPageGo=${pageController.totalPages}">${pageController.totalPages}</html:link> </logic:lessThan> </logic:equal> </logic:iterate> <logic:equal value="true" name="pageController" property="hasNext"> <html:link action="/mailbox/controller/list/next" paramId="toPageGo" paramName="pageController" paramProperty="nextPage">Next></html:link> </logic:equal> <logic:notEqual value="true" name="pageController" property="hasNext"> <span class="disabled">Next></span> </logic:notEqual> </div> </td> </tr> </logic:present> <!-- pagination menu end -->