数据库分页的实现
前言
这是我的首篇技术文章,文章内容其实是一年前做项目的时候写的。今天拿出来共享一下,这篇文章适合初学者学习借用,也希望各位大神提出宝贵意见。
一、分页技术简介
分页技术主要分三种:客户端分页、数据库分页、服务器端分页。
客户端分页:客户端分页说的直白一点就是在前台进行分页。这种分页的方式减少了与数据库的交互次数,但主要不足之处在于它要先把所有的数据从数据库中读出来,然后再拿到前台进行分页,当数据量很大的时候,这种缺点暴露的就更加明显。
数据库分页:这种分页方式刚好跟客户端分页相反,它是根据前台对pageSize的要求,按照pageSize的大小来查询数据库。当数据量很大时这种分页方式比较适用,只在页面上有查询需求时,后台才去查询数据库。这种分页方式加大了与数据库的交互次数
服务器端分页:这种分页方式结合了前面两种分页方式。先将数据一次性从数据库中读取出来放到缓冲区,在客户端进行分页。
二、数据库分页技术实现
1、com.***.data
做分页之前,先将与分页相关的属性和方法封装成一个JavaBean,在上层将这些以对象的形式呈现给客户端。具体的实现代码如下:
1 package zhu.common.data; 2 3 import java.util.List; 4 5 public class Pager { 6 private int totalRows;//记录总数 7 private int pageSize = 5;//设置一页显示的记录数 8 private int currentPage;//当前页码 9 private int totalPages;//总页数 10 private int startRow;//当前页码开始记录数 11 private List elements;//记录列表 12 public Pager() { 13 } 14 //构造pager对象 15 public Pager(int _totalRows, int pageSize) { 16 this.pageSize=pageSize; 17 totalRows = _totalRows; 18 totalPages=totalRows/pageSize; 19 int mod=totalRows%pageSize; 20 if(mod>0){ 21 totalPages++;//最后一页不足一页则总页数加1 22 } 23 currentPage = 1;//初始设置当前页为第一页 24 startRow = 0;//初始读取设置为0 25 } 26 27 //点击首页按钮,执行这个方法 28 public void first() { 29 currentPage = 1; 30 startRow = 0; 31 } 32 //点击上一页按钮,执行这个方法 33 public void previous() { 34 if (currentPage == 1) { 35 return; 36 } 37 currentPage--; 38 startRow = (currentPage - 1) * pageSize; 39 } 40 //点击下一页按钮,执行这个方法 41 public void next() { 42 if (currentPage < totalPages) { 43 currentPage++; 44 } 45 startRow = (currentPage - 1) * pageSize; 46 } 47 //点击尾页按钮,执行这个方法 48 public void last() { 49 currentPage = totalPages; 50 startRow = (currentPage - 1) * pageSize; 51 } 52 53 //做页面跳转时,执行这个方法 54 public void refresh(int _currentPage) { 55 currentPage = _currentPage; 56 if (currentPage > totalPages) { 57 last();//_currentPage超过了总页数,则跳转到最后一页 58 } 59 if(currentPage<1){ 60 first();//_currentPage不足1,则跳转到首页 61 } 62 startRow = (currentPage - 1) * pageSize;//重新设置起始读取位置 63 } 64 /*此处略去35行setters和getters,但是在使用这个类时要加上*/ 65 }
2、com.***.utils
将分页类设计成公用的util,不同的模块需要用到分页功能,都可以使用,但是前提是我们在applicationContext-dao.xml中配置了相应的bean。
<bean id="pagerManager" class="zhu.***.utils.PagerManagerImpl">
<property name="hibernateTemplate">
<ref bean="hibernateTemplate" />
</property>
</bean>
具体的实现代码如下:
(1) interface IPagerManager
分页工具对外的接口定义。具体的实现代码如下:
1 package zhu.***.utils; 2 3 import zhu.***.data.Pager; 4 5 public interface IPagerManager { 6 /* 7 * 获取分页对象: 8 * hsql:查询语句 9 * currentPage:当前页 10 * pagerMethod:只有5种取值(first、previous、next、last、空值)(首页、上一页、下一页、尾页) 11 * 当pagerMethod为空值时,直接跳到currentPage所指定的页数 12 */ 13 public Pager getPager(String hsql,Integer pageSize,String currentPage,String pagerMethod); 14 15 }
(2) implement PagerManagerImpl
分页工具对外的接口的实现。具体的实现代码如下:
1 package zhu.***.utils; 2 import java.util.ArrayList; 3 import java.util.List; 4 import org.hibernate.Query; 5 import org.hibernate.Session; 6 import org.springframework.orm.hibernate3.SessionFactoryUtils; 7 import org.springframework.orm.hibernate3.support.HibernateDaoSupport; 8 import zhu.***.data.Pager; 9 10 public class PagerManagerImpl extends HibernateDaoSupport implements IPagerManager { 11 /* 获取pager对象,用于传到页面 12 根据从页面上传过来的条件查询数据 13 currentPage主要用于指定页面跳转用,pagerMethod用于首页、前一页、后一页、尾页这四种请求的跳转 14 currentPage和pagerMethod不会同时不为空 15 */ 16 public Pager getPager(String hsql,Integer pageSize, String currentPage, String pagerMethod) { 17 18 int totalRows = 0; 19 List items = new ArrayList(); 20 Pager pager = null; 21 Session session = SessionFactoryUtils.getSession(getSessionFactory(),true); 22 Query query = session.createQuery(hsql); 23 24 totalRows = (query.list()).size(); //取得总计录数 25 //调用构造函数,初始化各种属性,包括currentPage=1和startRow=0 26 pager = new Pager(totalRows,pageSize); 27 //currentPage主要是做固定页面跳转用,从页面获取跳转页号赋给currentPage 28 //如果不为空,则根据从页面获取currentPage来刷新pager对象 29 if (currentPage != null) { 30 pager.refresh(Integer.parseInt(currentPage)); 31 } 32 //pagerMethod有四种值即四种请求方式:首页,前一页,后一页,尾页。 33 if (pagerMethod != null) { 34 if (pagerMethod.equals("first")) { 35 pager.first(); 36 } else if (pagerMethod.equals("previous")) { 37 pager.previous(); 38 } else if (pagerMethod.equals("next")) { 39 pager.next(); 40 } else if (pagerMethod.equals("last")) { 41 pager.last(); 42 } 43 } 44 //从当前页记录数开始 45 query.setFirstResult(pager.getStartRow()); 46 //取出pageSize个记录 47 query.setMaxResults(pager.getPageSize()); 48 items = query.list();//根据startRow和pageSize查询数据库 49 pager.setList(items);//将查询到数据列表赋值给pager对象的elements属性 50 51 return pager; 52 } 53 }
3、com.***.dao
在模块中的DAO层使用分页工具,注意要先在该模块的dao.xml中进行配置相应的bean引用。
<bean id="ModuleDAO" class="***">
<property name="pagerManager">
<ref bean="pagerManager"/>
</property>
</bean>
具体的实现代码如下:
1 package zhu.***.dao; 2 import zhu.***.data.Pager; 3 import zhu.***.utils.IPagerManager; 4 5 public class ExampleDAOImpl { 6 private IPagerManager pagerManager; 7 /* 8 exampleQueryCondition:查询条件 9 ExampleTableName:数据表对应于持久化类类名 10 ExampleTablePropertyName:持久化类中的一个属性名 11 */ 12 public Pager find(Integer exampleQueryCondition, Integer pageSize, String currentPage, String pageMethod) { 13 14 String hsql = " from ExampleTableName where ExampleTablePropertyName = '" + exampleQueryCondition + "'"; 15 return this.pagerManager.getPager(hsql, pageSize, currentPage, 16 pageMethod); 17 } 18 }