mysql pageinfo_Mybatis 数据库物理分页插件 PageHelper

本文介绍了Mybatis的PageHelper分页插件的使用方法,包括依赖引入、配置分页拦截器、在Spring配置文件中的设置,以及如何在ServiceImpl中传递分页参数。PageHelper通过拦截器实现物理分页,简化了手动编写SQL的步骤,提供了便捷的分页功能。
摘要由CSDN通过智能技术生成

以前使用ibatis/mybatis,都是自己手写sql语句进行物理分页,虽然稍微有点麻烦,但是都习惯了。最近试用了下mybatis的分页插件 PageHelper,感觉还不错吧。记录下其使用方法。

1.引入依赖jar包:

com.github.pagehelper

pagehelper

3.7.5

2.配置分页拦截器

PageHelper的原理是基于拦截器实现的。拦截器的配置有两种方法,一种是在mybatis的配置文件中配置,一种是直接在spring的配置文件中进行:

1)在mybatis-config.xml文件中配置:

这里要注意 在mybatis-config.xml文件中的位置,必须要符合 http://mybatis.org/dtd/mybatis-3-config.dtd 中指定的顺序:

objectFactory?, objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>

不然会报错。

当然mybatis-config.xml的位置,我们需要在spring的配置文件中进行指定:

2)如果mybatis没有mybatis-config.xml文件,那么就只能直接在spring的配置文件中配置了:

classpath:config/mapper/*.xml

dialect=mysql

到这里PageHelper所需要的配置已经完成,下面还需要在serviceImpl类中加入分页参数的代码:

3. 向拦截器传递分页参数

我们首先看下不分页的serviceImpl代码:

@Overridepublic ListgetUserByNoAndEmail(String no, String email) {

Map map = new HashMap<>();

map.put("no", no);

map.put("email", email);return this.userMapper.getUserByNoAndEmail(map);

}

然后我们将它改造成使用PageHelper分页:

1)首先我们根据自己项目的情况,定义一个PageBean,来保存分页之后的结果,需要哪些属性,就加入哪些属性,具体可以参考源代码中的PageInfo类的定义,其实PageInfo是插件作者给我们自己定义自己的PageBean,提供的一个参考例子。PageInfo代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

@SuppressWarnings({"rawtypes", "unchecked"})public class PageInfo implementsSerializable {private static final long serialVersionUID = 1L;//当前页

private intpageNum;//每页的数量

private intpageSize;//当前页的数量

private intsize;//由于startRow和endRow不常用,这里说个具体的用法//可以在页面中"显示startRow到endRow 共size条数据"//当前页面第一个元素在数据库中的行号

private intstartRow;//当前页面最后一个元素在数据库中的行号

private intendRow;//总记录数

private longtotal;//总页数

private intpages;//结果集

private Listlist;//第一页

private intfirstPage;//前一页

private intprePage;//下一页

private intnextPage;//最后一页

private intlastPage;//是否为第一页

private boolean isFirstPage = false;//是否为最后一页

private boolean isLastPage = false;//是否有前一页

private boolean hasPreviousPage = false;//是否有下一页

private boolean hasNextPage = false;//导航页码数

private intnavigatePages;//所有导航页号

private int[] navigatepageNums;/*** 包装Page对象

*

*@paramlist*/

public PageInfo(Listlist) {this(list, 8);

}/*** 包装Page对象

*

*@paramlist page结果

*@paramnavigatePages 页码数量*/

public PageInfo(List list, intnavigatePages) {if (list instanceofPage) {

Page page=(Page) list;this.pageNum =page.getPageNum();this.pageSize =page.getPageSize();this.total =page.getTotal();this.pages =page.getPages();this.list =page;this.size =page.size();//由于结果是>startRow的,所以实际的需要+1

if (this.size == 0) {this.startRow = 0;this.endRow = 0;

}else{this.startRow = page.getStartRow() + 1;//计算实际的endRow(最后一页的时候特殊)

this.endRow = this.startRow - 1 + this.size;

}this.navigatePages =navigatePages;//计算导航页

calcNavigatepageNums();//计算前后页,第一页,最后一页

calcPage();//判断页面边界

judgePageBoudary();

}

}/*** 计算导航页*/

private voidcalcNavigatepageNums() {//当总页数小于或等于导航页码数时

if (pages <=navigatePages) {

navigatepageNums= new int[pages];for (int i = 0; i < pages; i++) {

navigatepageNums[i]= i + 1;

}

}else { //当总页数大于导航页码数时

navigatepageNums = new int[navigatePages];int startNum = pageNum - navigatePages / 2;int endNum = pageNum + navigatePages / 2;if (startNum < 1) {

startNum= 1;//(最前navigatePages页

for (int i = 0; i < navigatePages; i++) {

navigatepageNums[i]= startNum++;

}

}else if (endNum >pages) {

endNum=pages;//最后navigatePages页

for (int i = navigatePages - 1; i >= 0; i--) {

navigatepageNums[i]= endNum--;

}

}else{//所有中间页

for (int i = 0; i < navigatePages; i++) {

navigatepageNums[i]= startNum++;

}

}

}

}/*** 计算前后页,第一页,最后一页*/

private voidcalcPage() {if (navigatepageNums != null && navigatepageNums.length > 0) {

firstPage= navigatepageNums[0];

lastPage= navigatepageNums[navigatepageNums.length - 1];if (pageNum > 1) {

prePage= pageNum - 1;

}if (pageNum

nextPage= pageNum + 1;

}

}

}/*** 判定页面边界*/

private voidjudgePageBoudary() {

isFirstPage= pageNum == 1;

isLastPage= pageNum ==pages;

hasPreviousPage= pageNum > 1;

hasNextPage= pageNum

}public void setPageNum(intpageNum) {this.pageNum =pageNum;

}public intgetPageNum() {returnpageNum;

}public intgetPageSize() {returnpageSize;

}public intgetSize() {returnsize;

}public intgetStartRow() {returnstartRow;

}public intgetEndRow() {returnendRow;

}public longgetTotal() {returntotal;

}public intgetPages() {returnpages;

}public ListgetList() {returnlist;

}public intgetFirstPage() {returnfirstPage;

}public intgetPrePage() {returnprePage;

}public intgetNextPage() {returnnextPage;

}public intgetLastPage() {returnlastPage;

}public booleanisIsFirstPage() {returnisFirstPage;

}public booleanisIsLastPage() {returnisLastPage;

}public booleanisHasPreviousPage() {returnhasPreviousPage;

}public booleanisHasNextPage() {returnhasNextPage;

}public intgetNavigatePages() {returnnavigatePages;

}public int[] getNavigatepageNums() {returnnavigatepageNums;

}

@OverridepublicString toString() {final StringBuffer sb = new StringBuffer("PageInfo{");

sb.append("pageNum=").append(pageNum);

sb.append(", pageSize=").append(pageSize);

sb.append(", size=").append(size);

sb.append(", startRow=").append(startRow);

sb.append(", endRow=").append(endRow);

sb.append(", total=").append(total);

sb.append(", pages=").append(pages);

sb.append(", list=").append(list);

sb.append(", firstPage=").append(firstPage);

sb.append(", prePage=").append(prePage);

sb.append(", nextPage=").append(nextPage);

sb.append(", lastPage=").append(lastPage);

sb.append(", isFirstPage=").append(isFirstPage);

sb.append(", isLastPage=").append(isLastPage);

sb.append(", hasPreviousPage=").append(hasPreviousPage);

sb.append(", hasNextPage=").append(hasNextPage);

sb.append(", navigatePages=").append(navigatePages);

sb.append(", navigatepageNums=");if (navigatepageNums == null) sb.append("null");else{

sb.append('[');for (int i = 0; i < navigatepageNums.length; ++i)

sb.append(i== 0 ? "" : ", ").append(navigatepageNums[i]);

sb.append(']');

}

sb.append('}');returnsb.toString();

}

}

PageInfo.java

因为PageInfo.java只是一个示例,所以他定义得有点重量级,属性有点多,我们可以参考它,定义适合我们自己的PageBean, 比如如下定义:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public class PageBean implementsSerializable {private static final long serialVersionUID = 8656597559014685635L;private long total; //总记录数

private List list; //结果集

private int pageNum; //第几页

private int pageSize; //每页记录数

private int pages; //总页数

private int size; //当前页的数量 <= pageSize,该属性来自ArrayList的size属性

/*** 包装Page对象,因为直接返回Page对象,在JSON处理以及其他情况下会被当成List来处理,

* 而出现一些问题。

*@paramlist page结果

*@paramnavigatePages 页码数量*/

public PageBean(Listlist) {if (list instanceofPage) {

Page page = (Page) list;this.pageNum =page.getPageNum();this.pageSize =page.getPageSize();this.total =page.getTotal();this.pages =page.getPages();this.list =page;this.size =page.size();

}

}public longgetTotal() {returntotal;

}public void setTotal(longtotal) {this.total =total;

}public ListgetList() {returnlist;

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

}public intgetPageNum() {returnpageNum;

}public void setPageNum(intpageNum) {this.pageNum =pageNum;

}public intgetPageSize() {returnpageSize;

}public void setPageSize(intpageSize) {this.pageSize =pageSize;

}public intgetPages() {returnpages;

}public void setPages(intpages) {this.pages =pages;

}public intgetSize() {returnsize;

}public void setSize(intsize) {this.size =size;

}

}

PageBean.java

因为分页查询结果返回的是一个 Page 对象,而 Page 对象继承自ArrayList,但是如果我们直接返回ArrayList的话,在一些场景下回遇到问题,比如在JSON处理Page类型的结果时,会被当成List来JSON格式化,会丢弃 Page 对象的所有扩展属性,所以这里我们要将分页的结果 Page 类型转换成我们自己定义的 PageBean. 我们自己定义的PageBean没有继承ArrayList,而是包含一个List属性来保存分页结果。所以避免前面的问题。

2)修改 serviceImpl中的代码:

@Overridepublic PageBeangetUserByNoAndEmail(String no, String email) {

Map map = new HashMap<>();

map.put("no", no);

map.put("email", email);

PageHelper.startPage(PaginationContext.getPageNum(), PaginationContext.getPageSize());

List list = this.userMapper.getUserByNoAndEmail(map);return new PageBean(list);

}

我们只需要使用 PageHelper.startPage(pageNum, pageSize); 函数来指定 pageNum(第几页) 和 pageSize(每页显示几条记录) 两个参数。然后调用原来的查询,就进行了分页。最后将返回的List,转换成 PageBean类型的结果即可。前台页面就可以根据PageBean中包括的属性来进行分页显示了。

上面的 PaginationContext 是基于 ThreadLocal 来传递分页参数的一个工具类,其实现如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classPaginationContext {//定义两个threadLocal变量:pageNum和pageSize

private static ThreadLocal pageNum = new ThreadLocal(); //保存第几页

private static ThreadLocal pageSize = new ThreadLocal(); //保存每页记录条数

/** pageNum :get、set、remove*/

public static intgetPageNum() {

Integer pn=pageNum.get();if (pn == null) {return 0;

}returnpn;

}public static void setPageNum(intpageNumValue) {

pageNum.set(pageNumValue);

}public static voidremovePageNum() {

pageNum.remove();

}/** pageSize :get、set、remove*/

public static intgetPageSize() {

Integer ps=pageSize.get();if (ps == null) {return 0;

}returnps;

}public static void setPageSize(intpageSizeValue) {

pageSize.set(pageSizeValue);

}public static voidremovePageSize() {

pageSize.remove();

}

}

PaginationContext.java

实现了前台页面向ServiceImpl中传递分页参数: pageNum 和 pageSize.

当然从请求中获取分页参数pageNum和pageSize需要用到filter:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public class PageFilter implements Filter {

public PageFilter() {}

public void destroy() {}

@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

HttpServletRequest httpRequest = (HttpServletRequest) request;

PaginationContext.setPageNum(getPageNum(httpRequest));

PaginationContext.setPageSize(getPageSize(httpRequest));

try {

chain.doFilter(request, response);

}

// 使用完Threadlocal,将其删除。使用finally确保一定将其删除

finally {

PaginationContext.removePageNum();

PaginationContext.removePageSize();

}

}

/**

* 获得pager.offset参数的值

*

* @param request

* @return

*/

protected int getPageNum(HttpServletRequest request) {

int pageNum = 1;

try {

String pageNums = request.getParameter("pageNum");

if (pageNums != null && StringUtils.isNumeric(pageNums)) {

pageNum = Integer.parseInt(pageNums);

}

} catch (NumberFormatException e) {

e.printStackTrace();

}

return pageNum;

}

/**

* 设置默认每页大小

*

* @return

*/

protected int getPageSize(HttpServletRequest request) {

int pageSize = 10; // 默认每页10条记录

try {

String pageSizes = request.getParameter("pageSize");

if (pageSizes != null && StringUtils.isNumeric(pageSizes)) {

pageSize = Integer.parseInt(pageSizes);

}

} catch (NumberFormatException e) {

e.printStackTrace();

}

return pageSize;

}

/**

* @see Filter#init(FilterConfig)

*/

public void init(FilterConfig fConfig) throws ServletException {}

}

PageFilter.java

PageFilter在web.xml中的配置:

PageFilter

com.ems.filter.PageFilter

PageFilter

/*

OK,到此,PageHelper的使用方法,基本结束。

PageHelper 项目地址:http://git.oschina.net/free/Mybatis_PageHelper

文档地址:http://git.oschina.net/free/Mybatis_PageHelper/blob/master/wikis/HowToUse.markdown

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值