前文说到,新项目中,用到的是SpringMVC + jdbcTemplate,前台是EasyUI,发现同事以前封装分页是逻辑分页,于是,自己动手封装了下物理分页。
这个是核心分页实体:
import java.io.Serializable; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.springframework.jdbc.core.JdbcTemplate; /** * 分页实体 * @author lyh * @version 2013-10-10 * @see Pagination * @since */ public class Pagination implements Serializable { /** * 序列号<br> */ private static final long serialVersionUID = -2554565760258955645L; /** * 每页显示的记录数 */ private int numPerPage; /** * 记录总数 (命名必须为total 对应easyui分页) */ private int total; /** * 总页数 */ private int totalPages; /** * 当前页码 */ private int currentPage; /** * 记录起始行数 */ private int startIndex; /** * 记录结束行数 */ private int lastIndex; /** * 结果集存放List (命名必须为rows 对应easyui分页) */ private List<Map<String,Object>> rows; /** * 构造函数 * @param sql sql语句 * @param currentPage 当前页码 * @param numPerPage 每页显示记录数 * @param jdbcTemplate JdbcTemplate实例 */ public Pagination(String sql, int currentPage, int numPerPage, JdbcTemplate jdbcTemplate) { if (jdbcTemplate == null) { throw new IllegalArgumentException( "jdbcTemplate is null , pls initialize ... "); } else if (StringUtils.isBlank(sql)) { throw new IllegalArgumentException("sql is blank , pls initialize ... "); } //设置每页显示记录数 setNumPerPage(numPerPage); //设置当前页数 setCurrentPage(currentPage); //计算总记录数SQL StringBuffer totalSQL = new StringBuffer(" select count(1) from ( "); totalSQL.append(sql); totalSQL.append(" ) "); //总记录数 setTotal(jdbcTemplate.queryForInt(totalSQL.toString())); //计算总页数 setTotalPages(); //计算起始行数 setStartIndex(); //计算结束行数 setLastIndex(); //拼装oracle的分页语句 (其他DB修改此处的分页关键词即可) StringBuffer paginationSQL = new StringBuffer(" select * from ( "); paginationSQL.append(" select row_limit.*,rownum rownum_ from ( "); paginationSQL.append(sql); paginationSQL.append(" ) row_limit where rownum <= " + lastIndex); paginationSQL.append(" ) where rownum_ > " + startIndex); //装入结果集(key转为小写) setRows(ConvertMapkey.listKeyToLower(jdbcTemplate.queryForList( paginationSQL.toString()))); } /** * 根据总记录数和每页显示记录数 计算总页数 * * @see */ private void setTotalPages() { if (total % numPerPage == 0) { this.totalPages = total / numPerPage; } else { this.totalPages = (total / numPerPage) + 1; } } /** * 根据当前页和每页显示记录条数 计算记录开始行数 * * @see */ private void setStartIndex() { this.startIndex = (currentPage - 1) * numPerPage; } /** * 计算记录结束行数 * * @see */ private void setLastIndex() { if (total < numPerPage) { this.lastIndex = total; } else if ((total % numPerPage == 0) || (total % numPerPage != 0 && currentPage < totalPages)) { this.lastIndex = currentPage * numPerPage; } else if (total % numPerPage != 0 && currentPage == totalPages) { this.lastIndex = total; } } //setter and getter public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getNumPerPage() { return numPerPage; } public void setNumPerPage(int numPerPage) { this.numPerPage = numPerPage; } public List<Map<String,Object>> getRows() { return rows; } public void setRows(List<Map<String,Object>> rows) { this.rows = rows; } public int getTotalPages() { return totalPages; } public int getTotal() { return total; } public void setTotal(int total) { this.total = total; } public int getStartIndex() { return startIndex; } public int getLastIndex() { return lastIndex; } }
Map转化工具类:
public class ConvertMapkey { /** * 把map对象的key全部转为小写形式 * @param map * @return */ public static Map<String, Object> keyToLower(Map<String, Object> map) { Map<String, Object> r = new HashMap<String, Object>(); if (map == null || map.size() == 0) return r; for (Map.Entry<String, Object> entry : map.entrySet()) { r.put(entry.getKey().toLowerCase(), entry.getValue()); } return r; } /** * 把list map中map对象的key全部转为小写形式 * @param listmap * @return */ public static List<Map<String, Object>> listKeyToLower(List<Map<String, Object>> listmap) { List<Map<String, Object>> r = new ArrayList<Map<String, Object>>(); if (listmap == null || listmap.size() == 0) return r; for (Map<String, Object> map : listmap) { r.add(keyToLower(map)); } return r; } }
DAO层 \ Service层:
return new Pagination(sqlFetchRows, page, rows, jdbcTemplate);
Controller层:
@RequestMapping(value = "/list_school") @ResponseBody public Pagination listSchool(HttpServletRequest request) { Pagination p = null; try { int page = Integer.parseInt(request.getParameter("page")); int rows = Integer.parseInt(request.getParameter("rows")); String school_code = request.getParameter("s_school_code"); String school_name = request.getParameter("s_school_name"); //page:当前页 rows:每页显示记录条数 区别结果集存放List-rows p = schoolService.pageData(page, rows, school_id, school_code, school_name); } catch (Exception e) { logger.error(e); } return p; }
注意:Controller返回的 Pagination实体在会转为JSON(故实体中一定不能含有jdbcTemplate字段,jdbcTemplate只能通过方法形式注入),然后在EasyUi中展示。
通过FireFox 可以发现上述返回的分页实体的JSON。
JS部分:
// 查询 $('#btn_02010100').click(function() { $('#basedg').datagrid('load'); });
$('#basedg').datagrid({ animate: true, //是否动画展开折叠 checkbox: true, //全选复选框 checkOnSelect: true, //选中复选框的同时选中行 selectOnCheck: true, //选中行的同时选中复选框 singleSelect: false, //是否单选 collapsible: true, //是否可折叠 height: 'auto', //自动高度 iconCls: 'icon-save', //样式图标 idField: 'school_id', //主索引,唯一标识字段 loadMsg: '数据载入中,请稍候......', maximizable: true, nowrap: true, //截断内文 pagination: true, //分页 pageList: [10,15,20,25,30], rownumbers: true, //是否显示列数, url: basePath + '/school/list_school', frozenColumns: [[ {field:'ck',checkbox:true}, {field:'school_id',title:'唯一id',hidden:true}, {field:'school_code',title:'学校代码',width:80}, {field:'school_name',title:'学校名称',width:200} ]], columns: [[ {field:'schooling_length',title:'学制',width:100}, {field:'telephone',title:'联系电话',width:120}, {field:'school_address',title:'学校地址',width:300}, {field:'establishment_date',title:'建校年月',width:80, formatter:function (value) { return value == null ? '' : (new Date(value).format('yyyy-MM-dd')); } } ]], onBeforeLoad: function (param) { param.s_school_code = $('#s_school_code').searchbox('getValue'); param.s_school_name = $('#s_school_name').searchbox('getValue'); } }); }
JSP页面:
<table id="basedg" toolbar="#toolbar" pagination="true"></table> <div id="toolbar"> <div id="searchbar"> <table cellspacing="0" cellpadding="0"> <tr> <td>查询条件:</td> <td> <input id="s_school_code" class="easyui-searchbox" data-options="prompt:'学校代码'"></input> </td> <td> <input id="s_school_name" class="easyui-searchbox" data-options="prompt:'学校名称'"></input> </td> </tr> </table> </div> <a href="javascript:void(0)" id="btn_02010100" class="easyui-linkbutton" iconCls="icon-search" plain="true">查询</a> </div>
最终效果:
每次查询时的触发SQL如下:
log Begining method: com.ruhuiyun.studentmanager.service.SchoolService.pageData 2013-10-11 10:40:18,345 [qtp14565508-22] DEBUG [org.springframework.jdbc.core.JdbcTemplate] - Executing SQL query [ select count(1) from ( SELECT school_id, school_code, school_name, schooling_length, school_address, telephone, establishment_date FROM T_SCHOOL WHERE 1 = 1 AND instr(school_name, '无锡') > 0 ) ] 2013-10-11 10:40:18,349 [qtp14565508-22] DEBUG [org.springframework.jdbc.core.JdbcTemplate] - Executing SQL query [ select * from ( select row_limit.*,rownum rownum_ from ( SELECT school_id, school_code, school_name, schooling_length, school_address, telephone, establishment_date FROM T_SCHOOL WHERE 1 = 1 AND instr(school_name, '无锡') > 0 ) row_limit where rownum <= 2 ) where rownum_ > 0] 2013-10-11 10:40:18,353 [qtp14565508-22] INFO [com.ruhuiyun.studentmanager.aop.LogAdvice] - log Ending method: com.ruhuiyun.studentmanager.service.SchoolService.pageData
一曲终了~~