读书人

displayTags大数据量分页领航

发布时间: 2012-12-23 11:28:15 作者: rapoo

displayTags大数据量分页导航

?

李楠注:
????这个内容我还没有测试过,打算以后分别用mysql,mssql,oracle10g测试一下,
数据量分别为1万,2万,10万,100万。这里先把此文档保存下来。
????关注这个内容,主要是这个功能要经常使用,并且,每个框架的实现都不相同(比如hibernate,ibatis)。
这次,是因为我在分析ibatis的框架,而听说ibatis实现的PaginatedList接口在数据量不超过2万的时候,
可以使用,但遇到大数据量的时候会有问题。据说在一个30万行的表里翻页,
一次select用了363.031second。如果真是这样的话,只好自己实现这个接口了。
????以下,是文章的内容:
----------------------------------------------

由于displayTag只处理数据的显示,传递给他多少数据,它会根据数据的记录数及其每页显示多少计算出需要的页数,但是在处理大数据量集合的时候,会遇到问题,就是将所有的数据传递给displayTag表格显示标签变得不现实也没有必要,如何既能够用到dispalyTag强大的显示功能,用能够很好的处理大数据量的
显示和分页功能呢?


当我遇到这个问题的时候,感到无从下手,因为我当时并不是很熟悉displaytag,更不要提它的深层次的处理机制问题了,嘿嘿!于是我就开始在群里请教高人,未果,无奈之余我只有借助网络,哈,我不停的变换关键词进行搜索,结果发现不止是我一个人遇到此问题啊,那是千千万万啊(一点都不夸张)!在那些五花八门的答案中我开始筛选,实验。。。

最终,根据displayTag官方文档的推荐和网友们的建议,我做开始了解决这个问题的尝试(虽然之前我遇到这个问题的时候,就先请教了我的一个同事,但他给我的建议我感觉太麻烦了,改动比较大,于是就下决心一定自己解决这个问题啦!)

首先我了解到displaytag1.0实在是太傻了,每次分页还需要将所有数据一次载入,效率低到无法忍受:)而displaytag1.1就不同了,1.1版最大的改进可以说是终于支持了大家期待以久的分次加载功能了,想显示多少数据就载入多少数据.1.1版本支持两种方式的分页,第一种是实现其org.displaytag.pagination.PaginatedList 接口,第二种是在页面和后台同时做修改来实现分页功能.在网上关于第二种分页的使用方法介绍的非常多,而且官方文档上面写的也比较详细,所以在这里我主要介绍自己是如何使用第一种方式进行分页的,且这种方式也是官方推荐分页方式:

首先写一个org.displaytag.pagination.PaginatedList 接口的实现类:
//package com.greatroad.webapp.paging;

import java.util.List;

import org.displaytag.pagination.PaginatedList;
import org.displaytag.properties.SortOrderEnum;

/**
* PaginatedListImpl
* User: zhangyd
* Date: 2007-10-20
* Time: 20:35:18
*
* totalNum 所有条目数目
* currentPage 当前所在页号
* objectsPerPage 每页显示条数
* list 此页所需要显示的数据
*/
public class PaginatedListHelper implements PaginatedList{
??????private List list;
??????private int pageNumber = 1;
??????private int objectsPerPage = 20;
??????private int fullListSize = 0;
??????private String sortCriterion;
??????private SortOrderEnum sortDirection;
??????private String searchId;

??????public List getList() {
??????????return list;
??????}

??????public void setList(List list) {
??????????this.list = list;
??????}

??????public int getPageNumber() {
??????????return pageNumber;
??????}

??????public void setPageNumber(int pageNumber) {
??????????this.pageNumber = pageNumber;
??????}

??????public int getObjectsPerPage() {
??????????return objectsPerPage;
??????}

??????public void setObjectsPerPage(int objectsPerPage) {
??????????this.objectsPerPage = objectsPerPage;
??????}

??????public int getFullListSize() {
??????????return fullListSize;
??????}

??????public void setFullListSize(int fullListSize) {
??????????this.fullListSize = fullListSize;
??????}

??????public String getSortCriterion() {
??????????return sortCriterion;
??????}

??????public void setSortCriterion(String sortCriterion) {
??????????this.sortCriterion = sortCriterion;
??????}

??????public SortOrderEnum getSortDirection() {
??????????return sortDirection;
??????}

??????public void setSortDirection(SortOrderEnum sortDirection) {
??????????this.sortDirection = sortDirection;
??????}

??????public String getSearchId() {
??????????return searchId;
??????}

??????public void setSearchId(String searchId) {
??????????this.searchId = searchId;
??????}

}
然后在使用的时候只需要创建此类的一个实例,且将所需要的参数通过set方法赋值进去就可以了,比如我在XXXController.java中是这样实现的(注意加粗的部分):

package com.greatroad.webapp.action;

import java.text.SimpleDateFormat;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.displaytag.pagination.PaginatedList;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.greatroad.Constants;
import com.greatroad.model.Station;
import com.greatroad.service.CardhistorydataManager;

import com.greatroad.service.StationManager;
import com.greatroad.webapp.paging.PaginatedListHelper;

public class CardhistorydataController implements Controller {
private final Log log = LogFactory.getLog(CardhistorydataController.class);

private CardhistorydataManager cardhistorydataManager = null;

public void setCardhistorydataManager(
?????CardhistorydataManager cardhistorydataManager) {
????this.cardhistorydataManager = cardhistorydataManager;
}

private StationManager stationManager = null;

public void setStationManager(StationManager stationManager) {
????this.stationManager = stationManager;
}

public ModelAndView handleRequest(HttpServletRequest request,
????????????????????????????????????????HttpServletResponse response)
??????throws Exception {
??????????if (log.isDebugEnabled()) {
??????????????log.debug("entering 'handleRequest' method...");
??????????}

??????????Object[] o = new Object[4];
??????????String personId = request.getParameter("person");
??????????String d1 = request.getParameter("starttime");
??????????String d2 = request.getParameter("endtime");
???????
??????????SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
???????
??????????if(personId!=null && personId.length()>0)
???????????o[0] = personId;
??????????if(d1!=null && d1.length()>0)
???????????o[1] = sdf.parse(d1);
??????????if(d2!=null && d2.length()>0)
???????????o[2] = sdf.parse(d2);
// ///////////////////////////////////////////////////////
??????????Station station = new Station();
??????????String stationId = request.getParameter("stationname");
??????????if(stationId!=null && stationId.length()>0){
???????????station = stationManager.getStation(stationId);
???????????o[3] = stationId;
???????????request.setAttribute("Stationid", stationId);
??????????}
???????????List stationList = stationManager.getStations(null);
???????????if(stationList != null && stationList.size()>0){
????????????request.setAttribute("stationlist", stationList);
???????????}
// /////////////////////////////////////////////////////////////////////////////
????????/*
??????* 其中request中的page参数为displaytag中的默认当前页数,当然也可以使用*TableTagParameters.SORT_AMOUNT_PAGE来表示当前页数
??????*/
????????int pageSize;
????????if (request.getParameter("pageSize") != null
??????????&& !"".equals(request.getParameter("pageSize"))) {
?????????pageSize = Integer.parseInt(request.getParameter("pageSize"));
????????} else {
?????????pageSize = 15;
????????}

????????int page = 1;
????????if (request.getParameter("page") != null
??????????&& !"".equals(request.getParameter("page"))) {
?????????page = Integer.parseInt(request.getParameter("page"));
????????} else {
?????????page = 1;
????????}

????????int fromIndex = (page - 1) * pageSize;
//??????int toIndex = fromIndex + pageSize;
????????int toIndex = pageSize;
????????// 获得每次查询的总记录数
????????int ListSize = cardhistorydataManager.countListSize(o);//DAO中实现

????????// 此页要显示的list数据
????????List cardhistorydatas = null;

????????if (ListSize > 0) {
?????????cardhistorydatas = cardhistorydataManager.getCardhistorydatas(o, fromIndex, toIndex);//DAO中实现
????????} else {
?????????cardhistorydatas = null;
????????}
????????PaginatedList paginaredList = new PaginatedListHelper();
????????((PaginatedListHelper) paginaredList).setPageNumber(page);
????????if (cardhistorydatas != null && ListSize != 0) {
?????????// System.out.println("getFullListSize: " + ListSize);
?????????// 总共有多少数据,他会根据所有数目和每页数目自动统计页数
?????????((PaginatedListHelper) paginaredList).setFullListSize(ListSize);
?????????((PaginatedListHelper) paginaredList).setObjectsPerPage(pageSize);
?????????((PaginatedListHelper) paginaredList).setList(cardhistorydatas);
????????} else {
?????????((PaginatedListHelper) paginaredList).setFullListSize(0);
?????????((PaginatedListHelper) paginaredList).setList(null);
????????}
????????// 如果你只设定这几个参数,那么其余的参数将会默认为你实现类中所赋的初值
????????// 最后,你还需要将这个实例放入到request或session中去,好让displaytag知道这个是外部分页
//????????request.setAttribute("cardhistorydataList", paginaredList);
////////////////////////////////////////////////////////////////////////////////

??????????return new ModelAndView("cardhistorydataList", Constants.CARDHISTORYDATA_LIST, paginaredList);
??????}
}
当然还有相关的一些地方需要改动,如果你能做的这一步,其余的那些已经不是问题了^!^另外再强调一点:页面无需任何改动哦!

参考文献:http://displaytag.sourceforge.net/11/

读书人网 >编程

热点推荐