Teambiz中分頁之后臺處理
作者:何楊
撰寫日期:2012年2月25日
版本:1.00
更新日期:
第一部分:功能說明
分頁是Web程序的常見功能之一,此文主要講述后臺對分頁功能的處理。
第二部分:核心組件
名稱 | 路徑 | 說明 |
BaseService | teambiz\src\com\ibm\heyang\service\base\BaseService.java | 此抽象類是諸Service類的基類,它提供了專用于分頁的函數pagedSearch,用戶只需傳入相應的SQL語句,RequestParamMap實例和dao實例即可完成分頁功能,實際上后兩者一個是在AjaxAction中自動生成的,一個是Sping中配置的,因此,用戶只需書寫正確的查詢SQL語句即可。 由于DB2數據庫分頁操作的特殊性,它需要分頁時加入排序項,因此若數據源是DB2,那么請換用功能相似的pagedSearch4DB2函數。 |
JdbcDao | teambiz\src\com\ibm\heyang\dao\base\JdbcDao.java | 此抽象類是諸Dao類的基類,它提供了getSqlCount,pageSearchList兩個函數以實現分頁功能,前者用于得到結果集的總數,后者用于取得某一頁的結果集。 若數據庫是DB2,請換用功能相似的pageSearchList4DB2。 |
第三部分:關鍵代碼說明
1. BaseService中的pagedSearch函數:
public String pagedSearch(String sql,RequestParamMap paramMap,JdbcDao dao) throws Exception{
int currentPage=Integer.parseInt(paramMap.getParamValue("start"));
int pageSize=Integer.parseInt(paramMap.getParamValue("pageSize"));
StringBuilder sb=new StringBuilder();
sb.append("<currentPage>"+currentPage+"</currentPage>");
// 取得總記錄數
long recordCount=dao.getSqlCount(sql);
sb.append("<recordCount>"+recordCount+"</recordCount>");
// 得到總頁數
long pageCount=0;
if((recordCount % pageSize)==0){
pageCount=recordCount/pageSize;
}
else{
pageCount=recordCount/pageSize+1;
}
sb.append("<pageCount>"+pageCount+"</pageCount>");
NameValueList nvList=dao.pageSearchList(sql,currentPage*pageSize, (currentPage+1)*pageSize);
sb.append(nvList.asXML());
return sb.toString();
}
這個函數對數據庫進行了兩次查詢,一次是取出SQL語句能得到的記錄總數,一次是取出當前頁的數據,另外從paramMap中取出了當前頁和一頁可以容納的記錄數等數據,有了這些數據,進行一點計算,就能獲得前臺頁面需要的當前頁,總記錄數,頁數和當前頁記錄等數據,最后此函數將所有數據都變換為XML格式的字符串。
2. JdbcDao的getSqlCount函數。
public int getSqlCount(String sql) throws Exception{
RecordCounter rc=new RecordCounter(sql,this.getJdbcTemplate());
return rc.getCount();
}
這個類利用RecordCounter類對SQL語句進行了一定程序的處理,然后取出這個SQL語句能查詢出的記錄總數量,RecordCounter類代碼如下:
public class RecordCounter{
private String sql;
private JdbcTemplate jdbcTemplate;
/**
* 構造函數
* @param sql
* @param jdbcTemplate
*/
public RecordCounter(String sql,JdbcTemplate jdbcTemplate){
this.sql=sql;
this.jdbcTemplate=jdbcTemplate;
}
/**
* 得到SQL語句查詢到的記錄數,對外的關鍵語句
* @author: 何楊(heyanghy@cn.ibm.com)
* @date : Apr 23, 2011
* @time : 11:09:35 AM
* @return
*/
public int getCount() throws Exception{
StringBuilder sb=new StringBuilder();
sb.append(" select ");
sb.append(" count(*) as recordCount ");
sb.append(" from ("+sql+") t ");
String sql=sb.toString();
List<?> ls = jdbcTemplate.query(sql, (new IntegerRowMapper()));
Integer i=(Integer)ls.get(0);
return i.intValue();
}
}
以上代碼路徑:teambiz\src\com\ibm\heyang\dao\rowmapper\RecordCounter.java
3. JdbcDao類的fetchPageRecords和fetchPageRecords4DB2函數。
下面兩個函數用于取出分頁的數據,按照數據庫的不同使用不同的部分或是換用不同的函數。
/**
* 查詢分頁數據,如果是Oracle則放開上面一段,如果是MySql則放開下面一段
* @author: 何楊(heyanghy@cn.ibm.com)
* @date : Mar 29, 2011
* @time : 3:34:44 PM
* @param start
* @param end
* @param sql
* @param mapper
* @return
*/
protected final List<?> fetchPageRecords(int start,int end,String sql,RowMapper mapper){
StringBuilder sb=new StringBuilder();
// Oracle
/*sb.append(" Select ");
sb.append(" * ");
sb.append(" from ");
sb.append(" ( ");
sb.append(" Select ");
sb.append(" t01.*, ");
sb.append(" rownum as newRowNum ");
sb.append(" from ");
sb.append(" ( ");
sb.append(sql);
sb.append(" ) t01 ");
sb.append(" where ");
sb.append(" rownum<='"+end+"' ");
sb.append(" ) ");
sb.append(" where ");
sb.append(" newRowNum>'"+start+"' ");*/
// MySql
sb.append(sql+" limit "+start+","+(end-start));
String sql2=sb.toString();
return this.getJdbcTemplate().query(sql2,mapper);
}
/**
* 專門為DB2制作的查詢分頁數據,特殊的地方是比上面的函數多了一個Order by
* @param start
* @param end
* @param sql
* @param orderBy
* @param mapper
* @return
*/
protected final List<?> fetchPageRecords4DB2(int start,int end,String sql,String orderBy,RowMapper mapper){
StringBuilder sb=new StringBuilder();
// Db2
sb.append(" Select ");
sb.append(" * ");
sb.append(" from ");
sb.append(" ( ");
sb.append(" Select ");
sb.append(" table01.*, ");
sb.append(" ROW_NUMBER() OVER(ORDER BY "+orderBy+" ) AS ROWNUM ");
sb.append(" from ");
sb.append(" ( ");
sb.append(sql);
sb.append(" ) table01 ) ");
sb.append(" where ");
sb.append(" ROWNUM >"+start+" and ");
sb.append(" ROWNUM <="+end+" ");
String sql2=sb.toString();
return this.getJdbcTemplate().query(sql2,mapper);
}
第四部分:使用步驟
步驟 | 說明 | 參照 |
在Dao類中編寫需要進行分頁查詢的SQL語句,并用函數進行包裝。 | 建議對SQL進行良好的整形。 | teambiz\src\com\ibm\heyang\dao\RelationDao.java中的getSentRelationSql函數。 |
在Service類中撰寫調用dao中的分頁查詢函數 | 無 | teambiz\src\com\ibm\heyang\service\RelationService.java中的pagedSearchMySentRelation函數。 |
在Action中調用Service中的分頁查詢函數 | 如果需要在paramMap中增加新的參數,可以使用com.ibm.heyang.action.base.RequestParamMap類的addParam函數 | teambiz\src\com\ibm\heyang\action\relation\SearchSentRealationAction.java類 |
第五部分:小結
后臺的分頁處理,實際上需要程序員動腦筋的地方就是SQL語句的編寫,其它都是固定模式的操作,TeamBiz通過BaseService和JDBCdao兩個類中相應函數的幫助,固化了這些固定的部分,程序員只要正確調用即可,這在一定程度上減輕了程序員的工作量,降低了人為出錯的可能。
通過不同分頁SQL語句的采用,TeamBiz能適應三種數據庫,Oracle,MySQL和Db2,如果要增添更多數據庫的支持,對分頁SQL進行改寫即可。