JavaWeb分頁技術總結
阿新 • • 發佈:2019-01-07
分頁技術:將所有資料分段展示給使用者的技術。
分頁的意義:增加系統的複雜度,另外可以將大量的資料限制在某一個特定的範圍。
選擇分頁的標準: 首先,判斷的標準是速度,顯而易見,資料庫伺服器,Web應用伺服器和客戶端之間是網路,如果網路傳遞的資料量越少,則客戶端獲得響應的速度越快。一般來說,資料庫伺服器和Web應用伺服器的處理能力一般比客戶端要強很多.從這兩點來看,在客戶端分頁的方案是最不可取的。
其次,在Web伺服器端分頁和在資料庫端分頁,如果選擇在Web伺服器端分頁的話,大部分的被過濾掉的資料還是被傳輸到了Web應用伺服器端,與其這樣還不如直接在資料庫端進行分頁。
因此比較好的分頁做法應該是每次翻頁的時候只從資料庫裡檢索頁面大小的塊區的資料。
雖然每次翻頁都需要查詢資料庫,但查詢出的記錄數很少,網路傳輸資料量不大,如果使用連線池更可以略過最耗時的建立資料庫連線過程。而在資料庫端有各種成熟的優化技術用於提高查詢速度,比在應用伺服器層做快取有效得多。
Web伺服器端分頁和在資料庫端分頁:
資料庫端分頁:通過JDBC的方式訪問資料庫,根據資料庫型別採取不同的SQL分頁語句。
對於MySql資料庫:採用limit m,n語句進行分頁,需要指定m和n的2個值
Limit後的兩個引數中,引數m是起始下標[頁碼],它從0開始;引數n是返回的記錄數。
SQL語句形式:
語句1: select * from 表名 limit m,n; --返回表中m-n行的資料
語句2: select * from 表名 limit m offset n; --從n行開始到返回表中m行的資料
假設 numberpage 表示每頁要顯示的條數,pagenumber表示頁碼:
語句3:select * from 表名 limit (pagenumber-1)*numberpage,numberpage;
語句4:select * from 表名 limit numberpage offset(pagenumber-1)*numberpage;
對於Oracle資料庫:採用rownum的方式進行分頁,rownum表示一條記錄的行號,注意Oracle獲取每一行後才賦予.因此,指定rownum區間來取得分頁資料在一層查詢語句中是無法做到的,要分頁還要進行一次查詢。
SQL形式:
select * from (
select page.*,rownum rn
from (select * from 表名) page
where rownum <= (?-1)*?+?)
where rn > (?-1)*?;
--其中page是將表中的資料查詢出來取名為page
另外,不論使用哪種資料庫,都的想知道資料中有幾條資料,自然需要一個獲取總行的SQL:
SQL形式:
select count(*) from 表名;
首先:實現分頁的具體實現需要結合JDBC和Java程式碼實現:
分頁的時,返回的引數包括查詢的結果集(List),總的頁數(pageCount)、當前第幾頁(pageNo)等等資訊,所以我們封裝一個查詢結果Page類,當然還需要分頁的一個實體類,這裡我以Entity為例,具體程式碼:
Page.java:
//第一種實現方式:
import java.util.List;
import entity.Entity;
public class Page {
private int pageNo;//當前頁數
private int hangCount;//每頁顯示的行數
private int sumCount;//總條數
private int sumPage;//總頁數
private List<Entity> entitys;//需要生成setXX()和getXX()方法
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
//給當前頁賦值
if (pageNo<=1) {
this.pageNo=1;
}else if (pageNo>=this.sumPage) {
this.pageNo=this.sumPage;
}else {
this.pageNo = pageNo;
}
}
public int getHangCount() {
return hangCount;
}
public void setHangCount(int hangCount) {
this.hangCount = hangCount;
}
public int getSumCount() {
return sumCount;
}
public void setSumCount(int sumCount) {
this.sumCount = sumCount;
if(this.sumCount%this.hangCount==0){
this.sumPage = this.sumCount/this.hangCount;
}
else{
this.sumPage = this.sumCount/this.hangCount+1;
}
}
public int getSumPage() {
return sumPage;
}
public void setSumPage(int sumPage) {
this.sumPage = sumPage;
}
//List<Entity> entitys 生成的setXX()和getXX()方法
}
//第二種實現方式:
import java.util.List;
import entity.Entity;
public class Page {
private int pageNo;//當前頁數
private int hangCount;//每頁顯示的行數
private int sumCount;//總條數
private int sumPage;//總頁數
private List<Entity> entitys;//需要生成setXX()和getXX()方法
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public int getHangCount() {
return hangCount;
}
public void setHangCount(int hangCount) {
this.hangCount = hangCount;
}
public int getSumCount() {
return sumCount;
}
public void setSumCount(int sumCount) {
this.sumCount = sumCount;
setSumPage((getSumCount()%hangCount)==0?(getSumCount()/hangCount):(getTotalNum() /hangCount+1));
}
public int getSumPage() {
return sumPage;
}
public void setSumPage(int sumPage) {
this.sumPage = sumPage;
}
// 獲取首頁
public int getFirstPage() {
return 1;
}
// 獲取末頁
public int getLastPage() {
return sumPage;
}
// 獲取上一頁
public int getPrePage() {
if (pageNo > 1)
return pageNo - 1;
return 1;
}
// 獲取下一頁
public int getBackPage() {
if (pageNo<sumPage)
return pageNo + 1;
return sumPage;
}
// 判斷'首頁'及‘上一頁’是否可用
public String isPreable() {
if (pageNo == 1)
return "disabled";
return "";
}
// 判斷'尾頁'及‘下一頁’是否可用
public String isBackable() {
if (pageNo == totalPage)
return "disabled";
return "";
}
//List<Entity> entitys 生成的setXX()和getXX()方法
}
其次:編寫資料資料連線類,以BaseDao為例,具體程式碼:
資料庫驅動類名:oracle.jdbc.driver.OracleDriver
資料庫連線URL:jdbc:oracle:thin:@localhost:1521:連線名
資料庫使用者名稱和密碼:userName,passWord
//BaseDao.java
第一種方式:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BaseDao{
//使用ThreadLocal是為了保證事務的一致,使得同一個執行緒的所有資料庫操作使用同一個Connection
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
public static Connection getConnection() {
Connection conn = null;
conn = threadLocal.get();
if (conn == null) {
try {
Class.forName("資料庫驅動類名");
conn = DriverManager.getConnection(
"資料庫連線URL", "使用者名稱","密碼");
threadLocal.set(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
return conn;
}
// 封裝設定Connection自動提交
public static void setAutoCommit(Connection conn, Boolean flag) {
try {
conn.setAutoCommit(flag);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 設定事務提交
public static void commit(Connection conn) {
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 封裝設定Connection回滾
public static void rollBack(Connection conn) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 封裝關閉Connection、PreparedStatement、ResultSet的函式
public static void closeConnection() {
Connection conn = threadLocal.get();
try {
if (conn != null) {
conn.close();
conn = null;
threadLocal.remove();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//關閉PreparedStatement
public static void closePreparedStatement(PreparedStatement pstmt) {
try {
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//關閉ResultSet
public static void closeResultSet(ResultSet rs) {
try {
if (rs != null) {
rs.close();
rs = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//公共的增刪改方法
public int allUpdateAndAddAndDel(List<Object> list,String sql){
try {
conn=getConnection();
ps=conn.prepareStatement(sql);
if(list.size()>0){
for (int i = 0; i < list.size(); i++) {
ps.setObject((i+1), list.get(i));
}
}
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
return -1;
}
finally{
closeAll();
}
}
//查詢公共方法
public ResultSet select(String sql,List<Object> list) {
try {
conn=getConnection();
ps=conn.prepareStatement(sql);
if (list.size()>0) {
for (int i = 0; i < list.size(); i++) {
ps.setObject((i+1), list.get(i));
}
}
rs=ps.executeQuery();
return rs;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
第二種方式:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
public class BaseDao {
private String name="使用者名稱";
private String pwd="密碼";
private String drivername="資料庫驅動名";
private String url="資料庫連線URL";
public Connection conn = null;
public PreparedStatement ps = null;
public ResultSet rs = null;
/**
* 關閉所有介面物件的方法
*/
public void closeAll(){
try {
if(rs!=null)rs.close();
if(ps!=null)ps.close();
if(conn!=null)conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取連線物件的方法
*/
public Connection getConnection(){
try {
Class.forName(drivername);
conn = DriverManager.getConnection(url, name, pwd);
return conn;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// 封裝設定Connection自動提交
public static void setAutoCommit(Connection conn, Boolean flag) {
try {
conn.setAutoCommit(flag);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 設定事務提交
public static void commit(Connection conn) {
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 封裝設定Connection回滾
public static void rollBack(Connection conn) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 封裝關閉Connection、PreparedStatement、ResultSet的函式
public static void closeConnection() {
Connection conn = threadLocal.get();
try {
if (conn != null) {
conn.close();
conn = null;
threadLocal.remove();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//公共的增刪改方法
public int allUpdateAndAddAndDel(List<Object> list,String sql){
try {
conn=getConnection();
ps=conn.prepareStatement(sql);
if(list.size()>0){
for (int i = 0; i < list.size(); i++) {
ps.setObject((i+1), list.get(i));
}
}
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
return -1;
}
finally{
closeAll();
}
}
//查詢公共方法
public ResultSet select(String sql,List<Object> list) {
try {
conn=getConnection();
ps=conn.prepareStatement(sql);
if (list.size()>0) {
for (int i = 0; i < list.size(); i++) {
ps.setObject((i+1), list.get(i));
}
}
rs=ps.executeQuery();
return rs;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
利用Jsp/Servlet實現:
以實體類User為例,需要UserInfo.java:
//UserInfo.java
import java.util.Date;
public class UserInfo {
private int id;
private String username;
private String password;
private String truename;
private String sex;
private Date birthday;
private String home;
private String colleage;
private String comingYear;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTruename() {
return truename;
}
public void setTruename(String truename) {
this.truename = truename;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getHome() {
return home;
}
public void setHome(String home) {
this.home = home;
}
public String getColleage() {
return colleage;
}
public void setColleage(String colleage) {
this.colleage = colleage;
}
public String getCy() {
return comingYear;
}
public void setCy(String cy) {
this. comingYear= cy;
}
}
在dao層實現:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import entity.UserInfo;
import entity.BaseDao;
public class UserInfoDao {
public List<UserInfo> getUserList(UserInfo userInfo, int pageNo,
int hangCount ) throws Exception {
PreparedStatement pstmt = null;
ResultSet rs = null;
List<UserInfo> userList = null;
try {
String sql = "select * from(select rownum num,u.* from(select * from user_info where sex = ? and home like '"
+ userInfo.getHome()
+ "%"
+ "' and colleage like '"
+ userInfo.getColleage()
+ "%"
+ "' and comingyear like '"
+ userInfo.getCy()
+ "%"
+ "' order by id) u where rownum<=?) where num>=?";
userList = new ArrayList<UserInfo>();
Connection conn = BaseDao.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userInfo.getSex());
pstmt.setInt(2, pageNo * hangCount);
pstmt.setInt(3, (pageNo - 1) * hangCount + 1);
rs = pstmt.executeQuery();
while (rs.next()) {
UserInfo user = new UserInfo();
user.setId(rs.getInt("id"));
user.setTruename(rs.getString("truename"));
user.setSex(rs.getString("sex"));
user.setHome(rs.getString("home"));
userList.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
throw new Exception(e);
} finally {
BaseDao.closeResultSet(rs);
BaseDao.closePreparedStatement(pstmt);
}
return userList;
}
public int getTotalNum(UserInfo userInfo) throws Exception {
PreparedStatement pstmt = null;
ResultSet rs = null;
int count = 0;
try {
String sql = "select count(*) from user_info where sex=? and home like '"
+ userInfo.getHome()
+ "%"
+ "' and colleage like '"
+ userInfo.getColleage()
+ "%"
+ "' and comingyear like '"
+ userInfo.getCy()+ "%" + "'";
Connection conn = BaseDao.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userInfo.getSex());
rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
throw new Exception(e);
} finally {
BaseDao.closeResultSet(rs);
BaseDao.closePreparedStatement(pstmt);
}
return count;
}
}
在service層:
import java.sql.Connection;
import util.BaseDao;
import util.Page;
public class UserInfoManage {
private UserInfoDao userInfoDao = null;
public UserInfoManage () {
userInfoDao = new UserInfoDao();
}
public Page userBasicSearch(UserInfo u, int pageNo,
int hangCount) throws Exception {
Connection connection = null;
Page pagination = new Page();
try {
connection = BaseDao.getConnection();
DBUtility.setAutoCommit(connection, false);
pagination.setList(userInfoDao.getUserList(u, pageNo, hangCount));
pagination.setPageNo(pageNo);
pagination.setHangCount(hangCount);
pagination.setSumCount(userInfoDao.getTotalNum(u));
BaseDao.commit(connection);
} catch (Exception e) {
DBUtility.rollBack(connection);
e.printStackTrace();
throw new Exception();
} finally {
BaseDao.closeConnection();
}
return pagination;
}
}
在Servlet:
import java.io.*;
import java.util.*;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import entity.UserInfo;
import service.UserInfoManage;
import util.Page;
public class UserBasicSearchServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private int hangCount = 0;
@Override
public void init(ServletConfig config) throws ServletException {
hangCount = Integer.parseInt(config.getInitParameter("hangCount"));
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1.取得頁面引數並構造引數物件
int pageNo = Integer.parseInt(req.getParameter("pageNo"));
String sex = req.getParameter("gender");
String home = req.getParameter("newlocation");
String colleage = req.getParameter("colleage");
String comingyear = req.getParameter("ComingYear");
UserInfo u = new UserInfo();
u.setSex(sex);
u.setHome(home);
u.setColleage(colleage);
u.setCy(comingyear);
// 2.呼叫業務邏輯取得結果集
UserInfoManage userInfoManage = new UserInfoManage();
PageModel<UserInfo> pagination = userInfoManage.userBasicSearch(u,
pageNo, pageSize);
List<UserInfo> userList = pagination.getList();
// 3.封裝返回結果
StringBuffer resultXML = new StringBuffer();
try {
resultXML.append("<?xml version='1.0' encoding='gb18030'?>/n");
resultXML.append("<root>/n");
for (Iterator<UserInfo> iterator = userList.iterator(); iterator
.hasNext();) {
UserInfo userInfo = iterator.next();
resultXML.append("<data>/n");
resultXML.append("/t<id>" + userInfo.getId() + "</id>/n");
resultXML.append("/t<truename>" + userInfo.getTruename()
+ "</ truename >/n");
resultXML.append("/t<sex>" + userInfo.getSex() + "</sex>/n");
resultXML.append("/t<home>" + userInfo.getHome() + "</home>/n");
resultXML.append("</data>/n");
}
resultXML.append("<pagination>/n");
resultXML.append("/t<total>" + pagination.getTotalPage()
+ "</total>/n");
resultXML.append("/t<start>" + pagination.getFirstPage()
+ "</start>/n");
resultXML.append("/t<end>" + pagination.getLastPage() + "</end>/n");
resultXML.append("/t<pageno>" + pagination.getPageNo()
+ "</pageno>/n");
resultXML.append("</pagination>/n");
resultXML.append("</root>/n");
} catch (Exception e) {
e.printStackTrace();
}
writeResponse(req, resp, resultXML.toString());
}
public void writeResponse(HttpServletRequest request,
HttpServletResponse response, String result) throws IOException {
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-Type", "text/xml; charset=gb18030");
PrintWriter pw = response.getWriter();
pw.write(result);
pw.close();
}
}
利用SSH實現:
在dao層編寫getSumCount()和List<Student> getStuByPage(Integer pageNo, Integer pageCount)2個方法:
有2種方法:
第一種:使用普通的分頁方法
//實現獲取總行數的方法
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Query;
private BaseUtil baseUtil;//需要生成setXX()和getXX()方法
public Integer getSumCount() {
//獲取session
Session session = baseUtil.getHibernateTemplate().getSessionFactory().openSession();
//執行查詢,呼叫查詢結果唯一的uniqueResult()方法;
Object object =session.createQuery("select count(別名.id) from 類名 別名 ").uniqueResult();
//根據資料型別確定返回值,型別不對時需要強制轉換
return Integer.valueOf(object.toString());
}
//實現分頁的方法
public List<Entity> getEntityByPage(Integer pageNo, Integer pageCount) {
Session session = baseUtil.getHibernateTemplate().getSessionFactory().openSession();
Query query = session.createQuery("from 類名 別名 ");
query.setMaxResults(pageCount);
return query.setFirstResult((pageNo-1)*pageCount).list();
}
第二種:使用Spring框架提供的方法
import org.hibernate.HibernateException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.hibernate.Query;
//實現獲取總行數的方法
public Integer getSumCount() {
Object obj = baseUtil.getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session){
Query query = session.createQuery("select count(別名.id) from 類名 別名 ");
Object object = query.uniqueResult();
return object;
}
});
return Integer.valueOf(obj.toString());
}
//實現分頁的方法
getEntityByPage(final Integer pageNo, final Integer pageCount):方法內的變數必須是final
public List<Entity> getEntityByPage(final Integer pageNo, final Integer pageCount) {
List<Entity> entitys = baseUtil.getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session){
Query query = session.createQuery("from 類名 別名");
query.setMaxResults(pageCount);
query.setFirstResult((pageNo-1)*pageCount);
return query.list();
}
});
return entitys ;
}
在service層中:
//EntityService.java
private Page page;//需要生成setXX()和getXX()方法
private Integer pageNo=1;
private Integer pageCount=1;
public Page getEntityByPage(Integer pageNo, Integer pageCount) {
if(page==null){
page=new Page();
}
page.setHangCount(pageCount);
page.setSumCount(stuDao.getSumCount());
page.setPageNo(pageNo);
page.setEntitys(stuDao.getEntityByPage(page.getPageNo(), page.getHangCount()));
return page;
}
在action層中:
//EntityAction.java
import service.EntityService;
import util.Page;
import com.opensymphony.xwork2.ActionSupport;
public class EntityAction extends ActionSupport {
private EntityService EntityService;//需要生成setXX()方法
private Page page;//當前頁,需要生成setXX()和getXX()方法
private Integer pageNo=1;//當前頁數,需要生成setXX()和getXX()方法
private Integer pageCount=2;//每頁顯示行數,需要生成setXX()和getXX()方法
@SuppressWarnings("unchecked")
@Override
public String execute() throws Exception {
page=entityService.getEntityByPage(pageNo, pageCount);
return SUCCESS;
}
最後在jsp頁面:
<div class=pager>
<ul>
<li class=current><a href="form表單action名?pageNo=1">首頁</a></li>
<li><a href="form表單action名?pageNo=${page.pageNo-1}">上一頁</a></li>
<li><a href="form表單action名?pageNo=${page.pageNo+1}">下一頁</a></li>
<li><a href="form表單action名?pageNo=${page.sumPage}">末頁</a></li>
</ul>
</DIV>
綜上所述,分頁功能可以基本實現。
文責宣告:本人借鑑得有別的作者的程式碼,本人初探JavaWeb,技術有限,還望各位多多指正批評。如果文中有涉及之外的事情,還望見諒!
分頁的意義:增加系統的複雜度,另外可以將大量的資料限制在某一個特定的範圍。
選擇分頁的標準: 首先,判斷的標準是速度,顯而易見,資料庫伺服器,Web應用伺服器和客戶端之間是網路,如果網路傳遞的資料量越少,則客戶端獲得響應的速度越快。一般來說,資料庫伺服器和Web應用伺服器的處理能力一般比客戶端要強很多.從這兩點來看,在客戶端分頁的方案是最不可取的。
其次,在Web伺服器端分頁和在資料庫端分頁,如果選擇在Web伺服器端分頁的話,大部分的被過濾掉的資料還是被傳輸到了Web應用伺服器端,與其這樣還不如直接在資料庫端進行分頁。
因此比較好的分頁做法應該是每次翻頁的時候只從資料庫裡檢索頁面大小的塊區的資料。
雖然每次翻頁都需要查詢資料庫,但查詢出的記錄數很少,網路傳輸資料量不大,如果使用連線池更可以略過最耗時的建立資料庫連線過程。而在資料庫端有各種成熟的優化技術用於提高查詢速度,比在應用伺服器層做快取有效得多。
Web伺服器端分頁和在資料庫端分頁:
資料庫端分頁:通過JDBC的方式訪問資料庫,根據資料庫型別採取不同的SQL分頁語句。
對於MySql資料庫:採用limit m,n語句進行分頁,需要指定m和n的2個值
Limit後的兩個引數中,引數m是起始下標[頁碼],它從0開始;引數n是返回的記錄數。
SQL語句形式:
語句1: select * from 表名 limit m,n; --返回表中m-n行的資料
語句2: select * from 表名 limit m offset n; --從n行開始到返回表中m行的資料
假設 numberpage 表示每頁要顯示的條數,pagenumber表示頁碼:
語句3:select * from 表名 limit (pagenumber-1)*numberpage,numberpage;
語句4:select * from 表名 limit numberpage offset(pagenumber-1)*numberpage;
對於Oracle資料庫:採用rownum的方式進行分頁,rownum表示一條記錄的行號,注意Oracle獲取每一行後才賦予.因此,指定rownum區間來取得分頁資料在一層查詢語句中是無法做到的,要分頁還要進行一次查詢。
SQL形式:
select * from (
select page.*,rownum rn
from (select * from 表名) page
where rownum <= (?-1)*?+?)
where rn > (?-1)*?;
--其中page是將表中的資料查詢出來取名為page
另外,不論使用哪種資料庫,都的想知道資料中有幾條資料,自然需要一個獲取總行的SQL:
SQL形式:
select count(*) from 表名;
首先:實現分頁的具體實現需要結合JDBC和Java程式碼實現:
分頁的時,返回的引數包括查詢的結果集(List),總的頁數(pageCount)、當前第幾頁(pageNo)等等資訊,所以我們封裝一個查詢結果Page類,當然還需要分頁的一個實體類,這裡我以Entity為例,具體程式碼:
Page.java:
//第一種實現方式:
import java.util.List;
import entity.Entity;
public class Page {
private int pageNo;//當前頁數
private int hangCount;//每頁顯示的行數
private int sumCount;//總條數
private int sumPage;//總頁數
private List<Entity> entitys;//需要生成setXX()和getXX()方法
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
//給當前頁賦值
if (pageNo<=1) {
this.pageNo=1;
}else if (pageNo>=this.sumPage) {
this.pageNo=this.sumPage;
}else {
this.pageNo = pageNo;
}
}
public int getHangCount() {
return hangCount;
}
public void setHangCount(int hangCount) {
this.hangCount = hangCount;
}
public int getSumCount() {
return sumCount;
}
public void setSumCount(int sumCount) {
this.sumCount = sumCount;
if(this.sumCount%this.hangCount==0){
this.sumPage = this.sumCount/this.hangCount;
}
else{
this.sumPage = this.sumCount/this.hangCount+1;
}
}
public int getSumPage() {
return sumPage;
}
public void setSumPage(int sumPage) {
this.sumPage = sumPage;
}
//List<Entity> entitys 生成的setXX()和getXX()方法
}
//第二種實現方式:
import java.util.List;
import entity.Entity;
public class Page {
private int pageNo;//當前頁數
private int hangCount;//每頁顯示的行數
private int sumCount;//總條數
private int sumPage;//總頁數
private List<Entity> entitys;//需要生成setXX()和getXX()方法
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public int getHangCount() {
return hangCount;
}
public void setHangCount(int hangCount) {
this.hangCount = hangCount;
}
public int getSumCount() {
return sumCount;
}
public void setSumCount(int sumCount) {
this.sumCount = sumCount;
setSumPage((getSumCount()%hangCount)==0?(getSumCount()/hangCount):(getTotalNum() /hangCount+1));
}
public int getSumPage() {
return sumPage;
}
public void setSumPage(int sumPage) {
this.sumPage = sumPage;
}
// 獲取首頁
public int getFirstPage() {
return 1;
}
// 獲取末頁
public int getLastPage() {
return sumPage;
}
// 獲取上一頁
public int getPrePage() {
if (pageNo > 1)
return pageNo - 1;
return 1;
}
// 獲取下一頁
public int getBackPage() {
if (pageNo<sumPage)
return pageNo + 1;
return sumPage;
}
// 判斷'首頁'及‘上一頁’是否可用
public String isPreable() {
if (pageNo == 1)
return "disabled";
return "";
}
// 判斷'尾頁'及‘下一頁’是否可用
public String isBackable() {
if (pageNo == totalPage)
return "disabled";
return "";
}
//List<Entity> entitys 生成的setXX()和getXX()方法
}
其次:編寫資料資料連線類,以BaseDao為例,具體程式碼:
資料庫驅動類名:oracle.jdbc.driver.OracleDriver
資料庫連線URL:jdbc:oracle:thin:@localhost:1521:連線名
資料庫使用者名稱和密碼:userName,passWord
//BaseDao.java
第一種方式:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BaseDao{
//使用ThreadLocal是為了保證事務的一致,使得同一個執行緒的所有資料庫操作使用同一個Connection
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
public static Connection getConnection() {
Connection conn = null;
conn = threadLocal.get();
if (conn == null) {
try {
Class.forName("資料庫驅動類名");
conn = DriverManager.getConnection(
"資料庫連線URL", "使用者名稱","密碼");
threadLocal.set(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
return conn;
}
// 封裝設定Connection自動提交
public static void setAutoCommit(Connection conn, Boolean flag) {
try {
conn.setAutoCommit(flag);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 設定事務提交
public static void commit(Connection conn) {
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 封裝設定Connection回滾
public static void rollBack(Connection conn) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 封裝關閉Connection、PreparedStatement、ResultSet的函式
public static void closeConnection() {
Connection conn = threadLocal.get();
try {
if (conn != null) {
conn.close();
conn = null;
threadLocal.remove();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//關閉PreparedStatement
public static void closePreparedStatement(PreparedStatement pstmt) {
try {
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//關閉ResultSet
public static void closeResultSet(ResultSet rs) {
try {
if (rs != null) {
rs.close();
rs = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//公共的增刪改方法
public int allUpdateAndAddAndDel(List<Object> list,String sql){
try {
conn=getConnection();
ps=conn.prepareStatement(sql);
if(list.size()>0){
for (int i = 0; i < list.size(); i++) {
ps.setObject((i+1), list.get(i));
}
}
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
return -1;
}
finally{
closeAll();
}
}
//查詢公共方法
public ResultSet select(String sql,List<Object> list) {
try {
conn=getConnection();
ps=conn.prepareStatement(sql);
if (list.size()>0) {
for (int i = 0; i < list.size(); i++) {
ps.setObject((i+1), list.get(i));
}
}
rs=ps.executeQuery();
return rs;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
第二種方式:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
public class BaseDao {
private String name="使用者名稱";
private String pwd="密碼";
private String drivername="資料庫驅動名";
private String url="資料庫連線URL";
public Connection conn = null;
public PreparedStatement ps = null;
public ResultSet rs = null;
/**
* 關閉所有介面物件的方法
*/
public void closeAll(){
try {
if(rs!=null)rs.close();
if(ps!=null)ps.close();
if(conn!=null)conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取連線物件的方法
*/
public Connection getConnection(){
try {
Class.forName(drivername);
conn = DriverManager.getConnection(url, name, pwd);
return conn;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// 封裝設定Connection自動提交
public static void setAutoCommit(Connection conn, Boolean flag) {
try {
conn.setAutoCommit(flag);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 設定事務提交
public static void commit(Connection conn) {
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 封裝設定Connection回滾
public static void rollBack(Connection conn) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 封裝關閉Connection、PreparedStatement、ResultSet的函式
public static void closeConnection() {
Connection conn = threadLocal.get();
try {
if (conn != null) {
conn.close();
conn = null;
threadLocal.remove();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//公共的增刪改方法
public int allUpdateAndAddAndDel(List<Object> list,String sql){
try {
conn=getConnection();
ps=conn.prepareStatement(sql);
if(list.size()>0){
for (int i = 0; i < list.size(); i++) {
ps.setObject((i+1), list.get(i));
}
}
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
return -1;
}
finally{
closeAll();
}
}
//查詢公共方法
public ResultSet select(String sql,List<Object> list) {
try {
conn=getConnection();
ps=conn.prepareStatement(sql);
if (list.size()>0) {
for (int i = 0; i < list.size(); i++) {
ps.setObject((i+1), list.get(i));
}
}
rs=ps.executeQuery();
return rs;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
利用Jsp/Servlet實現:
以實體類User為例,需要UserInfo.java:
//UserInfo.java
import java.util.Date;
public class UserInfo {
private int id;
private String username;
private String password;
private String truename;
private String sex;
private Date birthday;
private String home;
private String colleage;
private String comingYear;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTruename() {
return truename;
}
public void setTruename(String truename) {
this.truename = truename;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getHome() {
return home;
}
public void setHome(String home) {
this.home = home;
}
public String getColleage() {
return colleage;
}
public void setColleage(String colleage) {
this.colleage = colleage;
}
public String getCy() {
return comingYear;
}
public void setCy(String cy) {
this. comingYear= cy;
}
}
在dao層實現:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import entity.UserInfo;
import entity.BaseDao;
public class UserInfoDao {
public List<UserInfo> getUserList(UserInfo userInfo, int pageNo,
int hangCount ) throws Exception {
PreparedStatement pstmt = null;
ResultSet rs = null;
List<UserInfo> userList = null;
try {
String sql = "select * from(select rownum num,u.* from(select * from user_info where sex = ? and home like '"
+ userInfo.getHome()
+ "%"
+ "' and colleage like '"
+ userInfo.getColleage()
+ "%"
+ "' and comingyear like '"
+ userInfo.getCy()
+ "%"
+ "' order by id) u where rownum<=?) where num>=?";
userList = new ArrayList<UserInfo>();
Connection conn = BaseDao.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userInfo.getSex());
pstmt.setInt(2, pageNo * hangCount);
pstmt.setInt(3, (pageNo - 1) * hangCount + 1);
rs = pstmt.executeQuery();
while (rs.next()) {
UserInfo user = new UserInfo();
user.setId(rs.getInt("id"));
user.setTruename(rs.getString("truename"));
user.setSex(rs.getString("sex"));
user.setHome(rs.getString("home"));
userList.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
throw new Exception(e);
} finally {
BaseDao.closeResultSet(rs);
BaseDao.closePreparedStatement(pstmt);
}
return userList;
}
public int getTotalNum(UserInfo userInfo) throws Exception {
PreparedStatement pstmt = null;
ResultSet rs = null;
int count = 0;
try {
String sql = "select count(*) from user_info where sex=? and home like '"
+ userInfo.getHome()
+ "%"
+ "' and colleage like '"
+ userInfo.getColleage()
+ "%"
+ "' and comingyear like '"
+ userInfo.getCy()+ "%" + "'";
Connection conn = BaseDao.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userInfo.getSex());
rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
throw new Exception(e);
} finally {
BaseDao.closeResultSet(rs);
BaseDao.closePreparedStatement(pstmt);
}
return count;
}
}
在service層:
import java.sql.Connection;
import util.BaseDao;
import util.Page;
public class UserInfoManage {
private UserInfoDao userInfoDao = null;
public UserInfoManage () {
userInfoDao = new UserInfoDao();
}
public Page userBasicSearch(UserInfo u, int pageNo,
int hangCount) throws Exception {
Connection connection = null;
Page pagination = new Page();
try {
connection = BaseDao.getConnection();
DBUtility.setAutoCommit(connection, false);
pagination.setList(userInfoDao.getUserList(u, pageNo, hangCount));
pagination.setPageNo(pageNo);
pagination.setHangCount(hangCount);
pagination.setSumCount(userInfoDao.getTotalNum(u));
BaseDao.commit(connection);
} catch (Exception e) {
DBUtility.rollBack(connection);
e.printStackTrace();
throw new Exception();
} finally {
BaseDao.closeConnection();
}
return pagination;
}
}
在Servlet:
import java.io.*;
import java.util.*;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import entity.UserInfo;
import service.UserInfoManage;
import util.Page;
public class UserBasicSearchServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private int hangCount = 0;
@Override
public void init(ServletConfig config) throws ServletException {
hangCount = Integer.parseInt(config.getInitParameter("hangCount"));
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1.取得頁面引數並構造引數物件
int pageNo = Integer.parseInt(req.getParameter("pageNo"));
String sex = req.getParameter("gender");
String home = req.getParameter("newlocation");
String colleage = req.getParameter("colleage");
String comingyear = req.getParameter("ComingYear");
UserInfo u = new UserInfo();
u.setSex(sex);
u.setHome(home);
u.setColleage(colleage);
u.setCy(comingyear);
// 2.呼叫業務邏輯取得結果集
UserInfoManage userInfoManage = new UserInfoManage();
PageModel<UserInfo> pagination = userInfoManage.userBasicSearch(u,
pageNo, pageSize);
List<UserInfo> userList = pagination.getList();
// 3.封裝返回結果
StringBuffer resultXML = new StringBuffer();
try {
resultXML.append("<?xml version='1.0' encoding='gb18030'?>/n");
resultXML.append("<root>/n");
for (Iterator<UserInfo> iterator = userList.iterator(); iterator
.hasNext();) {
UserInfo userInfo = iterator.next();
resultXML.append("<data>/n");
resultXML.append("/t<id>" + userInfo.getId() + "</id>/n");
resultXML.append("/t<truename>" + userInfo.getTruename()
+ "</ truename >/n");
resultXML.append("/t<sex>" + userInfo.getSex() + "</sex>/n");
resultXML.append("/t<home>" + userInfo.getHome() + "</home>/n");
resultXML.append("</data>/n");
}
resultXML.append("<pagination>/n");
resultXML.append("/t<total>" + pagination.getTotalPage()
+ "</total>/n");
resultXML.append("/t<start>" + pagination.getFirstPage()
+ "</start>/n");
resultXML.append("/t<end>" + pagination.getLastPage() + "</end>/n");
resultXML.append("/t<pageno>" + pagination.getPageNo()
+ "</pageno>/n");
resultXML.append("</pagination>/n");
resultXML.append("</root>/n");
} catch (Exception e) {
e.printStackTrace();
}
writeResponse(req, resp, resultXML.toString());
}
public void writeResponse(HttpServletRequest request,
HttpServletResponse response, String result) throws IOException {
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-Type", "text/xml; charset=gb18030");
PrintWriter pw = response.getWriter();
pw.write(result);
pw.close();
}
}
利用SSH實現:
在dao層編寫getSumCount()和List<Student> getStuByPage(Integer pageNo, Integer pageCount)2個方法:
有2種方法:
第一種:使用普通的分頁方法
//實現獲取總行數的方法
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Query;
private BaseUtil baseUtil;//需要生成setXX()和getXX()方法
public Integer getSumCount() {
//獲取session
Session session = baseUtil.getHibernateTemplate().getSessionFactory().openSession();
//執行查詢,呼叫查詢結果唯一的uniqueResult()方法;
Object object =session.createQuery("select count(別名.id) from 類名 別名 ").uniqueResult();
//根據資料型別確定返回值,型別不對時需要強制轉換
return Integer.valueOf(object.toString());
}
//實現分頁的方法
public List<Entity> getEntityByPage(Integer pageNo, Integer pageCount) {
Session session = baseUtil.getHibernateTemplate().getSessionFactory().openSession();
Query query = session.createQuery("from 類名 別名 ");
query.setMaxResults(pageCount);
return query.setFirstResult((pageNo-1)*pageCount).list();
}
第二種:使用Spring框架提供的方法
import org.hibernate.HibernateException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.hibernate.Query;
//實現獲取總行數的方法
public Integer getSumCount() {
Object obj = baseUtil.getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session){
Query query = session.createQuery("select count(別名.id) from 類名 別名 ");
Object object = query.uniqueResult();
return object;
}
});
return Integer.valueOf(obj.toString());
}
//實現分頁的方法
getEntityByPage(final Integer pageNo, final Integer pageCount):方法內的變數必須是final
public List<Entity> getEntityByPage(final Integer pageNo, final Integer pageCount) {
List<Entity> entitys = baseUtil.getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session){
Query query = session.createQuery("from 類名 別名");
query.setMaxResults(pageCount);
query.setFirstResult((pageNo-1)*pageCount);
return query.list();
}
});
return entitys ;
}
在service層中:
//EntityService.java
private Page page;//需要生成setXX()和getXX()方法
private Integer pageNo=1;
private Integer pageCount=1;
public Page getEntityByPage(Integer pageNo, Integer pageCount) {
if(page==null){
page=new Page();
}
page.setHangCount(pageCount);
page.setSumCount(stuDao.getSumCount());
page.setPageNo(pageNo);
page.setEntitys(stuDao.getEntityByPage(page.getPageNo(), page.getHangCount()));
return page;
}
在action層中:
//EntityAction.java
import service.EntityService;
import util.Page;
import com.opensymphony.xwork2.ActionSupport;
public class EntityAction extends ActionSupport {
private EntityService EntityService;//需要生成setXX()方法
private Page page;//當前頁,需要生成setXX()和getXX()方法
private Integer pageNo=1;//當前頁數,需要生成setXX()和getXX()方法
private Integer pageCount=2;//每頁顯示行數,需要生成setXX()和getXX()方法
@SuppressWarnings("unchecked")
@Override
public String execute() throws Exception {
page=entityService.getEntityByPage(pageNo, pageCount);
return SUCCESS;
}
最後在jsp頁面:
<div class=pager>
<ul>
<li class=current><a href="form表單action名?pageNo=1">首頁</a></li>
<li><a href="form表單action名?pageNo=${page.pageNo-1}">上一頁</a></li>
<li><a href="form表單action名?pageNo=${page.pageNo+1}">下一頁</a></li>
<li><a href="form表單action名?pageNo=${page.sumPage}">末頁</a></li>
</ul>
</DIV>
綜上所述,分頁功能可以基本實現。
文責宣告:本人借鑑得有別的作者的程式碼,本人初探JavaWeb,技術有限,還望各位多多指正批評。如果文中有涉及之外的事情,還望見諒!