本文参考传智播客巴巴运动网视频教程
首先创建一个QueryResult类来存放结果集和总记录数:package cn.aaron.bean;
import java.util.List; public class QueryResult<T> { private List<T> resultlist; private long totalrecord; public List<T> getResultlist() { return resultlist; } public void setResultlist(List<T> resultlist) { this.resultlist = resultlist; } public long getTotalrecord() { return totalrecord; } public void setTotalrecord(long totalrecord) { this.totalrecord = totalrecord; } }
接下来在DaoSupport类里面添加如下方法:
/** * 分页获取记录 * @param firstindex 开始索引,如果输入值为-1,即获取全部数据 * @param maxresult 每页获取的记录数,如果输入值为-1,即获取全部数据 * @param wherejpql 条件语句,不带where关键字,条件语句只能使用位置参数,位置参数索引以1开始,如:o.username=?1 and o.password=?2 * @param params 条件语句出现的位置参数 * @param orderby 排序,Key为排序属性,Value为asc/desc */ @Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED) public QueryResult<T> getScrollData(int firstindex, int maxresult , String wherejpql, Object[] queryParams,LinkedHashMap<String, String> orderby) { QueryResult qr = new QueryResult<T>(); String entityname = getEntityName(this.entityClass); Query query = em.createQuery("select o from "+ entityname+ " o "+(wherejpql==null || "".equals(wherejpql.trim())? "": "where "+ wherejpql)+ buildOrderby(orderby)); setQueryParams(query, queryParams); if(firstindex!=-1 && maxresult!=-1) query.setFirstResult(firstindex).setMaxResults(maxresult); qr.setResultlist(query.getResultList()); query = em.createQuery("select count("+ getCountField(this.entityClass)+ ") from "+ entityname+ " o "+(wherejpql==null || "".equals(wherejpql.trim())? "": "where "+ wherejpql)); setQueryParams(query, queryParams); qr.setTotalrecord((Long)query.getSingleResult()); return qr; } protected static void setQueryParams(Query query, Object[] queryParams){ if(queryParams!=null && queryParams.length>0){ for(int i=0; i<queryParams.length; i++){ query.setParameter(i+1, queryParams[i]); } } } /** * 组装order by语句 * @param orderby * @return */ protected static String buildOrderby(LinkedHashMap<String, String> orderby){ StringBuffer orderbyql = new StringBuffer(""); if(orderby!=null && orderby.size()>0){ orderbyql.append(" order by "); for(String key : orderby.keySet()){ orderbyql.append("o.").append(key).append(" ").append(orderby.get(key)).append(","); } orderbyql.deleteCharAt(orderbyql.length()-1); } return orderbyql.toString(); } /** * 获取实体的名称 * @param <E> * @param clazz 实体类 * @return */ protected static <E> String getEntityName(Class<E> clazz){ String entityname = clazz.getSimpleName(); Entity entity = clazz.getAnnotation(Entity.class); if(entity.name()!=null && !"".equals(entity.name())){ entityname = entity.name(); } return entityname; } protected static <E> String getCountField(Class<E> clazz){ String out = "o"; try { PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); for(PropertyDescriptor propertydesc : propertyDescriptors){ Method method = propertydesc.getReadMethod(); if(method!=null && method.isAnnotationPresent(EmbeddedId.class)){ PropertyDescriptor[] ps = Introspector.getBeanInfo(propertydesc.getPropertyType()).getPropertyDescriptors(); out = "o."+ propertydesc.getName()+ "." + (!ps[1].getName().equals("class")? ps[1].getName(): ps[0].getName()); break; } } } catch (Exception e) { e.printStackTrace(); } return out; }
getScrollData是最主要的方法,可以对分页进行排序、加条件等等。
我们可以讲getScrollData得到的值存放到下面这个类中,请注意这个类的注释以及相关方法的注释:
import java.util.List; /** * 封装了Action向jsf所存放的一些数据 * 该类最重要的是调用setQueryResult方法,他会连环设置该类其他属性的值。 * @author bruce * @param <T> */ public class PageView<T> { /** 分页数据 **/ private List<T> records; /** 页码开始索引和结束索引 **/ private PageIndex pageindex; /** 总页数 **/ private long totalpage = 1; /** 每页显示记录数 **/ private int maxresult = 12; /** 当前页 **/ private int currentpage = 1; /** 总记录数 **/ private long totalrecord; /** 页码数量 **/ private int pagecode = 10; /** 要获取记录的开始索引 **/ public int getFirstResult() { return (this.currentpage-1)*this.maxresult; } public int getPagecode() { return pagecode; } public void setPagecode(int pagecode) { this.pagecode = pagecode; } /** * 构造方法,要使用这个类,必须传进每页显示记录数和当前页。 * @param maxresult * @param currentpage */ public PageView(int maxresult, int currentpage) { this.maxresult = maxresult; this.currentpage = currentpage; } /** * 该方法存在一个连环的调用 * 将从数据库分页查询出来的总结果集和总记录数设置进来。 * 在设置总记录数的同时,会换算出总页数。详情参看setTotalrecord方法。 * 在设置总页数的同时,包含分页的开始索引和结束索引的PageIndex对象也确定了下来。详情参看setTotalpage方法。 * @param qr */ public void setQueryResult(QueryResult<T> qr){ setRecords(qr.getResultlist()); setTotalrecord(qr.getTotalrecord()); } public long getTotalrecord() { return totalrecord; } /** * 在设置总记录数的同时,会将总页数也设置进来。 * 在设置总页数的同时,包含分页的开始索引和结束索引的PageIndex对象也确定了下来。 * @param totalrecord */ public void setTotalrecord(long totalrecord) { this.totalrecord = totalrecord; setTotalpage(this.totalrecord%this.maxresult==0? this.totalrecord/this.maxresult : this.totalrecord/this.maxresult+1); } public List<T> getRecords() { return records; } public void setRecords(List<T> records) { this.records = records; } public PageIndex getPageindex() { return pageindex; } public long getTotalpage() { return totalpage; } public void setTotalpage(long totalpage) { this.totalpage = totalpage; this.pageindex = PageIndex.getPageIndex(pagecode, currentpage, totalpage); } public int getMaxresult() { return maxresult; } public int getCurrentpage() { return currentpage; } }
PageView用到了一个类PageIndex:
/** * 此类有一个静态方法,返回带有分页的开始索引和结束索引值的对象 */ public class PageIndex { private long startindex; private long endindex; public PageIndex(long startindex, long endindex) { this.startindex = startindex; this.endindex = endindex; } public long getStartindex() { return startindex; } public void setStartindex(long startindex) { this.startindex = startindex; } public long getEndindex() { return endindex; } public void setEndindex(long endindex) { this.endindex = endindex; } /** * 静态方法来获取分页的开始索引和结束索引的值 * @param viewpagecount 分页栏总共显示多少个页码 * @param currentPage 当前页码值 * @param totalpage 总共页码值 * @return 带有开始索引和结束索引的页码对象 */ public static PageIndex getPageIndex(long viewpagecount, int currentPage, long totalpage){ long startpage = currentPage-(viewpagecount%2==0? viewpagecount/2-1 : viewpagecount/2); long endpage = currentPage+viewpagecount/2; if(startpage<1){ startpage = 1; if(totalpage>=viewpagecount) endpage = viewpagecount; else endpage = totalpage; } if(endpage>totalpage){ endpage = totalpage; if((endpage-viewpagecount)>0) startpage = endpage-viewpagecount+1; else startpage = 1; } return new PageIndex(startpage, endpage); } }
前台jsp的封装如下:
<%@ page language="java" pageEncoding="UTF-8"%> <font color="#FFFFFF"> 当前页:第${pageView.currentpage}页 | 总记录数:${pageView.totalrecord}条 | 每页显示:${pageView.maxresult}条 | 总页数:${pageView.totalpage}页</font> <c:forEach begin="${pageView.pageindex.startindex}" end="${pageView.pageindex.endindex}" var="wp"> <c:if test="${pageView.currentpage==wp}"><b><font color="#FFFFFF">第${wp}页</font></b></c:if> <c:if test="${pageView.currentpage!=wp}"><a href="javascript:topage('${wp}')" class="a03">第${wp}页</a></c:if> </c:forEach>
倒数第二行用到了a href="javascript:topage('${wp}')"而不是直接写链接地址,这是因为这个jsp是封装好的,以后别的jsp调用就可以直接写一个topage的js方法来将链接地址写入。