搜索这个标题找到一篇文章:
适用所有使用jdbc结合sqlserver的javaWeb工程的分页查询共通操作代码
http://alexlsg.iteye.com/blog/700015
看了之后,试运行了一下。发现不可以用。
原因:row_number()是sql2005及以后版本的函数。而sql2000是没有的。
故此重新梳理了一下。
1、分页查询时需要用到的分页信息实体类
import java.io.Serializable;
/**
* 适用于所有的使用jdbc结合sqlserver的web工程
*
*
* @author ycglei886
*/
public class PageInfo implements Serializable {
private static final long serialVersionUID = 7126509565385142115L;
/**
* 记录总数(该属性由PageSearchUtil设置)
*
*/
private int recordCount;
/**
* 每页面最大记录数(该属性在传入PageSearchUtil的getPageResultSet方法之前需要设置)
*
*/
private int pageSize;
/**
* 总页数(该属性由本类的compute方法计算得出)
*
*/
private int pageCount;
/**
* 每部分页数(假如总共有100页,那么我们不可能将100页的页码都显示在页面上,只能部分部分的显示,该属性就是设置部分显示多少页的)
* 该属性与compute方法无关,在PageSearchUtil中也不会用到,但我们在页面上会用到
*/
private int partPageCount = 10;
/**
* 当前是第几页(该属性在传入PageSearchUtil的getPageResultSet方法之前需要设置)
*
*/
private int currentPage;
/**
* 开始记录数(该属性由本类的compute方法计算得出)
*
*/
private int startRecord;
/**
* 结束记录数(该属性由本类的compute方法计算得出)
*
*/
private int endRecrod;
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getEndRecrod() {
return endRecrod;
}
public int getPageCount() {
return pageCount;
}
public int getPartPageCount() {
return partPageCount;
}
public void setPartPageCount(int partPageCount) {
this.partPageCount = partPageCount;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getRecordCount() {
return recordCount;
}
public void setRecordCount(int recordCount) {
this.recordCount = recordCount;
}
public int getStartRecord() {
return startRecord;
}
public PageInfo() {
}
/**
* 通过recordCount、pageSize、currentPage三个属性值来计算本对象中所有属性的值
*
*
*/
public void compute() {
if (recordCount == 0 || pageSize == 0) {
pageCount = 0;
startRecord = 0;
endRecrod = 0;
currentPage = 0;
} else {
pageCount = (recordCount + pageSize - 1) / pageSize;
if (currentPage <= 0) {
currentPage = 1;
}
if (currentPage > pageCount) {
currentPage = pageCount;
}
startRecord = (currentPage - 1) * pageSize + 1;
int endRecrodTemp = startRecord + pageSize - 1;
if (endRecrodTemp <= recordCount) {
endRecrod = endRecrodTemp;
} else {
endRecrod = recordCount;
}
}
}
}
2、分页查询共通操作类
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
/**
* 分页查询共通操作类 分页查询的思路是每页的数据分别进行查询,而不是将全部数据查询出来之后再分页
*
* @author ycglei886
* 创建时间:2010/5/20
* @version 1.0
*/
public class PageSearchUtil {
/**
* PageSearchUtil私有构造方法 通过这个私有构造方法使该类无法实例化,只能通过静态方式调用该类的分页查询方法。
*/
private PageSearchUtil() {
}
/**
* 分页查询
*
*
* @param conn
* 数据库连接对象(该对象由调用本方法的方法传入和关闭)
* @param ps
* 数据库操作预编译对象(该对象是进行分页查询时查询每页数据的预编译对象,该对象由调用本方法的方法传入和关闭)
* @param pageInfo
* 分页信息对象(该对象中提供了set方法的属性需要进行预先设置,该对象传入本方法后其属性值会被本方法更新,因此在调用本方法的方法中,请注意获取该pageInfo属性的时机)
* @param selectContent
* sql语句中select关键字后面跟的字段字符串(形如:"userName,password"或者"*")
* @param fromContent
* sql语句中from关键字后面跟的字段字符串(形如:"userInfo"或Bulletin bu left join
* UserInfo us on bu.userId=us.id)
* @param whereContent
* sql语句中where关键字后面跟的条件字符串(形如:"userName=?,password=?")
* @param orderByContent
* 使用sqlserver进行分页查询时,需要用到row_number()函数,该函数必须与over(order by
* ...)连用,也就是说sqlserver中要分页就必须要排序
* @param paramArray
* 查询参数(如果在前面的whereContent中使用了问好占位符,则该参数用于依次替换问号,如果没有使用问号站位符,则该参数传入null)
* @return ResultSet 数据库查询结果对象(该对象即分页查询时每页的查询结果集,该对象由调用本方法的方法传入和关闭)
*/
public static ResultSet getPageResultSet(Connection conn,
PreparedStatement ps, PageInfo pageInfo, String selectContent,
String fromContent, String whereContent, String orderByContent,
Object[] paramArray) {
// 构造查询记录总条数的sql语句
StringBuffer countSqlBuffer = new StringBuffer("select count(*) from ");
countSqlBuffer.append(fromContent);
countSqlBuffer.append(" where 1=1");
if (whereContent != null && whereContent.length() > 0) {
countSqlBuffer.append(whereContent);
}
// 构造查询结果集的sql2005语句
/* StringBuffer sqlBuffer = new StringBuffer(
"WITH OrderedOrders AS (select row_number() over(order by ");
sqlBuffer.append(orderByContent);
sqlBuffer.append(") as 'rowNum', ");
sqlBuffer.append(selectContent);
sqlBuffer.append(" from ");
sqlBuffer.append(fromContent);
sqlBuffer.append(" where 1=1");
if (whereContent != null && whereContent.length() > 0) {
sqlBuffer.append(" and ");
sqlBuffer.append(whereContent);
}
sqlBuffer
.append(") select * from OrderedOrders WHERE rowNum between ? and ?"); */
// 构造查询结果集的sql2000语句
StringBuffer sqlBuffer = new StringBuffer(
"SELECT * from ( select (select count(*) from ");
sqlBuffer.append(fromContent);
sqlBuffer.append(" t2 where t1.");
sqlBuffer.append(orderByContent);
sqlBuffer.append(" >= ");
sqlBuffer.append(" t2.");
sqlBuffer.append(orderByContent);
if (whereContent != null && whereContent.length() > 0) {
sqlBuffer.append(whereContent);
}
sqlBuffer.append(" ) as 'rowNum', ");
sqlBuffer.append(selectContent);
sqlBuffer.append(" from ");
sqlBuffer.append(fromContent);
sqlBuffer.append(" t1 where 1=1");
if (whereContent != null && whereContent.length() > 0) {
sqlBuffer.append(whereContent);
}
sqlBuffer.append(") windCommonTable WHERE rowNum between ? and ?");
// 声明查询数据条数的预编译对象(该对象由本方法自己控制生成和关闭,注意区别该对象不是传入本方法的那个预编译对象)
PreparedStatement countPs = null;
// 声明查询结果集对象(该对象的关闭由调用本方法的方法来执行)
ResultSet rs = null;
// 声明存放记录总数的变量
int count = 0;
try {
// 获取查询数据条数的预编译对象
countPs = conn.prepareStatement(countSqlBuffer.toString());
// 获取查询每页数的预编译对象
ps = conn.prepareStatement(sqlBuffer.toString());
// 通过以下循环来为两个预编译对象设置参数,因为两个查询的查询语句前面的问号位置和数量是完全一致的(ps最后面会多两个问号),
//所以这里在一个循环中为两个预编译对象设置参数
int i = 1;
if (paramArray != null && paramArray.length > 0) {
for (; i <= paramArray.length; i++) {
if(i<=paramArray.length/2){
countPs.setObject(i, paramArray[i - 1]);
}
ps.setObject(i, paramArray[i - 1]);
}
}
// 获取记录总数的查询结果集
ResultSet countRs = countPs.executeQuery();
if (countRs != null && countRs.next()) {
count = countRs.getInt(1);
}
// 关闭查询记录总数所使用的预编译对象和查询结果集
DBConnection.closeConn(countRs, countPs, null);
// 设置分页信息对象的记录总数属性
pageInfo.setRecordCount(count);
// 调用分页信息对象的方法来计算并更新分页信息对象中其他的属性值
pageInfo.compute();
// 当记录结果大于0的时候才进行每页数据的查询
if (count > 0) {
// 获取每页面最大记录数
int pageSize = pageInfo.getPageSize();
// 获取当前第几页(页数)
int pageNum = pageInfo.getCurrentPage();
// 设置预编译对象的between and相关的2个参数
System.out.println((pageNum - 1) * pageSize + 1);
System.out.println(pageNum * pageSize);
ps.setInt(i, (pageNum - 1) * pageSize + 1);
ps.setInt(i + 1, pageNum * pageSize);
// 获取每页数据查询结果集
rs = ps.executeQuery();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
// 返回每页数据查询结果集
return rs;
}
/**
* 初始化PageInfo,当request中无法获取相应值的时候设置默认值
* @param request HttpServletRequest
* @return PageInfo
*/
public static PageInfo initPageInfo(HttpServletRequest request){
PageInfo pageInfo = new PageInfo();
// 设置当前第几页,默认值为1
String pageNum = request.getParameter("pageNum");
if(pageNum != null && !"".equals(pageNum)){
pageInfo.setCurrentPage(Integer.valueOf(pageNum));
}else{
pageInfo.setCurrentPage(1);
}
// 设置每页面最大记录数,默认值为10
String pageSize = request.getParameter("pageSize");
if(pageSize != null && !"".equals(pageSize)){
pageInfo.setPageSize(Integer.valueOf(pageSize));
}else{
pageInfo.setPageSize(10);
}
// 设置每部分页数,默认值为10
String partPageCount = request.getParameter("partPageCount");
if(partPageCount != null && "".equals(partPageCount)){
pageInfo.setPartPageCount(Integer.valueOf(partPageCount));
}else{
pageInfo.setPartPageCount(10);
}
// 返回PageInfo对象
return pageInfo;
}
}
3、数据库访问操作类代码:
public List<TableName > getSa(TableName smtab,PageInfo pageInfo){
//实例化list对象
List<TableName > list = new ArrayList<TableName >();
//获得数据库连接得到conn对象
Connection conn = DBConnection.getConn();
//声明一个sql预编译器语句对象
PreparedStatement ps = null;
//获得构造sql查询字段
String selectContent = " * ";
//获得查询数据表的关联关系
String fromContent = "dbo.TableName ";
//初始化定义一个sql语句查询条件为null
String whereContent = "";
List params=new ArrayList();
if(null!=smtab){
if(null!=smtab.getSNo() && !"".equals(smtab.getSNo())){
whereContent += " and SNo like ?";
params.add("%" + smtab.getSNo() + "%");
}
}
//条件数组参数对象
Object[] paramArray =new Object[params.size()*2];
if(params.size()>0){
for(int i=0;i<params.size();i++){
paramArray[i]=params.get(i);
}
for(int i=0,j=params.size();i<params.size();i++,j++){
paramArray[j]=params.get(i);
}
}
//定义排序对象
String orderByContent = "sNo";
//调用PageSearchUtil分页工具类并返回结果集对象
ResultSet rs = PageSearchUtil.getPageResultSet(conn, ps, pageInfo,
selectContent, fromContent, whereContent, orderByContent, paramArray);
try {
// 处理结果
while (rs != null && rs.next()) {
//读取第一行数据
TableName smtable = newTableName ();
//从结果集中通过列名读取当前游标指向行的指定列的数据
smtable.setSNo(rs.getString("sNo"));
list.add(smtable);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭数据库访问对象
DBConnection.closeConn(rs, ps, conn);
}
return list;
}
4.action代码
public String ster(){
pageInfo = PageSearchUtil.initPageInfo(request);
// 调用业务
SServiceImpl sserviceImpl=new SServiceImpl ();
smlist = sserviceImpl.getSa(smtab,pageInfo);
if(null!=smtab){
if(null!=smtab.getSNo() && !"".equals(smtab.getSNo())){
pageurl+= "&smtab.sNo="+smtab.getSNo();
}
}
return "sa";
}
5.自定义标签
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import com.wind.service.PageInfo;
public class PageSearchTag extends SimpleTagSupport {
private PageInfo pageInfo;
private String requestPath;
@Override
public void doTag() throws JspException, IOException {
this.getJspContext().setAttribute("requestPath", requestPath,
PageContext.REQUEST_SCOPE);
int currentPage = pageInfo.getCurrentPage();
int pageCount = pageInfo.getPageCount();
int partPageCount = pageInfo.getPartPageCount();
// 获取每部分的第一页页数
int firstPageNum = 0;
if (currentPage != 0 && currentPage % partPageCount == 0) {
firstPageNum = currentPage - partPageCount + 1;
} else {
firstPageNum = currentPage - currentPage % partPageCount + 1;
}
// 获取每部分最后一页页数
int lastPageNum = firstPageNum + partPageCount - 1;
if (lastPageNum > pageCount) {
lastPageNum = pageCount;
}
// 将本部分的页数添加到集合中,以便在页面上进行遍历显示
List<Integer> pageNumList = new ArrayList<Integer>();
int i = firstPageNum;
while (i <= lastPageNum) {
pageNumList.add(i);
i++;
}
this.getJspContext().setAttribute("pageNumList", pageNumList,
PageContext.REQUEST_SCOPE);
if (firstPageNum > partPageCount) {
this.getJspContext().setAttribute("beforeArrow", 1,
PageContext.REQUEST_SCOPE);
int beforePartFirstPageNum = firstPageNum - partPageCount;
this.getJspContext().setAttribute("beforePartFirstPageNum",
beforePartFirstPageNum, PageContext.REQUEST_SCOPE);
}
if (currentPage > 1) {
this.getJspContext().setAttribute("beforePage", 1,
PageContext.REQUEST_SCOPE);
}
if (currentPage < pageCount) {
this.getJspContext().setAttribute("afterPage", 1,
PageContext.REQUEST_SCOPE);
}
if (lastPageNum < pageCount) {
this.getJspContext().setAttribute("afterArrow", 1,
PageContext.REQUEST_SCOPE);
int afterPartFirstPageNum = firstPageNum + partPageCount;
this.getJspContext().setAttribute("afterPartFirstPageNum",
afterPartFirstPageNum, PageContext.REQUEST_SCOPE);
}
// 直接将标签间文字输出到页面上
this.getJspBody().invoke(null);
}
public PageInfo getPageInfo() {
return pageInfo;
}
public void setPageInfo(PageInfo pageInfo) {
this.pageInfo = pageInfo;
}
public String getRequestPath() {
return requestPath;
}
public void setRequestPath(String requestPath) {
this.requestPath = requestPath;
}
}
6.写一个共同的分页操作的jsp,得到当前第几页、共几条记录、上一页、下一页、跳转到第几页的链接。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<style>
<!--
.page {
PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; MARGIN: 3px; PADDING-TOP: 13px; TEXT-ALIGN: right; margin-bottom:10px;margin-right:20px;float:right;
}
.page A {
BORDER-RIGHT: #eee 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #eee 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 2px; MARGIN: 2px; BORDER-LEFT: #eee 1px solid; COLOR: #036cb4; PADDING-TOP: 2px; BORDER-BOTTOM: #eee 1px solid; TEXT-DECORATION: none
}
.page A:hover {
BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; BORDER-LEFT: #999 1px solid; COLOR: #666; BORDER-BOTTOM: #999 1px solid
}
.page A:active {
BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; BORDER-LEFT: #999 1px solid; COLOR: #666; BORDER-BOTTOM: #999 1px solid
}
.page .current {
BORDER-RIGHT: #036cb4 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #036cb4 1px solid; PADDING-LEFT: 5px; FONT-WEIGHT: bold; PADDING-BOTTOM: 2px; MARGIN: 2px; BORDER-LEFT: #036cb4 1px solid; COLOR: #fff; PADDING-TOP: 2px; BORDER-BOTTOM: #036cb4 1px solid; BACKGROUND-COLOR: #036cb4
}
.page .disabled {
BORDER-RIGHT: #eee 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #eee 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 2px; MARGIN: 2px; BORDER-LEFT: #eee 1px solid; COLOR: #ddd; PADDING-TOP: 2px; BORDER-BOTTOM: #eee 1px solid
}
-->
</style>
<c:if test="${pageInfo.recordCount>1}">
<div class="page">
<form
action="${requestPath}"
method="post">
共${requestScope.pageInfo.recordCount}条记录
第${requestScope.pageInfo.currentPage}/${requestScope.pageInfo.pageCount}页
<c:if test="${requestScope.beforeArrow==1}">
<a
href="${requestScope.requestPath}&pageNum=${requestScope.beforePartFirstPageNum}"><<</a>
</c:if>
<c:if test="${requestScope.beforePage==1}">
<a
href="${requestScope.requestPath}&pageNum=${requestScope.pageInfo.currentPage - 1}">上一页</a>
</c:if>
<c:forEach items="${requestScope.pageNumList}" var="pageNum">
<a href="${requestScope.requestPath}&pageNum=${pageNum}" <c:if test="${pageNum == requestScope.pageInfo.currentPage}"> style="background:#b7daf1" </c:if>>${pageNum}</a>
</c:forEach>
<c:if test="${requestScope.afterPage==1}">
<a
href="${requestScope.requestPath}&pageNum=${requestScope.pageInfo.currentPage + 1}">下一页</a>
</c:if>
<c:if test="${requestScope.afterArrow==1}">
<a
href="${requestScope.requestPath}&pageNum=${requestScope.afterPartFirstPageNum}">>></a>
</c:if>
<input type="text" name="pageNum" style="width: 24px">
<input type="submit" value="Go" style="width: 30px;text-align:center;">
</form>
</div>
</c:if>
7、写一个自定义标签库:
<tag>
<name>pageSearchTag</name>
<tag-class>com.lfl.toolUtil.PageSearchTag</tag-class>
<attribute>
<name>pageInfo</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>requestPath</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<body-content>scriptless</body-content>
</tag>
8.jsp调用
<my:pageSearchTag pageInfo="${pageInfo}"
requestPath="wind!custlist?result=1${pageurl}">
<jsp:include page="page.jsp"></jsp:include>
</my:pageSearchTag>
本文介绍了如何在使用jdbc连接SQLServer的JavaWeb项目中实现分页查询。提供了一个PageInfo类用于存储分页信息,并通过PageSearchUtil类处理分页查询的通用操作。该类考虑了SQLServer的不同版本,使用了row_number()函数进行排序和分页,同时给出了Action代码和自定义标签的使用示例。

2632

被折叠的 条评论
为什么被折叠?



