Pagination in JSP
Written by coregps on Wednesday, August 31st, 2005 in Java.
If you're new here, you may want to subscribe to my RSS feed. Thanks for visiting!
We often have the requirement to paginate large amounts of records retrieved from database into pages. I have first used the Pager Tag Library from jsptags.com. It works fine when there is a small quantity of data. But with the increase of data size, it becomes more and more slow. It seems that it fetch all the data from database each time when we navigate between pages (Maybe I’m wrong). So, I implemented my own pagination bean used for MySQL.
The main idea is as follows:
1. Run two queries: One (SELECT with the LIMIT) to gets the rows which match that limit. The second (SELECT COUNT()) to get the number of results that match the query. Both have the same FROM clause and WHERE clause.
SELECT COUNT(*) AS cnt FROM invoice
SELECT invoiceno, password FROM invoice LIMIT ?, ?
2. When the page is requested for the first time, get the total number of records using the second query.
3. Append two additional parameters used for pagination to the end of the requested URL, current page number and total number of records.
4. Generate the pagination links (First, Prev, Next, Last and Go to):
The following is the souce code:
Pagination Java Bean, PaginationUtil.java
/*
function: Pagination
author: esurfer
date: 2005-08-28
parameter:
1. numOfRec– total number of records
2. recPerPage– number of rows per page
3. currPage–current page number
4. url–the requested url
return: pagination links with First, Prev, Next, Last, Go to
*/
public static String Pagination(int numOfRec, int recPerPage, int currPage, String url) {
StringBuffer ressurl = new StringBuffer();
String spChar = “?”;
if (url.indexOf(spChar) != -1) spChar = “&”;
if (numOfRec > recPerPage) {
int pages = (int)java.lang.Math.ceil((double)numOfRec / (double)recPerPage); // Get total number of pages
ressurl.append(”<div nowrap>n”);
ressurl.append(”<font face=arial size=-1>”);
ressurl.append(”Results Page: “).append(currPage).append(” / “).append(pages);
// Display link to first page
ressurl.append(” <b><a href=”").append(url).append(spChar).append(”pageno=1&numofrec=”)
.append(numOfRec).append(””>First</a></b>n”);
// Link to previous page
if (currPage > 1) {
ressurl.append(”| <b><a href=”").append(url).append(spChar).append(”pageno=”)
.append(currPage - 1).append(”&numofrec=”).append(numOfRec).append(””>Prev</a></b>n”);
}
// Display link to next page
if (currPage < pages) {
ressurl.append(”| <b><a href=”").append(url).append(spChar).append(”pageno=”)
.append(currPage + 1).append(”&numofrec=”).append(numOfRec).append(””>Next</a></b>n”);
}
// Link to last page
ressurl.append(”| <b><a href=”").append(url).append(spChar).append(”pageno=”)
.append(pages).append(”&numofrec=”).append(numOfRec).append(””>Last</a></b>n”);
// Drop down navigation
ressurl.append(” Go to? <select id=”pageno” name=”pageno” onchange=”pagination()”>n”);
// If number of pages > 200
// display only 20 pagination links in the drop down list
// else
// display all pagination links in the drop down list
int iBeginPageNo = 1, iEndPageNo = pages;
if (pages >= 200) {
// Calculate the beginning index
int temp = currPage - 20;
if (temp <= 0) {
iBeginPageNo = 1;
} else {
iBeginPageNo = temp;
}
// Calculate the ending index
temp = currPage + 20;
if (temp >= pages) {
iEndPageNo = pages;
} else {
iEndPageNo = temp;
}
}
for (int i = iBeginPageNo; i <= iEndPageNo; i++) {
if (i == currPage) {
ressurl.append(”<option value=”").append(i).append(”” selected>”).append(i).append(”</option>n”);
} else {
ressurl.append(”<option value=”").append(i).append(””>”).append(i).append(”</option>n”);
}
}
ressurl.append(”</select></font>n”);
ressurl.append(”</div>n”);
ressurl.append(”<script type”=text/javascript”>n”);
ressurl.append(”function pagination() {n”);
ressurl.append(”location.href=’”).append(url).append(spChar).append(”pageno=’ + document.getElementById(’pageno’).value”)
.append(” + ‘&numofrec=”).append(numOfRec).append(”‘;n”);
ressurl.append(”}n”);
ressurl.append(”</script>n”);
}
return ressurl.toString();
}
}Invoice Java Bean, Invoice.java
package com.esurfer.report;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import com.esurfer.db.DBConn;
import com.esurfer.util.PaginationUtil;
public class Invoice {
static String sqlcnt = “SELECT COUNT(*) AS cnt FROM invoice”;;
static String url = “invoice.jsp”;
static int recPerPage = 15;
public static String getInvoiceList(int numOfRec, int currPage) {
int iStartLimit;
if (currPage == 1) {
numOfRec = DBConn.getNumOfRec(sqlcnt); // get total number of records only the first time
iStartLimit = 0;
currPage = 1;
} else {
iStartLimit = (currPage -1) * recPerPage;
}
StringBuffer result = new StringBuffer();
StringBuffer sql = new StringBuffer(”SELECT invoiceno, password FROM invoice”).append(” LIMIT “).append(”?, ?”);
ArrayList list = DBConn.searchToMapList(sql.toString(), new Object[]{new Integer(iStartLimit), new Integer(recPerPage)});
Iterator iterator = list.iterator();
Map map = null;
while (iterator.hasNext()) {
map = (Map)iterator.next();
result.append(”“).append(map.get(”invoiceno”)).append(” “).append(map.get(”password”)).append(” n”);
}
result.append(”“).append(PaginationUtil.Pagination(numOfRec, recPerPage, currPage, url)).append(” “);
iterator = null;
list = null;
map = null;
return result.toString();
}
}Testing in JSP, test.jsp
<%@page pageEncoding=”UTF-8″ contentType=”text/html; charset=UTF-8″ %>
<%@page import=”com.esurfer.report.*”%>
<%
String numofrec = request.getParameter(”numofrec”);
if (numofrec == null) numofrec = “0″;
String pageno = request.getParameter(”pageno”);
if (pageno == null) pageno = “1″;
%>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″/>
<title>Pagination Test</title>
</head>
<body>
<table border=”1″ cellpadding=”0″ cellspacing=”0″ width=”100%”>
<thead>
<tr><th>Invoice No</th><th>Password</th></tr>
</thead>
<tbody>
<%=Invoice.getInvoiceList(Integer.parseInt(numofrec), Integer.parseInt(pageno))%>
</tbody>
</table>
</body>
</html>
Although the code above gets a better performance, it seems too complex. In addition, the code above can only work for MySQL. Any better solutions will be appreciated.










