Teambiz中分頁之后臺處理
作者:何楊
撰寫日期:2012年2月25日
版本:1.00
更新日期:
第一部分:功能說明
分頁是Web程序的常見功能之一,此文主要講述后臺對分頁功能的處理。
第二部分:核心組件
名稱 | 路徑 | 說明 |
BaseService | teambiz\src\com\ibm\heyang\service\base\BaseService.java | 此抽象類是諸Service類的基類,它提供了專用于分頁的函數(shù)pagedSearch,用戶只需傳入相應(yīng)的SQL語句,RequestParamMap實(shí)例和dao實(shí)例即可完成分頁功能,實(shí)際上后兩者一個是在AjaxAction中自動生成的,一個是Sping中配置的,因此,用戶只需書寫正確的查詢SQL語句即可。 由于DB2數(shù)據(jù)庫分頁操作的特殊性,它需要分頁時(shí)加入排序項(xiàng),因此若數(shù)據(jù)源是DB2,那么請換用功能相似的pagedSearch4DB2函數(shù)。 |
JdbcDao | teambiz\src\com\ibm\heyang\dao\base\JdbcDao.java | 此抽象類是諸Dao類的基類,它提供了getSqlCount,pageSearchList兩個函數(shù)以實(shí)現(xiàn)分頁功能,前者用于得到結(jié)果集的總數(shù),后者用于取得某一頁的結(jié)果集。 若數(shù)據(jù)庫是DB2,請換用功能相似的pageSearchList4DB2。 |
第三部分:關(guān)鍵代碼說明
1. BaseService中的pagedSearch函數(shù):
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>");
// 取得總記錄數(shù)
long recordCount=dao.getSqlCount(sql);
sb.append("<recordCount>"+recordCount+"</recordCount>");
// 得到總頁數(shù)
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();
}
這個函數(shù)對數(shù)據(jù)庫進(jìn)行了兩次查詢,一次是取出SQL語句能得到的記錄總數(shù),一次是取出當(dāng)前頁的數(shù)據(jù),另外從paramMap中取出了當(dāng)前頁和一頁可以容納的記錄數(shù)等數(shù)據(jù),有了這些數(shù)據(jù),進(jìn)行一點(diǎn)計(jì)算,就能獲得前臺頁面需要的當(dāng)前頁,總記錄數(shù),頁數(shù)和當(dāng)前頁記錄等數(shù)據(jù),最后此函數(shù)將所有數(shù)據(jù)都變換為XML格式的字符串。
2. JdbcDao的getSqlCount函數(shù)。
public int getSqlCount(String sql) throws Exception{
RecordCounter rc=new RecordCounter(sql,this.getJdbcTemplate());
return rc.getCount();
}
這個類利用RecordCounter類對SQL語句進(jìn)行了一定程序的處理,然后取出這個SQL語句能查詢出的記錄總數(shù)量,RecordCounter類代碼如下:
public class RecordCounter{
private String sql;
private JdbcTemplate jdbcTemplate;
/**
* 構(gòu)造函數(shù)
* @param sql
* @param jdbcTemplate
*/
public RecordCounter(String sql,JdbcTemplate jdbcTemplate){
this.sql=sql;
this.jdbcTemplate=jdbcTemplate;
}
/**
* 得到SQL語句查詢到的記錄數(shù),對外的關(guān)鍵語句
* @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函數(shù)。
下面兩個函數(shù)用于取出分頁的數(shù)據(jù),按照數(shù)據(jù)庫的不同使用不同的部分或是換用不同的函數(shù)。
/**
* 查詢分頁數(shù)據(jù),如果是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制作的查詢分頁數(shù)據(jù),特殊的地方是比上面的函數(shù)多了一個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類中編寫需要進(jìn)行分頁查詢的SQL語句,并用函數(shù)進(jìn)行包裝。 | 建議對SQL進(jìn)行良好的整形。 | teambiz\src\com\ibm\heyang\dao\RelationDao.java中的getSentRelationSql函數(shù)。 |
在Service類中撰寫調(diào)用dao中的分頁查詢函數(shù) | 無 | teambiz\src\com\ibm\heyang\service\RelationService.java中的pagedSearchMySentRelation函數(shù)。 |
在Action中調(diào)用Service中的分頁查詢函數(shù) | 如果需要在paramMap中增加新的參數(shù),可以使用com.ibm.heyang.action.base.RequestParamMap類的addParam函數(shù) | teambiz\src\com\ibm\heyang\action\relation\SearchSentRealationAction.java類 |
第五部分:小結(jié)
后臺的分頁處理,實(shí)際上需要程序員動腦筋的地方就是SQL語句的編寫,其它都是固定模式的操作,TeamBiz通過BaseService和JDBCdao兩個類中相應(yīng)函數(shù)的幫助,固化了這些固定的部分,程序員只要正確調(diào)用即可,這在一定程度上減輕了程序員的工作量,降低了人為出錯的可能。
通過不同分頁SQL語句的采用,TeamBiz能適應(yīng)三種數(shù)據(jù)庫,Oracle,MySQL和Db2,如果要增添更多數(shù)據(jù)庫的支持,對分頁SQL進(jìn)行改寫即可。