jsp分页技术实现.docx
《jsp分页技术实现.docx》由会员分享,可在线阅读,更多相关《jsp分页技术实现.docx(25页珍藏版)》请在冰豆网上搜索。
jsp分页技术实现
select * from (
select my_table.*, rownum as my_rownum from (
select name, birthday from employee order by birthday
) my_table where rownum <120
) where my_rownum>=100
mySQL可以使用LIMIT子句:
select name, birthday from employee order by birthday LIMIT 99,20
DB2有rownumber()函数用于获取当前行数。
SQL Server没研究过,可以参考这篇文章:
在Web程序中分页会被频繁使用,但分页的实现细节却是编程过程中比较麻烦的事情。
大多分页显示的查询操作都同时需要处理复杂的多重查询条件,sql语句需要动态拼接组成,再加上分页需要的记录定位、总记录条数查询以及查询结果的遍历、封装和显示,程序会变得很复杂并且难以理解。
因此需要一些工具类简化分页代码,使程序员专注于业务逻辑部分。
下面是我设计的两个工具类:
PagedStatement 封装了数据库连接、总记录数查询、分页查询、结果数据封装和关闭数据库连接等操作,并使用了PreparedStatement支持动态设置参数。
RowSetPage 参考PetStore的page by page iterator模式, 设计RowSetPage用于封装查询结果(使用OracleCachedRowSet缓存查询出的一页数据,关于使用CachedRowSet封装数据库查询结果请参考JSP页面查询显示常用模式)以及当前页码、总记录条数、当前记录数等信息, 并且可以生成简单的HTML分页代码。
PagedStatement 查询的结果封装成RowsetPage。
下面是简单的使用示例:
1.
2. RowSet empRS = .RowSet) ();
3. if (empRS!
=null) while () ) {
4.%>
5.
6.
<%= ("EMP_ID")%> | 7.
<%= ("EMP_CODE")%> | 8.
<%= ("USER_NAME")%> | 9.
<%= ("REAL_NAME")%> | 10.
11.<%
12. }etHTML("doQuery", "pageno")%>
13.
14.
15.
效果如图:
因为分页显示一般都会伴有查询条件和查询动作,页面应已经有校验查询条件和提交查询的javascript方法(如上面的doQuery),所以()生成的分页代码在用户选择新页码时直接回调前面的处理提交查询的javascript方法。
注意在显示查询结果的时候上次的查询条件也需要保持,如">。
同时由于页码的参数名可以指定,因此也支持在同一页面中有多个分页区。
另一种分页代码实现是生成每一页的URL,将查询参数和页码作为QueryString附在URL后面。
这种方法的缺陷是在查询条件比较复杂时难以处理,并且需要指定处理查询动作的servlet,可能不适合某些定制的查询操作。
如果对()生成的默认分页代码不满意可以编写自己的分页处理代码,RowSetPage提供了很多getter方法用于获取相关信息(如当前页码、总页数、 总记录数和当前记录数等)。
在实际应用中可以将分页查询和显示做成jsp taglib, 进一步简化JSP代码,屏蔽Java Code。
附:
分页工具类的源代码, 有注释,应该很容易理解。
继承Page)
继承PagedStatement)
您可以任意使用这些源代码,但必须保留author字样
1.
2.List;
3.import .ArrayList;
4.import .Collection;
5.import .Collections;
6.
7.
8./**
9. * Title:
分页对象
10. * Description:
用于包含数据及分页信息的对象
11. * Page类实现了用于显示分页信息的基本方法,但未指定所含数据的类型,
12. * 可根据需要实现以特定方式组织数据的子类,
13. * 如RowSetPage以RowSet封装数据,ListPage以List封装数据
14. * Copyright:
Copyright (c) 2002
15. * @author
16. * @version
17. */
18.public class Page implements .Serializable {
19. public static final Page EMPTY_PAGE = new Page();
20. public static final int DEFAULT_PAGE_SIZE = 20;
21. public static final int MAX_PAGE_SIZE = 9999;
22.
23. private int myPageSize = DEFAULT_PAGE_SIZE;
24.
25. private int start;
26. private int avaCount,totalSize;
27. private Object data;
28.
29. private int currentPageno;
30. private int totalPageCount;
31.
32. /**
33. * 默认构造方法,只构造空页
34. */
35. protected Page(){
36. (0,0,0,DEFAULT_PAGE_SIZE,new Object());
37. }
38.
39. /**
40. * 分页数据初始方法,由子类调用
41. * @param start 本页数据在数据库中的起始位置
42. * @param avaCount 本页包含的数据条数
43. * @param totalSize 数据库中总记录条数
44. * @param pageSize 本页容量
45. * @param data 本页包含的数据
46. */
47. protected void init(int start, int avaCount, int totalSize, int pageSize, Object data){
48.
49. =avaCount;
50. = pageSize;
51.
52. = start;
53. = totalSize;
54.
55. =data;
56.
57. ength()<1) {
58. queryJSFunctionName = "gotoPage";
59. }
60. if (pageNoParamName == null || ().length()<1){
61. pageNoParamName = "pageno";
62. }
63.
64. String gotoPage = "_"+queryJSFunctionName;
65.
66. StringBuffer html = new StringBuffer("\n");
67. (" \n")
89. .append( "");
90. ( "
\n")91. .append( "
\n")92. .append( "
\n");93. ( " 共" ).append( getTotalPageCount() ).append( "页") 94. .append( " [") .append(getStart()).append("..").append(getEnd()) 95. .append("/").append()).append("] \n") 96. .append( " | \n")97. .append( "
\n"); 98. if (hasPreviousPage()){ 99. ( "[").append(gotoPage) 100. .append("(") .append(getCurrentPageNo()-1) 101. .append( ")'>上一页 ] \n"); 102. } 103. ( " 第") 104. .append( " 页 \n"); 121. if (hasNextPage()){ 122. ( " [").append(gotoPage) 123. .append("(").append((getCurrentPageNo()+1)) 124. .append( ")'>下一页 ] \n"); 125. } 126. ( " |
\n");
127.
128. return ();
129.
130. }
131.}
132.
133.
134.
135.
136.RowSet;
137.
138.
139./**
140. *
Title:
RowSetPage
141. *
Description:
使用RowSet封装数据的分页对象
142. *
Copyright:
Copyright (c) 2003
143. * @author
144. * @version
145. */
146.
147.public class RowSetPage extends Page {
148. private .RowSet rs;
149.
150. /**
151. *空页
152. */
153. public static final RowSetPage EMPTY_PAGE = new RowSetPage();
154.
155. /**
156. *默认构造方法,创建空页
157. */
158. public RowSetPage(){
159. this(null, 0,0);
160. }
161.
162. /**
163. *构造分页对象
164. *@param crs 包含一页数据的OracleCachedRowSet
165. *@param start 该页数据在数据库中的起始位置
166. *@param totalSize 数据库中包含的记录总数
167. */
168. public RowSetPage(RowSet crs, int start, int totalSize) {
169. this(crs,start,totalSize,;
170. }
171.
172. /**
173. *构造分页对象
174. *@param crs 包含一页数据的OracleCachedRowSet
175. *@param start 该页数据在数据库中的起始位置
176. *@param totalSize 数据库中包含的记录总数
177. *@pageSize 本页能容纳的记录数
178. */
179. public RowSetPage(RowSet crs, int start, int totalSize, int pageSize) {
180. try{
181. int avaCount=0;
182. if (crs!
=null) {
183. ();
184. if ()){
185. ();
186. avaCount = ();
187. }
188. ();
189. }
190. rs = crs;
191. (start,avaCount,totalSize,pageSize,rs);
192. }catch.SQLException sqle){
193. throw new RuntimeException());
194. }
195. }
196.
197. /**
198. *取分页对象中的记录数据
199. */
200. public .RowSet getRowSet(){
201. return rs;
202. }
203.
204.
205.}
206.
207.
208.
209.
210.BigDecimal;
211.import .List;
212.import .Iterator;
213.import .Collections;
214.
215.import .Connection;
216.import .SQLException;
217.import .ResultSet;
218.import .Statement;
219.import .PreparedStatement;
220.import .Timestamp;
221.import .RowSet;
222.
223./**
224. *
Title:
分页查询
225. *
Description:
根据查询语句和页码查询出当页数据
226. *
Copyright:
Copyright (c) 2002
227. * @author
228. * @version
229. */
230.public abstract class PagedStatement {
231. public final static int MAX_PAGE_SIZE = ;
232.
233. protected String countSQL, querySQL;
234. protected int pageNo,pageSize,startIndex,totalCount;
235. protected .RowSet rowSet;
236. protected RowSetPage rowSetPage;
237.
238. private List boundParams;
239.
240. /**
241. * 构造一查询出所有数据的PageStatement
242. * @param sql query sql
243. */
244. public PagedStat