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进行改写即可。