java+oracle 分页技术实现

来源:互联网 发布:用服务器ip做网站域名 编辑:程序博客网 时间:2024/06/07 08:45

分页技术原理与实现(二)——Java+Oracle代码实现

  紧接着上篇—分页技术原理与实现(一)——为什么要进行分页及怎么分页,本篇继续分析分页技术。上篇讲的是分页技术的简单原理与介绍,这篇深入分析一下分页技术的代码实现。

  上篇最后讲到了分页的最佳实现是在数据库层进行分页,而且不同的数据库有不同的分页实现,比如oracle是用三层sql嵌套实现分页的、MySQL是用limit关键字实现的(上篇已讲到)。

  这篇以Java+Oracle为基础,讲解代码层的实现。

  就如平时我们很在分页中看到的,分页的时候返回的不仅包括查询的结果集(List),而且还包括总的页数(pageNum)、当前第几页(pageNo)等等信息,所以我们封装一个查询结果PageModel,代码如下:

 

[java] view plain copy
  1. package kane;  
  2. import java.util.List;  
  3. public class PageModel<E> {  
  4.     private List<E> list;  
  5.     private int pageNo;  
  6.     private int pageSize;  
  7.     private int totalNum;  
  8.     private int totalPage;  
  9.   
  10.     public List<E> getList() {  
  11.         return list;  
  12.     }  
  13.   
  14.     public void setList(List<E> list) {  
  15.         this.list = list;  
  16.     }  
  17.   
  18.     public int getPageNo() {  
  19.         return pageNo;  
  20.     }  
  21.   
  22.     public void setPageNo(int pageNo) {  
  23.         this.pageNo = pageNo;  
  24.     }  
  25.   
  26.     public int getPageSize() {  
  27.         return pageSize;  
  28.     }  
  29.   
  30.     public void setPageSize(int pageSize) {  
  31.         this.pageSize = pageSize;  
  32.     }  
  33.   
  34.     public int getTotalNum() {  
  35.         return totalNum;  
  36.     }  
  37.   
  38.     public void setTotalNum(int totalNum) {  
  39.         this.totalNum = totalNum;  
  40.         setTotalPage((getTotalNum() % pageSize) == 0 ? (getTotalNum() / pageSize)  
  41.                 : (getTotalNum() / pageSize + 1));  
  42.     }  
  43.   
  44.     public int getTotalPage() {  
  45.         return totalPage;  
  46.     }  
  47.   
  48.     public void setTotalPage(int totalPage) {  
  49.         this.totalPage = totalPage;  
  50.     }  
  51.   
  52.     // 获取第一页  
  53.     public int getFirstPage() {  
  54.         return 1;  
  55.     }  
  56.   
  57.     // 获取最后页  
  58.     public int getLastPage() {  
  59.         return totalPage;  
  60.     }  
  61.   
  62.     // 获取前页  
  63.     public int getPrePage() {  
  64.         if (pageNo > 1)  
  65.             return pageNo - 1;  
  66.         return 1;  
  67.     }  
  68.   
  69.     // 获取后页  
  70.     public int getBackPage() {  
  71.         if (pageNo < totalPage)  
  72.             return pageNo + 1;  
  73.         return totalPage;  
  74.     }  
  75.   
  76.     // 判断'首页'及‘前页’是否可用  
  77.     public String isPreable() {  
  78.         if (pageNo == 1)  
  79.             return "disabled";  
  80.         return "";  
  81.     }  
  82.   
  83.     // 判断'尾页'及‘下页’是否可用  
  84.     public String isBackable() {  
  85.         if (pageNo == totalPage)  
  86.             return "disabled";  
  87.         return "";  
  88.     }  
  89. }  

 

  其中使用泛型是为了能使的该分页类能进行重用,比如在查询用户时可以封装User对象、在查询财务中的流向单时可以封装流向单FlowCard类。

 

  我们以查询用户为例,用户选择查询条件,首先调用Servlet获取查询参数,然后请求业务逻辑层取得分页封装结果类。业务逻辑调用Dao层取得结果集、取得中记录数封装成分页类。最后Servlet将结果设置到jsp页面显示。

  首先来讲解Servlet,代码如下:

[java] view plain copy
  1. package kane;  
  2. import java.io.*;  
  3. import java.util.*;  
  4.   
  5. import javax.servlet.ServletConfig;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServlet;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. import kane.UserInfo;  
  12. import kane.UserInfoManage;  
  13. import kane.PageModel;  
  14.   
  15. public class UserBasicSearchServlet extends HttpServlet {  
  16.     private static final long serialVersionUID = 1L;  
  17.     private int pageSize = 0;  
  18.   
  19.     @Override  
  20.     public void init(ServletConfig config) throws ServletException {  
  21.         pageSize = Integer.parseInt(config.getInitParameter("pageSize"));  
  22.     }  
  23.   
  24.     @Override  
  25.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  26.             throws ServletException, IOException {  
  27.         doPost(req, resp);  
  28.     }  
  29.   
  30.     @Override  
  31.     protected void doPost(HttpServletRequest req, HttpServletResponse resp)  
  32.             throws ServletException, IOException {  
  33.         // 1.取得页面参数并构造参数对象  
  34.         int pageNo = Integer.parseInt(req.getParameter("pageNo"));  
  35.         String sex = req.getParameter("gender");  
  36.         String home = req.getParameter("newlocation");  
  37.         String colleage = req.getParameter("colleage");  
  38.         String comingyear = req.getParameter("ComingYear");  
  39.   
  40.         UserInfo u = new UserInfo();  
  41.         u.setSex(sex);  
  42.         u.setHome(home);  
  43.         u.setColleage(colleage);  
  44.         u.setCy(comingyear);  
  45.   
  46.         // 2.调用业务逻辑取得结果集  
  47.         UserInfoManage userInfoManage = new UserInfoManage();  
  48.         PageModel<UserInfo> pagination = userInfoManage.userBasicSearch(u,  
  49.                 pageNo, pageSize);  
  50.         List<UserInfo> userList = pagination.getList();  
  51.   
  52.         // 3.封装返回结果  
  53.         StringBuffer resultXML = new StringBuffer();  
  54.         try {  
  55.             resultXML.append("<?xml version='1.0' encoding='gb18030'?>/n");  
  56.             resultXML.append("<root>/n");  
  57.             for (Iterator<UserInfo> iterator = userList.iterator(); iterator  
  58.                     .hasNext();) {  
  59.                 UserInfo userInfo = iterator.next();  
  60.                 resultXML.append("<data>/n");  
  61.                 resultXML.append("/t<id>" + userInfo.getId() + "</id>/n");  
  62.                 resultXML.append("/t<truename>" + userInfo.getTruename()  
  63.                         + "</ truename >/n");  
  64.                 resultXML.append("/t<sex>" + userInfo.getSex() + "</sex>/n");  
  65.                 resultXML.append("/t<home>" + userInfo.getHome() + "</home>/n");  
  66.                 resultXML.append("</data>/n");  
  67.             }  
  68.             resultXML.append("<pagination>/n");  
  69.             resultXML.append("/t<total>" + pagination.getTotalPage()  
  70.                     + "</total>/n");  
  71.             resultXML.append("/t<start>" + pagination.getFirstPage()  
  72.                     + "</start>/n");  
  73.             resultXML.append("/t<end>" + pagination.getLastPage() + "</end>/n");  
  74.             resultXML.append("/t<pageno>" + pagination.getPageNo()  
  75.                     + "</pageno>/n");  
  76.             resultXML.append("</pagination>/n");  
  77.   
  78.             resultXML.append("</root>/n");  
  79.         } catch (Exception e) {  
  80.             e.printStackTrace();  
  81.         }  
  82.         writeResponse(req, resp, resultXML.toString());  
  83.   
  84.     }  
  85.   
  86.     public void writeResponse(HttpServletRequest request,  
  87.             HttpServletResponse response, String result) throws IOException {  
  88.         response.setContentType("text/xml");  
  89.         response.setHeader("Cache-Control""no-cache");  
  90.         response.setHeader("Content-Type""text/xml; charset=gb18030");  
  91.         PrintWriter pw = response.getWriter();  
  92.         pw.write(result);  
  93.         pw.close();  
  94.     }  
  95. }  

 

 

其中User对象代码如下:

[java] view plain copy
  1. package kane;  
  2. import java.util.Date;  
  3. public class UserInfo {  
  4.     private int id;  
  5.     private String username;  
  6.     private String password;  
  7.     private String truename;  
  8.     private String sex;  
  9.     private Date birthday;  
  10.     private String home;  
  11.     private String colleage;  
  12.     private String comingYear;  
  13.   
  14.     public int getId() {  
  15.         return id;  
  16.     }  
  17.   
  18.     public void setId(int id) {  
  19.         this.id = id;  
  20.     }  
  21.   
  22.     public String getUsername() {  
  23.         return username;  
  24.     }  
  25.   
  26.     public void setUsername(String username) {  
  27.         this.username = username;  
  28.     }  
  29.   
  30.     public String getPassword() {  
  31.         return password;  
  32.     }  
  33.   
  34.     public void setPassword(String password) {  
  35.         this.password = password;  
  36.     }  
  37.   
  38.     public String getTruename() {  
  39.         return truename;  
  40.     }  
  41.   
  42.     public void setTruename(String truename) {  
  43.         this.truename = truename;  
  44.     }  
  45.   
  46.     public String getSex() {  
  47.         return sex;  
  48.     }  
  49.   
  50.     public void setSex(String sex) {  
  51.         this.sex = sex;  
  52.     }  
  53.   
  54.     public Date getBirthday() {  
  55.         return birthday;  
  56.     }  
  57.   
  58.     public void setBirthday(Date birthday) {  
  59.         this.birthday = birthday;  
  60.     }  
  61.   
  62.     public String getHome() {  
  63.         return home;  
  64.     }  
  65.   
  66.     public void setHome(String home) {  
  67.         this.home = home;  
  68.     }  
  69.   
  70.     public String getColleage() {  
  71.         return colleage;  
  72.     }  
  73.   
  74.     public void setColleage(String colleage) {  
  75.         this.colleage = colleage;  
  76.     }  
  77.   
  78.     public String getCy() {  
  79.         return comingYear;  
  80.     }  
  81.   
  82.     public void setCy(String cy) {  
  83.         this. comingYear= cy;  
  84.     }  
  85. }  

 

接着是业务逻辑层代码,代码如下:

 

[java] view plain copy
  1. package kane;  
  2. import java.sql.Connection;  
  3.   
  4. import kane.DBUtility;  
  5. import kane.PageModel;  
  6.   
  7. public class UserInfoManage {  
  8.     private UserInfoDao userInfoDao = null;  
  9.   
  10.     public UserInfoManage () {  
  11.         userInfoDao = new UserInfoDao();  
  12.     }  
  13.   
  14.     public PageModel<UserInfo> userBasicSearch(UserInfo u, int pageNo,  
  15.             int pageSize) throws Exception {  
  16.         Connection connection = null;  
  17.         PageModel<UserInfo> pagination = new PageModel<UserInfo>();  
  18.         try {  
  19.             connection = DBUtility.getConnection();  
  20.             DBUtility.setAutoCommit(connection, false);  
  21.             pagination.setList(userInfoDao.getUserList(u, pageNo, pageSize));  
  22.             pagination.setPageNo(pageNo);  
  23.             pagination.setPageSize(pageSize);  
  24.             pagination.setTotalNum(userInfoDao.getTotalNum(u));  
  25.             DBUtility.commit(connection);  
  26.         } catch (Exception e) {  
  27.             DBUtility.rollBack(connection);  
  28.             e.printStackTrace();  
  29.             throw new Exception();  
  30.         } finally {  
  31.             DBUtility.closeConnection();  
  32.         }  
  33.         return pagination;  
  34.     }  
  35. }  

其中DBUtility为数据库的连接封装类。

最后是Dao层代码实现,代码如下:

 

[java] view plain copy
  1. package kane;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.PreparedStatement;  
  5. import java.sql.ResultSet;  
  6. import java.sql.SQLException;  
  7. import java.util.ArrayList;  
  8. import java.util.List;  
  9.   
  10. import kane.UserInfo;  
  11. import kane.DBUtility;  
  12.   
  13. public class UserInfoDao {  
  14.   
  15.     public List<UserInfo> getUserList(UserInfo userInfo, int pageNo,  
  16.             int pageSize) throws Exception {  
  17.         PreparedStatement pstmt = null;  
  18.         ResultSet rs = null;  
  19.         List<UserInfo> userList = null;  
  20.         try {  
  21.             String sql = "select * from(select rownum num,u.* from(select * from user_info where sex = ? and home like '"  
  22.                     + userInfo.getHome()  
  23.                     + "%"  
  24.                     + "' and colleage like '"  
  25.                     + userInfo.getColleage()  
  26.                     + "%"  
  27.                     + "' and comingyear like '"  
  28.                     + userInfo.getCy()  
  29.                     + "%"  
  30.                     + "' order by id) u where rownum<=?) where num>=?";  
  31.             userList = new ArrayList<UserInfo>();  
  32.             Connection conn = DBUtility.getConnection();  
  33.             pstmt = conn.prepareStatement(sql);  
  34.             pstmt.setString(1, userInfo.getSex());  
  35.             pstmt.setInt(2, pageNo * pageSize);  
  36.             pstmt.setInt(3, (pageNo - 1) * pageSize + 1);  
  37.             rs = pstmt.executeQuery();  
  38.             while (rs.next()) {  
  39.                 UserInfo user = new UserInfo();  
  40.                 user.setId(rs.getInt("id"));  
  41.                 user.setTruename(rs.getString("truename"));  
  42.                 user.setSex(rs.getString("sex"));  
  43.                 user.setHome(rs.getString("home"));  
  44.                 userList.add(user);  
  45.             }  
  46.         } catch (SQLException e) {  
  47.             e.printStackTrace();  
  48.             throw new Exception(e);  
  49.         } finally {  
  50.             DBUtility.closeResultSet(rs);  
  51.             DBUtility.closePreparedStatement(pstmt);  
  52.         }  
  53.         return userList;  
  54.     }  
  55.   
  56.     public int getTotalNum(UserInfo userInfo) throws Exception {  
  57.         PreparedStatement pstmt = null;  
  58.         ResultSet rs = null;  
  59.         int count = 0;  
  60.         try {  
  61.             String sql = "select count(*) from user_info where sex=? and home like '"  
  62.                     + userInfo.getHome()  
  63.                     + "%"  
  64.                     + "' and colleage like '"  
  65.                     + userInfo.getColleage()  
  66.                     + "%"  
  67.                     + "' and comingyear like '"  
  68.                     + userInfo.getCy()+ "%" + "'";  
  69.             Connection conn = DBUtility.getConnection();  
  70.             pstmt = conn.prepareStatement(sql);  
  71.             pstmt.setString(1, userInfo.getSex());  
  72.             rs = pstmt.executeQuery();  
  73.             if (rs.next()) {  
  74.                 count = rs.getInt(1);  
  75.             }  
  76.         } catch (SQLException e) {  
  77.             e.printStackTrace();  
  78.             throw new Exception(e);  
  79.         } finally {  
  80.             DBUtility.closeResultSet(rs);  
  81.             DBUtility.closePreparedStatement(pstmt);  
  82.         }  
  83.         return count;  
  84.     }  
  85. }  

 

最后就是servlet将得到的结果返回给jsp页面显示出来。

注:其中DBUtility代码是封装数据库连接操作的代码,如下:

[java] view plain copy
  1. package kane;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.DriverManager;  
  5. import java.sql.PreparedStatement;  
  6. import java.sql.ResultSet;  
  7. import java.sql.SQLException;  
  8.   
  9. public class DBUtility {  
  10.     private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();  
  11.   
  12.     public static Connection getConnection() {  
  13.         Connection conn = null;  
  14.         conn = threadLocal.get();  
  15.         if (conn == null) {  
  16.             try {  
  17.                 Class.forName("oracle.jdbc.driver.OracleDriver");  
  18.                 conn = DriverManager.getConnection(  
  19.                         "jdbc:oracle:thin:@localhost:1521:oracle""admin",  
  20.                         "admin");  
  21.                 threadLocal.set(conn);  
  22.             } catch (ClassNotFoundException e) {  
  23.                 e.printStackTrace();  
  24.             } catch (SQLException e) {  
  25.                 e.printStackTrace();  
  26.             }  
  27.         }  
  28.         return conn;  
  29.     }  
  30.   
  31.     // 封装设置Connection自动提交  
  32.     public static void setAutoCommit(Connection conn, Boolean flag) {  
  33.         try {  
  34.             conn.setAutoCommit(flag);  
  35.         } catch (SQLException e) {  
  36.             e.printStackTrace();  
  37.         }  
  38.     }  
  39.   
  40.     // 设置事务提交  
  41.     public static void commit(Connection conn) {  
  42.         try {  
  43.             conn.commit();  
  44.         } catch (SQLException e) {  
  45.             e.printStackTrace();  
  46.         }  
  47.     }  
  48.   
  49.     // 封装设置Connection回滚  
  50.     public static void rollBack(Connection conn) {  
  51.         try {  
  52.             conn.rollback();  
  53.         } catch (SQLException e) {  
  54.             e.printStackTrace();  
  55.         }  
  56.     }  
  57.   
  58.     // 封装关闭Connection、PreparedStatement、ResultSet的函数  
  59.     public static void closeConnection() {  
  60.         Connection conn = threadLocal.get();  
  61.         try {  
  62.             if (conn != null) {  
  63.                 conn.close();  
  64.                 conn = null;  
  65.                 threadLocal.remove();  
  66.             }  
  67.         } catch (SQLException e) {  
  68.             e.printStackTrace();  
  69.         }  
  70.   
  71.     }  
  72.   
  73.     public static void closePreparedStatement(PreparedStatement pstmt) {  
  74.         try {  
  75.             if (pstmt != null) {  
  76.                 pstmt.close();  
  77.                 pstmt = null;  
  78.             }  
  79.         } catch (SQLException e) {  
  80.             e.printStackTrace();  
  81.         }  
  82.     }  
  83.   
  84.     public static void closeResultSet(ResultSet rs) {  
  85.         try {  
  86.             if (rs != null) {  
  87.                 rs.close();  
  88.                 rs = null;  
  89.             }  
  90.         } catch (SQLException e) {  
  91.             e.printStackTrace();  
  92.         }  
  93.     }  
  94. }  

 

使用ThreadLocal是为了保证事务的一致,使得同一个线程的所有数据库操作使用同一个Connection。

到此一个简单的代码实现就完成了。

原创粉丝点击