分页查询

   分页是系统中常用到的功能,只要涉及到查询必定伴随而来的就是分页,之前也学习过关于分页的内容,例如在牛腩的新闻发布系统,之前学习的大部分都是使用了假分页,这次学习java,使用Oracle数据库来实现一下真分页。

      首先来说一下实现这个分页查询的流程:

一、封装分页信息:

        需要分页的部分我们首先要做的是为分页封装一个分页实体,方便返回查询信息,封装如下:

 

[java] view plain copy
 
 print?
  1. /** 
  2.  *封装分页信息 
  3.  * @author YoungJong 
  4.  * 
  5.  */  
  6. public class PageModel<E> {  
  7.     //结果集  
  8.     private List<E> list;  
  9.     //查询记录数  
  10.     private int totalRecords;  
  11.     //每页多少条记录  
  12.     private int pageSize;  
  13.     //第几页  
  14.     private int pageNo;  
  15.       
  16.     public List<E> getList() {  
  17.         return list;  
  18.     }  
  19.     public void setList(List<E> list) {  
  20.         this.list = list;  
  21.     }  
  22.     public int getTotalRecords() {  
  23.         return totalRecords;  
  24.     }  
  25.     public void setTotalRecords(int totalRecords) {  
  26.         this.totalRecords = totalRecords;  
  27.     }  
  28.     public int getPageSize() {  
  29.         return pageSize;  
  30.     }  
  31.     public void setPageSize(int pageSize) {  
  32.         this.pageSize = pageSize;  
  33.     }  
  34.     public int getPageNo() {  
  35.         return pageNo;  
  36.     }  
  37.     public void setPageNo(int pageNo) {  
  38.         this.pageNo = pageNo;  
  39.     }  
  40.     /** 
  41.      * 总页数 
  42.      * @return 
  43.      */  
  44.     public int getTotalPages(){  
  45.         return(totalRecords+pageSize-1)/pageSize;  
  46.           
  47.     }  
  48.     /** 
  49.      * 取得首页 
  50.      * @return 
  51.      */  
  52.     public int getTopPageNo(){  
  53.         return 1;  
  54.     }  
  55.     /** 
  56.      * 上一页 
  57.      * @return 
  58.      */  
  59.     public int getPreviousPageNo(){  
  60.         if(pageNo<=1){  
  61.             return 1;  
  62.         }  
  63.         return pageNo-1;  
  64.     }  
  65.     /** 
  66.      * 下一页 
  67.      * @return 
  68.      */  
  69.     public int getNextPageNo() {  
  70.         if (pageNo >= getBottomPageNo()) {  
  71.             return getBottomPageNo();  
  72.         }  
  73.         return pageNo + 1;    
  74.     }  
  75.     /** 
  76.      * 取得尾页 
  77.      * @return 
  78.      */  
  79.     public int getBottomPageNo(){  
  80.         return getTotalPages();  
  81.     }  
  82.   
  83. }  

 

 

      这里的重点是这个实体使用了泛型,使用分页显示的数据并不全是同一种实体数据,为了更好的复用分页查询,将结果集定义成泛型,则便于众多信息的查询:

二、页面加载显示查询数据并分页显示(Servlet):

        页面加载时调用一个Servlet,通过Servelt来调用分页查询并将查询结果返回到页面:我们先来看Servlet的代码实现:

 

[java] view plain copy
 
 print?
  1. public class SearchItemServlet extends AbstractItemServlet {  
  2.     /** 
  3.      * 覆盖servlet的doGet方法 
  4.      */  
  5.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  6.             throws ServletException, IOException {  
  7.         // 定义显示第几页的变量  
  8.         int pageNo=0;  
  9.         //int pageSize=2;  
  10.         //从配置文件读取每页设置的显示数据数量  
  11.         int pageSize=Integer.parseInt(this.getServletContext().getInitParameter("page-size"));  
  12.         //获取jsp传递过来的显示第几页  
  13.         String pageNoString=req.getParameter("pageNo");  
  14.         //如果为空则显示第一页  
  15.         if(pageNoString==null){  
  16.             pageNo=1;  
  17.         }else{  
  18.             pageNo=Integer.parseInt(pageNoString);  
  19.         }  
  20.           
  21.         //取得查询条件条件,条件为空则查询全部  
  22.         String condation=req.getParameter("clientIdOrName");  
  23.           
  24.         //调用分页查询方法,返回查询数据  
  25.         PageModel pageModel=itemManager.findItemList(pageNo, pageSize, condation);  
  26.           
  27.         ///取得查询页面传递过来的分页实体  
  28.         req.setAttribute("pageModel", pageModel);  
  29.         //将查询数据在页面显示  
  30.         req.getRequestDispatcher("/basedata/item_maint.jsp").forward(req, resp);  
  31.     }  
  32.   
  33.     @Override  
  34.     protected void doPost(HttpServletRequest req, HttpServletResponse resp)  
  35.             throws ServletException, IOException {  
  36.         // TODO Auto-generated method stub  
  37.         //super.doPost(req, resp);  
  38.         doGet(req,resp);  
  39.     }  
  40.   
  41. }  

 

 

 

其中值得注意的是,关于每页显示数据条数的问题,这一部分可以自己写在代码里,也可以将显示的数目写在配置文件中,只需要读取配置文件即可,方便配置:

其中配置文件可以这样写:在WEB-INF下的web.xml中:

 

[html] view plain copy
 
 print?
  1. <context-param>  
  2.     <param-name>page-size</param-name>  
  3.     <param-value>3</param-value>  
  4. lt;/context-param>  



 

 

这种写法是可以适用于系统中所有的Servlet的,每一个想读取页面显示数量的都可以进行读取。

 

三、Dao层实现分页查询:

       Servlet调用查询方法是通过一个Manager的接口,类似于三层中B层的作用,由于没有复杂的逻辑,所以这里的代码很简单:

 

[java] view plain copy
 
 print?
  1. /**  
[java] view plain copy
 
 print?
  1.  * 查询物料信息,参数分别为:页码,每页显示数据,查询条件  
  2.  */  
  3. public PageModel findItemList(int pageNo, int pageSize, String condation) {  
  4.       
  5.     Connection conn=null;  
  6.     try{  
  7.         conn=DbUtil.getConnection();  
  8.         //调用Dao层的分页查询  
  9.         return itemDao.findItemList(conn, pageNo, pageSize, condation);  
  10.     }finally{  
  11.         DbUtil.close(conn);  
  12.     }  
  13.       
  14. }  



 

 

真分页查询的重点在于DAO层的实现,下面我们来看一下代码:

 

[java] view plain copy
 
 print?
  1. /**  
[java] view plain copy
 
 print?
  1.  * 分页查询  
  2.  */  
  3. public PageModel findItemList(Connection conn,int pageNo, int pageSize, String condation) {  
  4.       
  5.     StringBuffer sbSql=new StringBuffer();  
  6.       
  7.     sbSql.append("select * ")  
  8.     .append("from (")  
  9.         .append("select i.*, rownum rn from (")  
  10.         .append("select a.item_no, a.item_name, a.spec, a.pattern, a.item_category_id, ")  
  11.         .append("b.name as item_category_name, a.item_unit_id, c.name as item_unit_name, a.file_name ")  
  12.         .append("from t_items a, t_data_dict b, t_data_dict c ")  
  13.         .append("where a.item_category_id=b.id and a.item_unit_id=c.id  ");  
  14.         if (condation != null && !"".equals(condation)) {  
  15.             sbSql.append(" and (a.item_no like '" + condation + "%' or a.item_name like '" + condation + "%') ");  
  16.         }  
  17.         sbSql.append(" order by a.item_no")  
  18.         .append(") i where rownum<=? ")  
  19.         .append(") ")  
  20.         .append("where rn >? ");  
  21. System.out.println("sql=" + sbSql.toString());  
  22.           
  23. //通常采用日志组件记录,如log4j, 级别:info,debug,error...  
  24. PreparedStatement pstmt = null;  
  25. ResultSet rs = null;  
  26. PageModel pageModel = null;  
  27. try {  
  28.     //为查询条件参数赋值  
  29.     pstmt = conn.prepareStatement(sbSql.toString());  
  30.     //查询数据库中列在如何条件之间的数据  
  31.     pstmt.setInt(1, pageNo * pageSize);  
  32.     pstmt.setInt(2, (pageNo - 1) * pageSize);  
  33.     int i=pageNo*pageSize;  
  34.     int j=(pageNo - 1) * pageSize;  
  35.     rs = pstmt.executeQuery();  
  36.     //获得符合条件的信息结婚  
  37.     List itemList = new ArrayList();  
  38.     while (rs.next()) {  
  39.         Item item = new Item();  
  40.         item.setItemNo(rs.getString("item_no"));  
  41.         item.setItemName(rs.getString("item_name"));  
  42.         item.setSpec(rs.getString("spec"));  
  43.         item.setPattern(rs.getString("pattern"));  
  44.         //构造ItemCategory  
  45.         ItemCategory ic = new ItemCategory();  
  46.         ic.setId(rs.getString("item_category_id"));  
  47.         ic.setName(rs.getString("item_category_name"));  
  48.         item.setItemCategory(ic);  
  49.           
  50.         //构造ItemUnit  
  51.         ItemUnit iu = new ItemUnit();  
  52.         iu.setId(rs.getString("item_unit_id"));  
  53.         iu.setName(rs.getString("item_unit_name"));  
  54.         item.setItemUnit(iu);  
  55.           
  56.         item.setFileName(rs.getString("file_name"));  
  57.         itemList.add(item);  
  58.     }  
  59.     //为分页实体赋值  
  60.     pageModel = new PageModel();  
  61.     pageModel.setPageNo(pageNo);  
  62.     pageModel.setPageSize(pageSize);  
  63.     pageModel.setList(itemList);  
  64.     //根据条件取得记录数  
  65.     int totalRecords = getTotalRecords(conn, condation);  
  66.     pageModel.setTotalRecords(totalRecords);  
  67. }catch(SQLException e) {  
  68.     e.printStackTrace();  
  69.     //记录到日志文件 error  
  70.     throw new ApplicationException("分页查询失败");  
  71. }finally {  
  72.     DbUtil.close(rs);  
  73.     DbUtil.close(pstmt);  
  74. }  
  75. return pageModel;  
  76. }  

 

 

其实看起来复杂,做起来逻辑并不复杂,很容易实现

四、jsp页面显示

    后台获得了数据,传递到页面,页面接收后就可以在页面上进行显示了,其实获得数据的代码一句话就可以搞定:更Servlet的代码是对应的,因为在Servlet中我们已经使用了setAttribute,所以jsp中的代码如下:

PageModel pageModel= (PageModel) request.getAttribute("pageModel");

   点击跳到首页的方法如下(其他跳转类似不一一列出):

 

[java] view plain copy
 
 print?
  1. //跳转到首页  
  2. function topPage() {  
  3.       
  4.         window.self.location="<%=basePath%>servlet/item/SearchItemServlet?pageNo=<%=pageModel.getTopPageNo()%>&clientIdOrName=<%=clientIdOrName%>";  
  5.   
  6. }  


     这是一个完整的分页查询的流程,很多都是封装好的可以复用,只是在DAO层的查询语句需要自己写,不过最近了解了一些NHiernate,关于Hibernate的知识也在学习中,自己要写sql语句的问题也是可以解决的!

posted @ 2016-06-22 16:16  新月勾魂  阅读(90)  评论(0)    收藏  举报