Pagination.java
package com.dxwind.common.bean;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import com.dxwind.common.support.DAORowMapper;
/**
* 分页函数
*/
public class Pagination<T> {
private static Log logger = LogFactory.getLog(Pagination.class);
private int dbType = 1;//1:mssql;2:mysql;3:oracle
/** 一页显示的记录数 */
private int numPerPage = 0;
/** 记录总数 */
private int totalRows = 0;
/** 总页数 */
private int totalPages = 0;
/** 当前页码 */
private int currentPage = 1;
/** 起始行数 */
private int startIndex = 0;
/** 结束行数 */
private int lastIndex = 0;
/** 指定类型结果列表 */
private List<T> resultList = null;
/** 未指定类型结果列表 */
private List<Map<String, Object>> resultMapList = null;
/** JdbcTemplate jTemplate */
private JdbcTemplate jdbcTemplate = null;
/** 查询sql语句 */
private String querySql = null;
/** 计数sql语句 */
private String countSql = null;
/** 是否优化 (sql中有多个from或多个order by时置为false) */
private boolean optimizeCountSql = true;
/** RowMapper */
private DAORowMapper<T> rowMapper = null;
/** SQL 绑定参数 */
private Object[] objs = null;
/**
* 缺省构造函数
*/
public Pagination() {}
public Pagination(String sql, int currentPage, int numPerPage, JdbcTemplate jdbcTemplate) {
setQuerySql(sql);
setNumPerPage(numPerPage);
setCurrentPage(currentPage);
this.jdbcTemplate = jdbcTemplate;
}
public Pagination(String sql, int currentPage, int numPerPage, JdbcTemplate jdbcTemplate, Object[] objs) {
setQuerySql(sql);
setNumPerPage(numPerPage);
setCurrentPage(currentPage);
this.jdbcTemplate = jdbcTemplate;
this.objs = objs;
}
public Pagination(String sql, int currentPage, int numPerPage, JdbcTemplate jdbcTemplate, DAORowMapper<T> rowMapper) {
setQuerySql(sql);
setNumPerPage(numPerPage);
setCurrentPage(currentPage);
this.jdbcTemplate = jdbcTemplate;
this.setRowMapper(rowMapper);
}
public Pagination(String sql, int currentPage, int numPerPage, JdbcTemplate jdbcTemplate, DAORowMapper<T> rowMapper, Object[] objs) {
setQuerySql(sql);
setNumPerPage(numPerPage);
setCurrentPage(currentPage);
this.jdbcTemplate = jdbcTemplate;
this.objs = objs;
this.setRowMapper(rowMapper);
}
public Pagination(int currentPage, int numPerPage, int totalRows, List<T> list){
setTotalRows(totalRows);
setNumPerPage(numPerPage);
setCurrentPage(currentPage);
setResultList(list);
setTotalPages();
}
public String getCountSql(String querySql){
StringBuffer sb = new StringBuffer("select count(*) from (");
sb.append(querySql);
sb.append(") z");
return sb.toString();
}
public String getCountFastSql(String querySql){
String sql = querySql.toLowerCase();
StringBuffer sb = new StringBuffer("select count(*) ");
int orderPos = sql.lastIndexOf("order by");
int fromPos = sql.indexOf("from");
if(orderPos > 0)
sb.append(sql.substring(fromPos, orderPos));
else
sb.append(sql.substring(fromPos));
return sb.toString();
}
/**
* 初始化
* @param sql 根据传入的sql语句得到一些基本分页信息
* @param currentPage 当前页
* @param numPerPage 每页记录数
* @param jdbcTemplate JdbcTemplate实例
*/
public void query() {
if (this.jdbcTemplate == null) {
throw new IllegalArgumentException(
"com.dxwind.common.bean.Pagination.jdbcTemplate is null,please initial it first. ");
} else if (querySql == null || querySql.equals("")) {
throw new IllegalArgumentException(
"com.dxwind.common.bean.Pagination.querySql is empty,please initial it first. ");
}
String totalSQL = countSql == null?(isOptimizeCountSql()?getCountFastSql(querySql):getCountSql(querySql)): countSql;
// 总记录数
try{
if(objs == null){
setTotalRows(jdbcTemplate.queryForInt(totalSQL));
}else{
setTotalRows(jdbcTemplate.queryForInt(totalSQL,objs));
}
}catch(Exception e){
logger.error(e.getMessage(),e);
}
// 计算总页数
setTotalPages();
// 计算起始行数
setStartIndex();
// 计算结束行数
setLastIndex();
if(this.dbType == 1){
// 处理mssql数据库的分页存储过程
CallableStatementCallback<Integer> cb = new CallableStatementCallback<Integer>() {
@Override
public Integer doInCallableStatement(CallableStatement cs)
throws SQLException, DataAccessException {
cs.setString(1, querySql);
cs.setInt(2, currentPage);
cs.setInt(3, numPerPage);
cs.registerOutParameter(4, Types.INTEGER);
cs.execute();
cs.getMoreResults();
ResultSet rs = cs.getResultSet();
if(rowMapper != null){
List<T> list = new ArrayList<T>();
while (rs.next()) {
list.add(rowMapper.mapRow(rs, 0));
}
setResultList(list);
rs.close();
}else{
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
ResultSetMetaData rsMeta = rs.getMetaData();
while (rs.next()) {
Map<String, Object> rowMap = new HashMap<String, Object>();
for(int i = 1; i <= rsMeta.getColumnCount(); i++){
rowMap.put(rsMeta.getColumnName(i), rs.getObject(i));
}
list.add(rowMap);
}
setResultMapList(list);
rs.close();
}
return cs.getInt(4);
}
};
try {
this.jdbcTemplate.execute("{call sp_pagination(?,?,?,?)}", cb);
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
}else{
StringBuffer paginationSQL = new StringBuffer();
if(this.dbType == 2){
// 构造mysql数据库的分页语句
paginationSQL.append("select * from ( ");
paginationSQL.append(querySql);
paginationSQL.append(" limit " + startIndex + "," + numPerPage);
paginationSQL.append(") z");
}else{
// 构造oracle数据库的分页语句
paginationSQL.append("SELECT * FROM ( ");
paginationSQL.append("SELECT temp.* ,ROWNUM num FROM ( ");
paginationSQL.append(querySql);
paginationSQL.append(" ) temp where ROWNUM <= " + lastIndex);
paginationSQL.append(" ) WHERE num > " + startIndex);
}
// 装入结果集List
String paginationQuerySQL = paginationSQL.toString();
try{
if(this.rowMapper != null){
if(this.objs == null){
setResultList(this.jdbcTemplate.query(paginationQuerySQL, this.rowMapper));
}else{
setResultList(this.jdbcTemplate.query(paginationQuerySQL, this.rowMapper, objs));
}
}else{
if(this.objs == null){
setResultMapList(this.jdbcTemplate.queryForList(paginationQuerySQL));
}else{
setResultMapList(this.jdbcTemplate.queryForList(paginationQuerySQL, objs));
}
}
}catch(Exception e){
logger.error(e.getMessage(),e);
}
}
}
/**
* 获取分页信息
* @return
*/
public PageInfo getPageInfo(){
if(this.getResultList() != null){
return new PageInfo(this.getTotalPages(), currentPage, this.getTotalRows(),
this.getResultList().size(), this.getNumPerPage());
}
if(this.getResultMapList() != null){
return new PageInfo(this.getTotalPages(), currentPage, this.getTotalRows(),
this.getResultMapList().size(), this.getNumPerPage());
}
return new PageInfo(this.getTotalPages(), currentPage, this.getTotalRows(), 0, this.getNumPerPage());
}
private void setRowMapper(DAORowMapper<T> rowMapper) {
this.rowMapper = rowMapper;
}
public RowMapper<T> getRowMapper() {
return rowMapper;
}
public void setQuerySql(String querySql) {
this.querySql = querySql;
}
public String getQuerySql() {
return querySql;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
if(currentPage > 0){
this.currentPage = currentPage;
}else{
this.currentPage = 1;
}
}
public int getNumPerPage() {
return numPerPage;
}
public void setNumPerPage(int numPerPage) {
this.numPerPage = numPerPage;
}
public List<T> getResultList() {
return this.resultList;
}
public void setResultList(List<T> resultList) {
this.resultList = resultList;
}
public List<Map<String, Object>> getResultMapList() {
return this.resultMapList;
}
public void setResultMapList(List<Map<String, Object>> resultMapList) {
this.resultMapList = resultMapList;
}
public int getTotalPages() {
return this.totalPages;
}
// 计算总页数
public void setTotalPages() {
if (totalRows % numPerPage == 0) {
this.totalPages = totalRows / numPerPage;
} else {
this.totalPages = (totalRows / numPerPage) + 1;
}
if(this.currentPage > this.totalPages) this.currentPage = this.totalPages;
if(this.currentPage < 1) this.currentPage = 1;
}
public int getTotalRows() {
return totalRows;
}
public void setTotalRows(int totalRows) {
this.totalRows = totalRows;
}
public int getStartIndex() {
return startIndex;
}
public void setStartIndex() {
this.startIndex = (currentPage - 1) * numPerPage;
}
public int getLastIndex() {
return lastIndex;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// 计算结束时候的索引
public void setLastIndex() {
/*if(currentPage==-1){//如果当前页为-1,则认为需要显示全部
this.lastIndex = totalRows;
return;
}*/
if (totalRows < numPerPage) {
this.lastIndex = totalRows;
} else if ((totalRows % numPerPage == 0)
|| (totalRows % numPerPage != 0 && currentPage < totalPages)) {
this.lastIndex = currentPage * numPerPage;
} else if (totalRows % numPerPage != 0 && currentPage == totalPages) {// 最后一页
this.lastIndex = totalRows;
}
}
public Object[] getObjs() {
return objs;
}
public void setObjs(Object[] objs) {
this.objs = objs;
}
public String getCountSql() {
return countSql;
}
public void setCountSql(String countSql) {
this.countSql = countSql;
}
public boolean isOptimizeCountSql() {
return optimizeCountSql;
}
public void setOptimizeCountSql(boolean optimizeCountSql) {
this.optimizeCountSql = optimizeCountSql;
}
}
DAORowMapper.java
package com.dxwind.common.support;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSetMetaData;
public class DAORowMapper<T> implements RowMapper<T> {
static protected enum ClassType {
STRING, INT, LONG, BOOLEAN, DOUBLE, UTILDATE, CALENDAR, SQLTIMESTAMP, SQLDATE, SQLTIME;
}
private Class<? extends T> rowObjClass;
private boolean direct;
static protected Map<String, String> classNameCastMap = new HashMap<String, String>();
static protected Map<String, DAORowMapper.ClassType> classNameMap = new HashMap<String, DAORowMapper.ClassType>();
static {
DAORowMapper.classNameCastMap.put("java.lang.String", ",java.lang.String,");
DAORowMapper.classNameCastMap.put("java.lang.Integer", ",int,java.lang.Integer,boolean,java.lang.Boolean,");
DAORowMapper.classNameCastMap.put("java.math.BigInteger", ",int,java.lang.Integer,boolean,java.lang.Boolean,");
DAORowMapper.classNameCastMap.put("java.lang.Long", ",long,java.lang.Long,int,java.lang.Integer,boolean,java.lang.Boolean,");
DAORowMapper.classNameCastMap.put("java.lang.Boolean", ",boolean,java.lang.Boolean,");
DAORowMapper.classNameCastMap.put("java.math.BigDecimal", ",double,java.lang.Double,long,java.lang.Long,int,java.lang.Integer,boolean,java.lang.Boolean,");
DAORowMapper.classNameCastMap.put("java.lang.Double", ",double,java.lang.Double,long,java.lang.Long,int,java.lang.Integer,boolean,java.lang.Boolean,");
DAORowMapper.classNameCastMap.put("java.lang.Float", ",double,java.lang.Double,long,java.lang.Long,int,java.lang.Integer,boolean,java.lang.Boolean,");
DAORowMapper.classNameCastMap.put("java.sql.Timestamp", ",java.sql.Timestamp,java.sql.Date,java.util.Calendar,java.util.Date,java.lang.String,");
DAORowMapper.classNameCastMap.put("java.sql.Date", ",java.sql.Timestamp,java.sql.Date,java.util.Calendar,java.util.Date,java.lang.String,");
DAORowMapper.classNameCastMap.put("java.sql.Time", ",java.sql.Time,java.util.Calendar,java.util.Date,java.lang.String,");
DAORowMapper.classNameMap.put("java.lang.String", ClassType.STRING);
DAORowMapper.classNameMap.put("int", ClassType.INT);
DAORowMapper.classNameMap.put("java.lang.Integer", ClassType.INT);
DAORowMapper.classNameMap.put("long", ClassType.LONG);
DAORowMapper.classNameMap.put("java.lang.Long", ClassType.LONG);
DAORowMapper.classNameMap.put("boolean", ClassType.BOOLEAN);
DAORowMapper.classNameMap.put("java.lang.Boolean", ClassType.BOOLEAN);
DAORowMapper.classNameMap.put("double", ClassType.DOUBLE);
DAORowMapper.classNameMap.put("java.lang.Double", ClassType.DOUBLE);
DAORowMapper.classNameMap.put("java.util.Date", ClassType.UTILDATE);
DAORowMapper.classNameMap.put("java.util.Calendar", ClassType.CALENDAR);
DAORowMapper.classNameMap.put("java.sql.Timestamp", ClassType.SQLTIMESTAMP);
DAORowMapper.classNameMap.put("java.sql.Date", ClassType.SQLDATE);
DAORowMapper.classNameMap.put("java.sql.Time", ClassType.SQLTIME);
}
public DAORowMapper(Class<? extends T> rowObjClass) {
super();
this.rowObjClass = rowObjClass;
this.direct = this.isDirectClass();
}
public DAORowMapper(Class<? extends T> rowObjClass, boolean direct) {
super();
this.rowObjClass = rowObjClass;
boolean directClass = this.isDirectClass();
this.direct = directClass ? true : direct;
}
private final boolean isDirectClass() {
if (this.rowObjClass == null) return false;
return DAORowMapper.classNameMap.get(this.rowObjClass.getName()) != null;
}
@SuppressWarnings(value = "unchecked")
public T mapRow(ResultSet rs, int index){
T object = null;
try {
Method[] methods = null;
//获取列数据
ResultSetWrappingSqlRowSetMetaData wapping = new ResultSetWrappingSqlRowSetMetaData(rs.getMetaData());
int columnCount = wapping.getColumnCount();
if (this.direct){
Object value = null;
int columnIndex = 1;
if(columnCount == 1){
String columnClassName = wapping.getColumnClassName(columnIndex);//列被封装的java类型名称
if (DAORowMapper.classNameCastMap.get(columnClassName).indexOf(this.rowObjClass.getName()) != -1 || this.rowObjClass.getName().equals("java.lang.Object")) {
DAORowMapper.ClassType classType = DAORowMapper.classNameMap.get(this.rowObjClass.getName());
if (classType != null){
if(rs.getObject(columnIndex) != null || classType == DAORowMapper.ClassType.STRING){
switch (classType) {
case STRING:
value = rs.getString(columnIndex);
if(value == null){
value = "";
}else{
value = rs.getString(columnIndex);
}
break;
case INT:
value = rs.getInt(columnIndex);
break;
case LONG:
value = rs.getLong(columnIndex);
break;
case BOOLEAN:
value = rs.getBoolean(columnIndex);
break;
case DOUBLE:
value = rs.getDouble(columnIndex);
break;
case UTILDATE:
value = new java.util.Date(rs.getTimestamp(columnIndex).getTime());
break;
case CALENDAR:
Calendar targetValue = Calendar.getInstance();
targetValue.setTimeInMillis(rs.getTimestamp(columnIndex).getTime());
value = targetValue;
break;
case SQLTIMESTAMP:
value = rs.getTimestamp(columnIndex);
break;
case SQLDATE:
value = rs.getDate(columnIndex);
break;
case SQLTIME:
value = rs.getTime(columnIndex);
break;
}
}
}
}
}
return (T)value;
}else{
object = this.rowObjClass.newInstance();
methods = this.rowObjClass.getMethods(); //获取数据保存对象所有的公开方法,包括继承的方法
for (int columnIndex = 0; columnIndex++ != columnCount;){
String columnClassName = wapping.getColumnClassName(columnIndex);//列被封装的java类型名称
//找到和当前字段名称一致的对象属性设置方法,然后赋值
String columnName = wapping.getColumnLabel(columnIndex);
for (Method method : methods) {
Object value = null;
//通过方法名以及参数类型来过滤掉不匹配的方法,过滤之后剩下的就是对应的 setter
String methodName = method.getName();
if (methodName != null && methodName.equalsIgnoreCase("set".concat(columnName))){
//获取参数类型
Class<?>[] params = method.getParameterTypes();
if (params.length == 1) {
if (DAORowMapper.classNameCastMap.get(columnClassName).indexOf("," + params[0].getName() + ",") != -1 || params[0].getName().equals("java.lang.Object")) {
DAORowMapper.ClassType classType = DAORowMapper.classNameMap.get(params[0].getName());
if (classType != null){
if(rs.getObject(columnIndex) != null || classType == DAORowMapper.ClassType.STRING){
switch (classType) {
case STRING:
value = rs.getString(columnIndex);
if(value == null){
value = "";
}else{
if(columnClassName.equals("java.sql.Timestamp")){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
value = sdf.format(rs.getTimestamp(columnIndex));
}else{
value = rs.getString(columnIndex);
}
}
break;
case INT:
value = rs.getInt(columnIndex);
break;
case LONG:
value = rs.getLong(columnIndex);
break;
case BOOLEAN:
value = rs.getBoolean(columnIndex);
break;
case DOUBLE:
value = rs.getDouble(columnIndex);
break;
case UTILDATE:
value = new java.util.Date(rs.getTimestamp(columnIndex).getTime());
break;
case CALENDAR:
Calendar targetValue = Calendar.getInstance();
targetValue.setTimeInMillis(rs.getTimestamp(columnIndex).getTime());
value = targetValue;
break;
case SQLTIMESTAMP:
value = rs.getTimestamp(columnIndex);
break;
case SQLDATE:
value = rs.getDate(columnIndex);
break;
case SQLTIME:
value = rs.getTime(columnIndex);
break;
}
}else{
break;
}
}
}
}
}
//执行 setter
if(value != null){
method.invoke(object, value);
break;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
object = null;
}
return object;
}
}
SQLSERVER实现分页的存储过程:
ALTER PROCEDURE [dbo].[sp_pagination]
@sqlstr varchar(4000), --查询字符串
@currentpage int, --第N页
@pagesize int, --每页行数
@recordCount int output
as
set nocount on
declare @P1 int --P1是游标的id
exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@recordCount output
set @currentpage=(@currentpage-1)*@pagesize+1
exec sp_cursorfetch @P1,16,@currentpage,@pagesize
exec sp_cursorclose @P1
set nocount off