easyui中的分頁實現(支援MySQL,SQLServer,Oracle)
阿新 • • 發佈:2019-01-08
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,@[email protected] output set @currentpage=(@currentpage-1)*@pagesize+1 exec sp_cursorfetch @P1,16,@currentpage,@pagesize exec sp_cursorclose @P1 set nocount off