数据量你造吗-JAVA分页
原创地址: http://www.cnblogs.com/Alandre/ (泥沙砖瓦浆木匠),需要转载的,保留下! Thanks
学习的心态第一,解行要相应。其实《弟子规》在“余力学文”当中,一开头就强调了这一个重点。“不力行,但学文,长浮华,成何人”,这个没有侥幸的,只要学了不去做,无形当中就会增长傲慢,自己不知道。-<弟子规>
Written In The Font
JAVA-Web 基础那块,我自己也准备.搞哪里,优化哪里然后带给大家终结.谢谢
分页虽易,好却难.数据量,怎么办?
Content
分页(Paging),就像个切面.能把这个切面好好的放进去也是种nice方式.
第一种:小数据量分页实现 (可广泛用于 门户型 网页快速开发等)
这种比较简单,这边我们模拟实现.
字段结构:
private int pageSize; //每页有多少条
private int rowCount; //总行数
private int pageCount;//总页数
private int currentPage; //当前页码
流程结构:

list.subList(index, (currentPage < pageCount) ? (index + pageSize) : rowCount);将小数据量集合,根据分页参数返回指定的list部分.这样,如果数据小的话,这样很方便的实现了分页功能.下面是JDK api里面对方法的解释:
subList(int fromIndex, int toIndex)
返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
分页工具类:
package jeffli_10; import java.util.ArrayList;
import java.util.List; /** 分页类:根据总记录数和分页大小对 {@link List} 进行分页处理 */
public class Pagination
{
public static final int DEFAULT_PAGE_SIZE = 10; private int rowCount;
private int currentPage;
private int pageSize;
private int pageCount; private List<?> list; public Pagination(List<?> list)
{
this(list, DEFAULT_PAGE_SIZE);
} public Pagination(List<?> list, int pageSize)
{
this.currentPage = 1;
this.list = list;
this.rowCount = list.size(); setPageSize(pageSize);
} private void adjustPageCount()
{
pageCount = (rowCount + pageSize - 1) / pageSize;
} /** 获取要分页的 {@link List} */
public List<?> getList()
{
return list;
} /** 获取的 {@link List} 当前页内容 */
public List<?> getCurrentList()
{
List<?> currentList = null; if(currentPage >= 1 && currentPage <= pageCount)
{
int index = (currentPage - 1) * pageSize;
currentList = list.subList(index, (currentPage < pageCount) ? (index + pageSize) : rowCount);
} return currentList;
} /** 获取当前页号(从 1 开始) */
public int getCurrentPage()
{
return currentPage;
} /** 设置当前页号(从 1 开始) */
public boolean setCurrentPage(int page)
{
if(page >= 1 && page <= pageCount)
{
currentPage = page;
return true;
} return false;
} /** 转到下一页 */
public boolean nextPage()
{
return setCurrentPage(currentPage + 1);
} /** 转到上一页 */
public boolean prePage()
{
return setCurrentPage(currentPage - 1);
} /** 获取分页大小 */
public int getPageSize()
{
return pageSize;
} /** 设置分页大小 */
public void setPageSize(int size)
{
if(size <= 0)
size = DEFAULT_PAGE_SIZE; int index = (currentPage - 1) * pageSize; pageSize = size; if(index > pageSize)
currentPage = (index + pageSize - 1) / pageSize;
else
currentPage = 1; adjustPageCount();
} /** 获取总页数 */
public int getPageCount()
{
return pageCount;
} public static void main(String[] args)
{
final int PAGE_SIZE = 10;
final int LIST_SIZE = 39; List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i <= LIST_SIZE; i++)
list.add(i); Pagination pg = new Pagination(list, PAGE_SIZE); for(int i = 1; i <= pg.getPageCount(); i++)
{
pg.setCurrentPage(i);
System.out.println(pg.getCurrentList());
}
} }
RUN,你会看到 OUTPUTS:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
[31, 32, 33, 34, 35, 36, 37, 38, 39]
第二种:大数据量,采取DAO层分页操作(普遍性需求)
环境:
spring MVC (spring-4.0.0.RELEASE.jar)
hibernate (hibernate-core-4.3.5.Final.jar)
Mysql
两个核心工具类-分页
分页对象,包含所需要的所有参数及逻辑.
package sedion.jeffli.wmuitp.util;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Lists;
public class Page<T> {
//public variables
public static final String ASC = "asc";
public static final String DESC = "desc";
//parameters of page
protected int pageNo = 1;
protected int pageSize = -1;
protected String orderBy = null;
protected String order = null;
protected boolean autoCount = true;
//results
protected long totalCount = -1;
protected List<T> result = Lists.newArrayList();
public Page()
{
}
public Page(int pageSize)
{
this.pageSize = pageSize;
}
/**
* 获得当前页的页号,序号从1开始,默认为1.
*/
public int getPageNo()
{
return pageNo;
}
/**
* 设置当前页的页号,序号从1开始,低于1时自动调整为1.
*/
public void setPageNo(final int pageNo)
{
this.pageNo = pageNo;
if (pageNo < 1)
this.pageNo = 1;
}
/**
* 返回Page对象自身的setPageNo函数,可用于连续设置。
*/
public Page<T> pageNo(final int thePageNo)
{
setPageNo(thePageNo);
return this;
}
/**
* 获得每页的记录数量, 默认为-1.
*/
public int getPageSize()
{
return pageSize;
}
/**
* 设置每页的记录数量.
*/
public void setPageSize(final int pageSize)
{
this.pageSize = pageSize;
}
/**
* 返回Page对象自身的setPageSize函数,可用于连续设置。
*/
public Page<T> pageSize(final int thePageSize)
{
setPageSize(thePageSize);
return this;
}
/**
* 根据pageNo和pageSize计算当前页第一条记录在总结果集中的位置,序号从1开始.
*/
public int getFirst()
{
return ((pageNo - 1) * pageSize) + 1;
}
/**
* 获得排序字段,无默认值. 多个排序字段时用','分隔.
*/
public String getOrderBy()
{
return orderBy;
}
/**
* 设置排序字段,多个排序字段时用','分隔.
*/
public void setOrderBy(final String orderBy)
{
this.orderBy = orderBy;
}
/**
* 返回Page对象自身的setOrderBy函数,可用于连续设置。
*/
public Page<T> orderBy(final String theOrderBy)
{
setOrderBy(theOrderBy);
return this;
}
/**
* 获得排序方向, 无默认值.
*/
public String getOrder()
{
return order;
}
/**
* 设置排序方式向.
*
* @param order
* 可选值为desc或asc,多个排序字段时用','分隔.
*/
public void setOrder(final String order)
{
String lowcaseOrder = StringUtils.lowerCase(order);
String[] orders = StringUtils.split(lowcaseOrder, ',');
for (String orderStr : orders) {
if (!StringUtils.equals(DESC, orderStr) && !StringUtils.equals(ASC, orderStr)) {// 检查order字符串的合法值
throw new IllegalArgumentException("排序方向" + orderStr + "不是合法值");
}
}
this.order = lowcaseOrder;
}
/**
* 返回Page对象自身的setOrder函数,可用于连续设置。
*/
public Page<T> order(final String theOrder)
{
setOrder(theOrder);
return this;
}
/**
* 是否已设置排序字段,无默认值.
*/
public boolean isOrderBySetted()
{
return (StringUtils.isNotBlank(orderBy) && StringUtils.isNotBlank(order));
}
/**
* 获得查询对象时是否先自动执行count查询获取总记录数, 默认为false.
*/
public boolean isAutoCount()
{
return autoCount;
}
/**
* 设置查询对象时是否自动先执行count查询获取总记录数.
*/
public void setAutoCount(final boolean autoCount)
{
this.autoCount = autoCount;
}
/**
* 返回Page对象自身的setAutoCount函数,可用于连续设置。
*/
public Page<T> autoCount(final boolean theAutoCount)
{
setAutoCount(theAutoCount);
return this;
}
// -- 访问查询结果函数 --//
/**
* 获得页内的记录列表.
*/
public List<T> getResult()
{
return result;
}
/**
* 设置页内的记录列表.
*/
public void setResult(final List<T> result)
{
this.result = result;
}
/**
* 获得总记录数, 默认值为-1.
*/
public long getTotalCount()
{
return totalCount;
}
/**
* 设置总记录数.
*/
public void setTotalCount(final long totalCount)
{
this.totalCount = totalCount;
}
/**
* 根据pageSize与totalCount计算总页数, 默认值为-1.
*/
public long getTotalPages()
{
if (totalCount < 0)
return 1;
long count = totalCount / pageSize;
if (totalCount % pageSize > 0)
count++;
return count;
}
/**
* 是否还有下一页.
*/
public boolean isHasNext()
{
return (pageNo + 1 <= getTotalPages());
}
/**
* 取得下页的页号, 序号从1开始. 当前页为尾页时仍返回尾页序号.
*/
public int getNextPage()
{
if (isHasNext())
return pageNo + 1;
else
return pageNo;
}
/**
* 是否还有上一页.
*/
public boolean isHasPre()
{
return (pageNo - 1 >= 1);
}
/**
* 取得上页的页号, 序号从1开始. 当前页为首页时返回首页序号.
*/
public int getPrePage()
{
if (isHasPre())
return pageNo - 1;
else
return pageNo;
}
public long getBegin()
{
return Math.max(1, getPageNo() - pageSize / 2);
}
public long getEnd()
{
return getTotalPages();
}
}
分页初始化(包括参数变化)
package sedion.jeffli.wmuitp.util; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import com.sun.org.apache.xml.internal.resolver.helpers.PublicId; import sedion.jeffli.wmuitp.entity.SubjectInfor; /**
* 分页工具
*
*/
public class PageUtil { public static int PAGE_SIZE = 20;
public static int MAX_SIZE = 9999; public static final String PAGE_NUM_STR = "pageNum"; /**
* 初始化分页
* @param page page对象
* @param request 请求体
* @return
*/
public static int[] init(Page<?> page, HttpServletRequest request) { int pageNum = Integer.parseInt(StringUtils.defaultIfBlank(request.getParameter(PAGE_NUM_STR), "1")); page.setPageNo(Integer.valueOf(pageNum));
page.setPageSize(page.getPageSize()); int firstResult = page.getFirst() - 1;
int maxResults = page.getPageSize(); return new int[] { firstResult, maxResults };
}
}
#这里我们用request.getParameter(PAGE_NUM_STR) 获取分页操作时改变的字段.这样不必要每次都在Controller上附带参数了.
页面端:
<form id="pagerForm" method="post" action="${ctx}/subjectInfor/subjectInfors">
<input type="hidden" name="pageNum" value=${page.getPageNo()} />
<input type="hidden" name="numPerPage" value=${page.getPageSize()} />
</form>
<div class="panelBar">
<div class="pages">
<span>显示</span>
<select class="combox" name="numPerPage" onchange="navTabPageBreak({numPerPage:this.value})">
<option value="20" <#if numPerPage == > selected</#if>>20 </option>
<option value="50" <#if numPerPage == > selected</#if>>50 </option>
<option value="100" <#if numPerPage == > selected</#if>>100 </option>
<option value="200" <#if numPerPage == > selected</#if>>200 </option>
</select>
<span>条,共${page.getTotalCount()}条</span>
</div>
<div class="pagination" totalCount=${page.getTotalCount()} numPerPage=${page.getPageSize()} pageNumShown="10" currentPage=${page.getPageNo()}></div>
然后到Controller层:
@RequestMapping(value = "/subjectInfors")
public ModelAndView subjectInfos()
{
ModelAndView mav = new ModelAndView(SubjectInforWebConstant.getSubjectInforListView()); try { Page<SubjectInfor> page = new Page<>(PageUtil.PAGE_SIZE);
int[] pageParams = PageUtil.init(page,request);//分页初始化
subjectInforService.getSubjectInforsPages(page, pageParams); mav.addObject(MainWebConstant.getPage(), page); } catch (Exception e) {
e.printStackTrace();
} return mav;
}
调用Service层:
@Override
public List<SubjectInfor> getSubjectInforsPages(Page<SubjectInfor> page, int[] pageParams)
{
List<SubjectInfor> results = new ArrayList<>(); StringBuffer resultsHQL = new StringBuffer(All_SUBJECT_INFORS); try
{
results = subjectInforDAO.findByPage(resultsHQL.toString(), pageParams[0], pageParams[1]); page.setTotalCount(subjectInforDAO.getCount(resultsHQL.toString()));
page.setResult(results); } catch (Exception e)
{
e.printStackTrace();
} return results;
}
调用DAO层:
/**
* find entity-s of database by hql
* --------------------------------------------------------
* @param(String) hql
* @param(String) offset 当前标识
* @param(String) pageSize 分页大小
* @return null/List<T>
*/
@SuppressWarnings("unchecked")
public List<T> findByPage(String hql, int offset, int pageSize)
{
if (hql == null)
{
return new ArrayList<T>();
}
Query query = createQuery(hql);
if (!(offset == 0 && pageSize == 0))
{
query.setFirstResult(offset).setMaxResults(pageSize);
}
if (query.list() != null)
return query.list();
else
return null; }
实现的效果图:

#这样分页就简简单单实现了.
Editor's Note
找我加群,一起共勉!

数据量你造吗-JAVA分页的更多相关文章
- mysql大数据量下的分页
mysql大数据量使用limit分页,随着页码的增大,查询效率越低下. 测试实验 1. 直接用limit start, count分页语句, 也是我程序中用的方法: select * from p ...
- 大数据量下,分页的解决办法,bubuko.com分享,快乐人生
大数据量,比如10万以上的数据,数据库在5G以上,单表5G以上等.大数据分页时需要考虑的问题更多. 比如信息表,单表数据100W以上. 分页如果在1秒以上,在页面上的体验将是很糟糕的. 优化思路: 1 ...
- Mysql优化-大数据量下的分页策略
一.前言 通常,我们分页时怎么实现呢? 1 SELECT * FROM table ORDER BY id LIMIT 1000, 10; 但是,数据量猛增以后呢? 1 SELECT * FROM t ...
- mysql大数据量使用limit分页,随着页码的增大,查询效率越低下
1. 直接用limit start, count分页语句, 也是我程序中用的方法: select * from product limit start, count当起始页较小时,查询没有性能问题 ...
- MySQL 大数据量使用limit分页,随着页码的增大,查询效率越低下。
数据表结构 CREATE TABLE `ad_keyword` ( `id` int(11) NOT NULL AUTO_INCREMENT, `plan_goods_id` int(11) DEFA ...
- 超大数据量操作 java程序优化[转载]
一个表中有1000万以上的数据,要对其进行10万次以上的增删查改的操作,请问如何优化java程序对数据库的操作? 通过使用一些辅助性工具来找到程序中的瓶颈,然后就可以对瓶颈部分的代码进行优化. ...
- 数据你把它的金额-JAVA分页
数据量你造吗-JAVA分页 原创地址: http://www.cnblogs.com/Alandre/ (泥沙砖瓦浆木匠),须要转载的,保留下! Thanks 学习的心态第一,解行要对应. 事实 ...
- MySQL大数据量分页查询
mysql大数据量使用limit分页,随着页码的增大,查询效率越低下. 测试实验 1. 直接用limit start, count分页语句, 也是我程序中用的方法: select * from p ...
- 【1】MySQL大数据量分页查询方法及其优化
---方法1: 直接使用数据库提供的SQL语句---语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N---适应场景: 适用于数据量较少的情况(元组百/千 ...
随机推荐
- Python+Selenium基础篇-打开和关闭火狐浏览器
本节介绍如何初始化一个webdriver实例对象driver,然后打开和关闭firefox浏览器.要用selenium打开fiefox浏览器.首先需要去下载一个driver插件geckodriver. ...
- 移动端canvas文字图片合成并生成图片(canvas宽度自适应移动端屏幕)
这是我之前做的一个关于文字图片合成的代码,供大家参考,不足支出还望体谅:具体的注释在代码里都有,有什么不懂了可以留言互相交流.<!DOCTYPE html> <html lang=& ...
- linux的常用指令和配置文件
一. 常用的指令 mkdir -p 创建文件夹 parents递归创建 ls -alh 查看当前目录内容 cd 切换工作目录 pwd 打印当前工作目录 touch 文件名 创建文件 echo 字符 ...
- CentOS7配置阿里云源
cd /etc/yum.repos.d/ mkdir backup mv CentOS-* backup/ wget -O /etc/yum.repos.d/CentOS-Base.repo http ...
- Session使用(14)
用session统计某个网页的访问人数(因为我还不会js,所以就做了个简易版本的) 1.创建Session监听器,每创建了一个Session对象就执行监听类中·的sessionCreated方法. p ...
- liunx_second_day
liunx-基本权限 1.文件和目录权限的区别 A.文件的权限:所有者,所属组,其他人 rwx,读,写,执行,没有权限就是- 第一组rwx:文件所有者的权限 第二组rwx:文件所属组的权限 第三组rw ...
- 理解jsonp劫持漏洞
JSONP劫持 存在漏洞的链接格式类似于以下这种: http://www.xxx.com/xxx.do?callback=info 参数名也常见有cb jsoncb call jsoncall cba ...
- IDEA的Database管理台如何显示
1.找出database的显示view 2.点击设置数据库,下载驱动文件,直接点击下载就行了,用什么数据库就下什么 3.填写服务器地址和用户名密码,点击测试,成功就表示连上了 4.一些常用按钮 5.目 ...
- js的arguments到底是什么?
类数组对象:arguments 总所周知,js是一门相当灵活的语言.当我们在js中在调用一个函数的时候,我们经常会给这个函数传递一些参数,js把传入到这个函数的全部参数存储在一个叫做arguments ...
- hive 数值计算函数
Hive数值计算函数 (1)round(45.666,2)作用:四舍五入,保留2位小数 ceil(45.6) 作用:向上取整 floor(45.6) 作用:向下取整 (2)rand() ...