大量查询的数据耗时比较严重,而且为了更方便的查询和展示用户所需要的数据,项目使用到了分页查询,其主要原理是使用MySQL的limit关键字。
首先定义了一个pager实体类,包括以下属性:
private int pageSize; //每页显示多少条记录
private int currentPage; //当前是第几页数据
private int totalRecord; //一共多少条记录
private int totalPage; //一共多少页记录
private List dataList; //要显示的数据
当前端向servlet请求数据时,可以指定pageNum(第几页),pageSize(每页多少条记录),当然,也可以添加其他参数:指定main_id查询指定主分类的数据,指定sub_id查询指定二级分类的数据,指定id获取到指定一篇文章。这些查询条件被封装成article类型对象。Servlet调用ArticleService类的实例,查询文章数据。
在数据操作层ArticleDao中,有findArticle方法,传入参数Article searchModel, int pageNum, int pageSize查询到Pager
类型的分页信息。
首先,添加查询条件,组装sql查询语句:
StringBuilder sql = new StringBuilder("select a.*,m.name mname,s.name sname from article a left join maincategory m on a.main_id=m.id left join subcategory s on a.sub_id = s.id where 1=1 ");
StringBuilder countSql = new StringBuilder("select count(id) as totalRecord from article where 1=1 ");
if (id != 0 ) {
sql.append(" and a.id = ?");
countSql.append(" and id = ?");
paramList.add(id);
}
if (sub_id != 0 ) {
sql.append(" and a.sub_id = ? ");
countSql.append(" and sub_id = ? ");
paramList.add(sub_id);
}
if (main_id != 0 ) {
sql.append(" and a.main_id= ? ");
countSql.append(" and main_id = ? ");
paramList.add(main_id);
}
sql.append(" ORDER BY top desc,createdate desc ");
countSql.append(" ORDER BY top desc,createdate desc ");
// 起始索引
int fromIndex = pageSize * (pageNum - 1);
// 使用limit关键字,实现分页
sql.append(" limit " + fromIndex + ", " + pageSize);
第一条sql语句用到了三表连接查询,因为考虑到文章的二级分类可能为空,所以使用的是左外连接,以article表为基准,通过传进来的pageSize和pageNum算出数据库起始索引,指定为偏移量,将pageSize作为指定返回记录行的最大数目,通过limit关键字返回分页数据。查询使用的是jdbc的预处理,既可以提高执行速度尤其是多次操作数据库的情况,又能预防SQL注入,提高安全性。第二条sql语句,查询数据条数,作为总记录数,根据pageSize参数得到总页数,循环取出查询到的数据,封装成article对象,存到返回值pager对象的数据列表中,把该分页信息封装成pager对象返回。
jdbcUtil.getConnection(); // 获取数据库链接
// 获取总记录数
List<Map<String, Object>> countResult = jdbcUtil.findResult(countSql.toString(), paramList);
Map<String, Object> countMap = countResult.get(0);
int totalRecord = ((Number) countMap.get("totalRecord")).intValue();
// 获取查询的文章记录
List<Map<String, Object>> studentResult = jdbcUtil.findResult(sql.toString(), paramList);
if (studentResult != null) {
for (Map<String, Object> map : studentResult) {
Article s = new Article(map);
studentList.add(s);
}
}
int totalPage = totalRecord / pageSize; //记录总页数
if (totalRecord % pageSize != 0)
totalPage++;
result = new Pager<Article>(pageSize, pageNum,totalRecord, totalPage, studentList);
jsp页面使用jquery.pagination.js插件。这是个简单轻量级的分页插件,使用起来很容易,只要初始化一个实例,并设置总数量、翻页回调函数、其它参数就可以实现无刷新分页功能了
// 点击分页按钮以后触发的动作
function handlePaginationClick(new_page_index, pagination_container) {
$("#postForm").attr("action", "<%=context %>/servlet/PostlistServlet?role=1&pageNum=" + (new_page_index + 1));
$("#postForm").submit();
return false;
};
$(function () {
$("#News-Pagination").pagination(${result.totalRecord}, {
items_per_page:${result.pageSize}, // 每页显示多少条记录
current_page: ${result.currentPage} -1, // 当前显示第几页数据
num_display_entries: 3, // 分页显示的条目数
next_text: "下一页",
prev_text: "上一页",
num_edge_entries: 2, // 连接分页主体,显示的条目数
callback: handlePaginationClick
});
})