李曉潔 廊坊師範學院資訊科技提高班 12期
在開發過程中,我們經常會從資料庫中查詢資料,然後在客戶端顯示出來。當資料少時,可以在一個頁面顯示。當我們查詢幾百條以上資料,直接顯示在一個頁面上,不僅瀏覽不方便,查詢效率也會受到影響,這是,我們就可以使用分頁查詢來解決這個問題。
分頁思路
分析上面這個頁面,想要實現分頁,我們在頁面中需要顯示的資料有:
本頁的資料列表 |
recordList |
當前頁 |
currentPage |
總頁數 |
pageCount |
每頁顯示多少條 |
pageSize |
總記錄數 |
recordCount |
頁碼列表的開始索引 |
beginPageIndex |
頁碼列表的結束索引 |
endPageIndex |
實現分頁需要顯示這麼多資料,所以我們就可以為分頁功能來封裝一個PageBean實體,用來接收頁面傳來的引數,以及為action提供從資料庫查詢出來的資料。
我們可以把頁面顯示的資料分為三類:
1.指定的或是頁面引數:currentPage,pageSize.
2.資料庫查詢的資料:recordCount,recordList.
3.通過計算得到:pageCount,beginPageIndex,endPageIndex.
這樣就可以只接收前4個必要的屬性,自動計算出其他3個屬性的值。
我們可以先分析一下大概的思路,首先JSP頁面負責顯示資料,Action用來接收頁面傳來的引數,並呼叫Service準備需要的資料,Service實現了資料訪問的功能,從資料庫中查詢出需要的資料,通過封裝的PageBean實體返回給Action。
程式碼實現
PageBean:
/** 分頁功能中一頁的資訊 */ public class PageBean { //指定的或是頁面引數 private int currentPage;//當前頁 private int pageSize;//每頁顯示多少條 //查詢資料庫 private int recordCount;//總記錄數 private List recordList;//本頁的資料列表 //計算 private int pageCount;//總頁數 private int beginPageIndex;//頁碼列表的開始索引 private int endPageIndex;//頁碼列表的結束索引 /** * 只接受前4個必要的屬性,會自動計算出其他3個屬性的值 * @param currentPage * @param pageSize * @param recordCount * @param recordList */ public PageBean(int currentPage, int pageSize, int recordCount, List recordList) { this.currentPage = currentPage; this.pageSize = pageSize; this.recordCount = recordCount; this.recordList = recordList; //計算總頁碼 pageCount = (recordCount + pageSize - 1) / pageSize; //計算beginPageIndex 和 endPageIndex //>>總頁數不多於10頁,則全部顯示 if(pageCount <= 10){ beginPageIndex = 1; endPageIndex = pageCount; } //總頁數多於10頁,則顯示當前頁附近的共10個頁碼 else{ //當前頁附近的共10個頁碼(前4個+當前頁+後5個) beginPageIndex = currentPage - 4; endPageIndex = currentPage + 5; //當前面的頁碼不足4個時,則顯示前10個頁碼 if(beginPageIndex < 1){ beginPageIndex = 1; endPageIndex = 10; } //當後面的頁碼不足5個時,則顯示後10個頁碼 if(endPageIndex > pageCount){ endPageIndex = pageCount; beginPageIndex = pageCount -10 + 1; } } } //這裡是get,set }
Action中準備分頁資訊的程式碼
// ===========分頁用的引數============
private int pageNum = 1;// 當前頁
private int pageSize = 10;// 每頁顯示多少條記錄
//這裡省略了get,set方法
// 準備分頁資訊(將pageBean放在棧頂)
PageBean pageBean = replyService.getPageBeanByTopic(pageNum,pageSize,topic);
ActionContext.getContext().getValueStack().push(pageBean);
Service中查詢資料庫的程式碼
public PageBean getPageBeanByForum(int pageNum, int pageSize, Forum forum) {
// 查詢列表
List list = getSession()
.createQuery(//
"FROM Topic t WHERE t.forum=? ORDER BY (CASE t.type WHEN 2 THEN 2 ELSE 0 END) DESC, t.lastUpdateTime DESC")//
.setParameter(0, forum)//
.setFirstResult((pageNum - 1) * pageSize)//
.setMaxResults(pageSize)//
.list();
// 查詢總記錄數量
Long count = (Long) getSession().createQuery(//
"SELECT COUNT(*) FROM Topic t WHERE t.forum=?")//
.setParameter(0, forum)//
.uniqueResult();
return new PageBean(pageNum, pageSize, count.intValue(), list);
}
JSP頁面接收資料(這裡只顯示了分頁控制元件的實現,當前頁顯示的資料列表recordList繫結到對應的位置就可以了。):
<!--分頁資訊-->
<div id=PageSelectorBar>
<div id=PageSelectorMemo>頁次:${currentPage}/${pageCount}頁
每頁顯示:${pageSize}條 總記錄數:${recordCount}條</div>
<div id=PageSelectorSelectorArea>
<a href="javascript:gotoPage(1)" title="首頁" style="cursor: hand;">
<img
src="${pageContext.request.contextPath}/style/blue/images/pageSelector/firstPage.png" />
</a>
<s:iterator begin="%{beginPageIndex}" end="%{endPageIndex}" var="num">
<s:if test="#num == currentPage">
<%-- #表示從map獲取 --%>
<%-- 當前頁 --%>
<span class="PageSelectorNum PageSelectorSelected">${num}</span>
</s:if>
<s:else>
<%-- 非當前頁 --%>
<span class="PageSelectorNum" style="cursor: hand;"
onClick="gotoPage(${num});">${num}</span>
</s:else>
</s:iterator>
<a href="javascript:gotoPage(${pageCount})" title="尾頁"
style="cursor: hand;"> <img
src="${pageContext.request.contextPath}/style/blue/images/pageSelector/lastPage.png" />
</a> 轉到: <select onchange="gotoPage(this.value)" id="_pn">
<s:iterator begin="1" end="%{pageCount}" var="num">
<option value="${num}">${num}</option>
</s:iterator>
</select>
<script type="text/javascript">
$("#_pn").val("${currentPage}");
</script>
</div>
</div>
到現在,我們已經實現了一個簡單的分頁查詢功能。那麼我們繼續想,如果我們其他頁面實現分頁查詢功能,還需要再copy一遍上面的程式碼嗎?這麼做顯然不是科學的方法,我們就會繼續封裝一些公共的程式碼,靈活的供各個功能呼叫。比如說現在能想到的優化的地方:
1.action中公共的分頁引數
2.Service中除了查詢的Hql語句和引數不同,具體的套路都差不多,我們可不可以傳遞hql和對應的引數,呼叫一個公共的方法?
3.JSP頁面上相同的分頁程式碼,寫在一個公共的頁面中,需要分頁時,直接引用這個頁面就好了。