分頁技術(shù)在web開發(fā)中是不可忽略的,也是非常重要的。其實傳統(tǒng)分頁跟新式分頁還是各分千秋的,不能說老的不好,新的就好,要具體對待具體的項目。從網(wǎng)上看到某人的一段話,非常有效,相信這位仁兄也是經(jīng)驗之談了:
“第一種方法是用select語句查詢出所有的數(shù)據(jù),再通過移動當(dāng)前記錄指針到當(dāng)前頁面需要顯示的數(shù)據(jù)記錄位置,再作顯示。優(yōu)點是程序比較簡單,由于查詢出來的結(jié)果較大,網(wǎng)絡(luò)開銷也較大。
第二種方法是先用一條select語句得到SQL查詢的記錄條數(shù),因為數(shù)據(jù)庫存執(zhí)行"select count(*)"運算的速度是很快的,返回的數(shù)據(jù)集也僅一條記錄,此開銷可忽略不記。得到總記錄數(shù)后,再計算出當(dāng)前頁面要顯示的數(shù)據(jù)的SQL查詢結(jié)果的起始位置和結(jié)束位置,再用SQL語句查詢出當(dāng)前頁的數(shù)據(jù)。這種方法編寫的程序的量相對較多,得到的數(shù)據(jù)量也相對較小,運行效率比第一種高,但并不能從根本上優(yōu)化數(shù)據(jù)庫的SQL查詢,也不能從根本上解決網(wǎng)絡(luò)開銷大的問題。
第三種方法是使用存儲過程。存儲過程在數(shù)據(jù)庫中會作預(yù)編譯處理,所以執(zhí)行速度較快。在JSP頁面中要設(shè)定每頁記錄條數(shù)、當(dāng)前的頁碼等參數(shù),再將這些參數(shù)在調(diào)用存儲過程時傳入到存儲過程中,由存儲過程執(zhí)行后得到指定頁指定數(shù)目的記錄數(shù)。這種方法優(yōu)點燭效率最高,網(wǎng)絡(luò)開銷小,缺點不是程序員需要編寫較多的程序,針對每個查詢要編寫不同的存儲過程。”
三種分頁我也都有用到過,我的一點感受:第一,三種方案對java程序設(shè)計師非常簡單的。首先推翻一種說法,網(wǎng)上很多網(wǎng)友都說什么緩存數(shù)據(jù)查詢結(jié)果集。乍一想很不過的想法。仔細(xì)一想,怎么可能。每當(dāng)在數(shù)據(jù)庫連接關(guān)閉時(PareparedStatement,Connection關(guān)閉),ResultSet 也都關(guān)閉了。看看下面的圖就知道了:

分頁一:
我是這樣做的,首先我得到結(jié)果集(在我的項目里,結(jié)果集是解析xml而來的),然后都放到list中,傳到view層(JSP),將這個list保存在HeepSession中。每次查詢分頁都是在這個list里截取。在數(shù)據(jù)量很小的情況下,這個還是非常方便的。只需要讀取一次xml(一般連接DB的時候也只要連接一次)。同時缺點也是非常明顯的:1.當(dāng)這個結(jié)果集很大的時候無疑是非常耗內(nèi)存的,效率也大減;2.實時性也很差,開始就將數(shù)據(jù)封裝在list里了,得不到即時更新。
我在wap項目中的具體實現(xiàn),wap用法很簡單:
注:為了方便我個人,有些無用信息我也不刪除了,如果有讀者看到,無用信息就忽略了吧。還有這里的list是我從后層解析xml封裝的Listprize 集合。
JSP:
<%
request.setCharacterEncoding("UTF-8");
String lotid = request.getParameter("lotid");
String name = request.getParameter("name");
String pages = request.getParameter("pages");
int pageI = Integer.parseInt(pages);
String cpname = "";
if (lotid.equals("7")) {
cpname = "福彩3D";
} else if (lotid.equals("28")) {
cpname = "大樂透";
} else if (lotid.equals("8")) {
cpname = "22選5";
} else if (lotid.equals("20")) {
cpname = "29選7";
} else if (lotid.equals("5")) {
cpname = "數(shù)字排列";
} else if (lotid.equals("11")) {
cpname = "七樂彩";
} else if (lotid.equals("4")) {
cpname = "七星彩";
} else if (lotid.equals("26")) {
cpname = "36選7";
} else if (lotid.equals("12")) {
cpname = "時時樂";
} else if (lotid.equals("3")) {
cpname = "雙色球";
} else if (lotid.equals("21")) {
cpname = "15選5";
} else if (lotid.equals("1")) {
cpname = "勝負(fù)彩";
} else if (lotid.equals("15")) {
cpname = "半全場";
} else if (lotid.equals("17")) {
cpname = "進(jìn)球彩";
} else if (lotid.equals("29")) {
cpname = "時時彩";
}
out.write(cpname + "最新一期用戶中獎信息<br/>");
//第一次訪問排行榜的時候,初始化排行榜list,并將其放入session,供下次分頁。
if(pageI == 1) {
List<Listprize> list = prize.getPrize(lotid, name);
session.setAttribute("list", list);
}
List<Listprize> listPrize = (List<Listprize>)session.getAttribute("list");
int allpage = listPrize.size()/10 + (listPrize.size()%10==0?0:1);
int allRec = listPrize.size();
int pagesize = 10;
out.write("共" + allRec + "位中獎,第" + pageI + "/" + allpage + "頁<br/>");
if(allRec <= pagesize) {
for(Listprize l: listPrize) {
out.write("[" + cpname + "]" + l.getUsername() + "喜中" + l.getGetMoney() + "<br/>");
}
} else {
if(pageI == allpage){
for(int i = (pageI-1)*pagesize; i < allRec; i++) {
Listprize prizeObject = listPrize.get(i);
out.write("[" + cpname + "]" + prizeObject.getUsername() + "喜中" + prizeObject.getGetMoney() + "<br/>");
}
out.write("<anchor><go href='newaward.jsp'>上一頁<postfield name='lotid' value='"+lotid+"'/><postfield name='name' value='"+name+"'/><postfield name='pages' value='"+(pageI-1)+"'/></go></anchor><br/>");
}else {
for(int i = (pageI-1)*pagesize; i < pageI*pagesize; i++) {
Listprize prizeObject = listPrize.get(i);
out.write("[" + cpname + "]" + prizeObject.getUsername() + "喜中" + prizeObject.getGetMoney() + "<br/>");
}
if(pageI > 1) {
out.write("<anchor><go href='newaward.jsp'>上一頁<postfield name='lotid' value='"+lotid+"'/><postfield name='name' value='"+name+"'/><postfield name='pages' value='"+(pageI-1)+"'/></go></anchor>");
}
out.write(" <anchor><go href='newaward.jsp'>下一頁<postfield name='lotid' value='"+lotid+"'/><postfield name='name' value='"+name+"'/><postfield name='pages' value='"+(pageI+1)+"'/></go></anchor><br/>");
}
}
%>
“第一種方法是用select語句查詢出所有的數(shù)據(jù),再通過移動當(dāng)前記錄指針到當(dāng)前頁面需要顯示的數(shù)據(jù)記錄位置,再作顯示。優(yōu)點是程序比較簡單,由于查詢出來的結(jié)果較大,網(wǎng)絡(luò)開銷也較大。
第二種方法是先用一條select語句得到SQL查詢的記錄條數(shù),因為數(shù)據(jù)庫存執(zhí)行"select count(*)"運算的速度是很快的,返回的數(shù)據(jù)集也僅一條記錄,此開銷可忽略不記。得到總記錄數(shù)后,再計算出當(dāng)前頁面要顯示的數(shù)據(jù)的SQL查詢結(jié)果的起始位置和結(jié)束位置,再用SQL語句查詢出當(dāng)前頁的數(shù)據(jù)。這種方法編寫的程序的量相對較多,得到的數(shù)據(jù)量也相對較小,運行效率比第一種高,但并不能從根本上優(yōu)化數(shù)據(jù)庫的SQL查詢,也不能從根本上解決網(wǎng)絡(luò)開銷大的問題。
第三種方法是使用存儲過程。存儲過程在數(shù)據(jù)庫中會作預(yù)編譯處理,所以執(zhí)行速度較快。在JSP頁面中要設(shè)定每頁記錄條數(shù)、當(dāng)前的頁碼等參數(shù),再將這些參數(shù)在調(diào)用存儲過程時傳入到存儲過程中,由存儲過程執(zhí)行后得到指定頁指定數(shù)目的記錄數(shù)。這種方法優(yōu)點燭效率最高,網(wǎng)絡(luò)開銷小,缺點不是程序員需要編寫較多的程序,針對每個查詢要編寫不同的存儲過程。”
三種分頁我也都有用到過,我的一點感受:第一,三種方案對java程序設(shè)計師非常簡單的。首先推翻一種說法,網(wǎng)上很多網(wǎng)友都說什么緩存數(shù)據(jù)查詢結(jié)果集。乍一想很不過的想法。仔細(xì)一想,怎么可能。每當(dāng)在數(shù)據(jù)庫連接關(guān)閉時(PareparedStatement,Connection關(guān)閉),ResultSet 也都關(guān)閉了。看看下面的圖就知道了:

分頁一:
我是這樣做的,首先我得到結(jié)果集(在我的項目里,結(jié)果集是解析xml而來的),然后都放到list中,傳到view層(JSP),將這個list保存在HeepSession中。每次查詢分頁都是在這個list里截取。在數(shù)據(jù)量很小的情況下,這個還是非常方便的。只需要讀取一次xml(一般連接DB的時候也只要連接一次)。同時缺點也是非常明顯的:1.當(dāng)這個結(jié)果集很大的時候無疑是非常耗內(nèi)存的,效率也大減;2.實時性也很差,開始就將數(shù)據(jù)封裝在list里了,得不到即時更新。
我在wap項目中的具體實現(xiàn),wap用法很簡單:
注:為了方便我個人,有些無用信息我也不刪除了,如果有讀者看到,無用信息就忽略了吧。還有這里的list是我從后層解析xml封裝的Listprize 集合。
JSP:














































































