首先,我们要理解分页的算法,也要讲究效率,也就是说我们不能把所有的记录取出来,我们只取一个页面中需要显示的纪录,那么怎么去实现是我们关心的问题!不要着急,重在理解而是单纯技术实现。我采用Web框架两种方式来实现,attention!<o:p></o:p>
分页算法,也就是我们提供给客户方便的操作。一般有哪些东西呢?<o:p></o:p>
上页、下页、首页、末页、导航到X页,页码导航。说到这里我们先放下,我们来说说取出页面的记录,也就是只取一段的记录。打开Hibernate API 看到Criteria 接口,public Criteria setMaxResults(int maxResults),意思为:设置记录对象数目的上限,第二方法,public Criteria setFirstResult setFirstResult(int firstResult),意思:设置开始取得记录对象的下标,其中的第一对象下标为0。这样我们可以看出Hibernate提供很好的方法给我们实现分页。<o:p></o:p>
我们产生了思路:我们只有设置firstResult得下标,我们这里把它叫做游标。我们只要控制游标就可以控制取得的记录就是我们想要得到的,下面要做的工作就是我们来控制index,下面我写了一个HPage的类来实现这个工作,也就是取得一些相关的值,其中我们关系的有:当前的页码、当前的游标等等,下面我们结合代码来说明下!~~~<o:p></o:p>
实现代码如下:
- public class HPage {
- private int countPage; //页面的数量
- private int startIndex=0; //纪录游标
- private int recordPerPage; //每页中的记录数量
- private int pageIndex=1; //初始的页码
- private boolean nextPage=true;
- private boolean previousPage=false;
- private boolean firstPage=true;
- private boolean lastPage=false;
- public int getCountPage() //取得页面的数量
- {
- return countPage;
- }
- public int getStartIndex() //取得游标的位置
- {
- return startIndex;
- }
- public HPage(int countRecord,int recordPerPage)
- //coutRecord参数:纪录的总数量;recordPerPage参数:设置每页的记录数量
- {
- this.recordPerPage=recordPerPage;
- if(countRecord % recordPerPage == 0)
- countPage=countRecord / recordPerPage;
- else
- countPage=countRecord / recordPerPage +1;
- }
- public int getPageIndex() // 取得当前页码
- {
- return pageIndex;
- }
- public int nextPage() // 游标下一页滚动
- {
- pageIndex++;
- if(isOnlyOne())
- {
- nextPage=false;
- previousPage=false;
- firstPage=false;
- lastPage=false;
- }
- else
- {
- previousPage=true;
- firstPage=true;
- }
- if(pageIndex > countPage)
- return lastPage();
- else
- {
- return (startIndex=forwardPage(pageIndex));
- }
- }
- public int previousPage() // 游标上一页滚动
- {
- pageIndex--;
- if(isOnlyOne())
- {
- nextPage=false;
- previousPage=false;
- firstPage=false;
- lastPage=false;
- }
- else
- {
- nextPage=true;
- lastPage=true;
- }
- if(pageIndex <= 1)
- return firstPage();
- else
- {
- return (startIndex=forwardPage(pageIndex));
- }
- }
- public int lastPage() // 游标向末页滚动
- {
- pageIndex=countPage;
- if(isOnlyOne())
- {
- nextPage=false;
- previousPage=false;
- firstPage=false;
- lastPage=false;
- }
- else
- {
- nextPage=false;
- previousPage=true;
- firstPage=true;
- lastPage=false;
- }
- return (startIndex=(countPage-1) * recordPerPage);
- }
- public int firstPage() // 游标向首页滚动
- {
- pageIndex=1;
- if(isOnlyOne())
- {
- nextPage=false;
- previousPage=false;
- firstPage=false;
- lastPage=false;
- }
- else
- {
- nextPage=true;
- previousPage=false;
- firstPage=false;
- lastPage=true;
- }
- return (startIndex=0);
- }
- public int forwardPage(int pageIndex) //导向制定页面
- {
- if(pageIndex >= countPage)
- {
- pageIndex=countPage;
- return (startIndex=lastPage());
- }
- else if(pageIndex <= 1)
- {
- pageIndex=1;
- return startIndex=firstPage();
- }
- this.pageIndex=pageIndex;
- if(isOnlyOne())
- {
- nextPage=false;
- previousPage=false;
- firstPage=false;
- lastPage=false;
- }
- else
- {
- nextPage=true;
- previousPage=true;
- firstPage=true;
- lastPage=true;
- }
- return (startIndex=(this.pageIndex -1)* recordPerPage);
- }
- private boolean isOnlyOne() //是否只有一页
- {
- return countPage==1 ? true : false;
- }
- public boolean isNextPage() //是否有下页
- {
- return nextPage;
- }
- public boolean isPreviousPage() //是否有上页
- {
- return previousPage;
- }
- public boolean isFirstPage() //是否首页
- {
- return firstPage;
- }
- public boolean isLastPage() //是否末页
- {
- return lastPage;
- }
- }
不是很难吧!好的,现在我们做好的工作就是取得了我们要的数值,下面要做的是加到Hibernate查询里面去,下面的工作很简单。但是我们要注意几个问题,第一个问题,我们的设计的目的不是为了解决一个问题,而是抽象出一个方案提供给相似的问题的解决方案。这样的话,我们最大化重利用代码,那么我们采用范性的特点(注意JDK5.0的特征,以前的版本会报错误)。下面我分析一下代码:<o:p></o:p>
- public class DisplayPageRecordList<t></t> { //泛型实现
- private int startIndex;
- private static final int DEFAULT_RECORD_PER_PAGE=5; //默认:每页中5条记录
- private List<t></t> list;
- private HPage page;
- private int recordPerPage=DEFAULT_RECORD_PER_PAGE;
- private final Session session=HibernateSessionFactory.getSession();
- private DetachedCriteria deCriteria;
- private Criteria criteria;
- private int countRecord;
- public DisplayPageRecordList(String className) throws ClassNotFoundException
- //className参数:类的全定名称
- {
- deCriteria=DetachedCriteria.forClass(Class.forName(className)); //创造离线的查询
- criteria=deCriteria.getExecutableCriteria(session);
- criteria.setCacheable(true);
- doInit();
- page=new HPage(countRecord,recordPerPage);
- }
- public DisplayPageRecordList(int recordPerPage,String className) throws ClassNotFoundException
- //recordPerPage参数:每页的纪录的条目数,className参数:同上个构造方法中
- {
- deCriteria=DetachedCriteria.forClass(Class.forName(className));
- criteria=deCriteria.getExecutableCriteria(session);
- criteria.setCacheable(true);
- this.recordPerPage=recordPerPage;
- doInit();
- page=new HPage(countRecord,recordPerPage);
- }
- public DisplayPageRecordList(int recordPerPage,String className,Criterion criterion) throws ClassNotFoundException
- //recordPerPage参数:同上个构造方法中,className参数:同上个构造方法中,criterion参数:设置查询条件
- {
- deCriteria=DetachedCriteria.forClass(Class.forName(className));
- criteria=deCriteria.getExecutableCriteria(session);
- criteria.add(criterion);
- criteria.setCacheable(true);
- doInit();
- page=new HPage(countRecord,recordPerPage);
- }
- public void setRecordPerPage(int recordPerPage)
- {
- this.recordPerPage=recordPerPage;
- page=new HPage(countRecord,recordPerPage);
- }
- private void doInit()
- {
- this.countRecord=criteria.list().size(); //计算数据库中所有的记录数
- }
- public void addCriterion(Criterion criterion)
- {
- criteria=criteria.add(criterion); //更改所有所有查询条件
- doInit();
- }
- public void setCacheable(boolean cache) //是否启用缓存
- {
- criteria.setCacheable(cache);
- }
- public List doNextPage() //查询出下页中的纪录集
- {
- startIndex=page.nextPage();
- criteria.setFirstResult(startIndex);
- criteria.setMaxResults(this.recordPerPage);
- list=criteria.list();
- return list;
- }
- public List doPreviousPage() //查询出上页中的纪录集
- {
- startIndex=page.previousPage();
- criteria.setFirstResult(startIndex);
- criteria.setMaxResults(this.recordPerPage);
- list=criteria.list();
- return list;
- }
- public List doFirstPage() //查询出首页中的纪录集
- {
- startIndex=page.firstPage();
- criteria.setFirstResult(startIndex);
- criteria.setMaxResults(this.recordPerPage);
- list=criteria.list();
- return list;
- }
- public List doLastPage() //查询出末页中的纪录集
- {
- startIndex=page.lastPage();
- criteria.setFirstResult(startIndex);
- criteria.setMaxResults(this.recordPerPage);
- list=criteria.list();
- return list;
- }
- public List doForward(int pageIndex)
- {
- startIndex=page.forwardPage(pageIndex);
- criteria.setFirstResult(startIndex);
- criteria.setMaxResults(this.recordPerPage);
- list=criteria.list();
- return list;
- }
- public HPage getPage() //取得页面对象
- {
- return this.page;
- }
- }
以上代码中,实现了泛型-离线查询的页面的代码。上篇完,下篇我们来使用Struts和JSTL在网页上测试<o:p></o:p>
<o:p></o:p>