Mybatis的一个插件,PageHelper,非常方便mybatis分页查询。国内牛人的一个开源项目,有兴趣的可以去看源码,都有中文注释(ps:某些源码一大堆英文,痛哭流涕!)
在github上仓库地址为:Mybatis-PageHelper
它支持基本主流与常用的数据库,这可以在它的文档上看到。这里记录一下使用的基本方法
0.查看文档与使用准备
开发文档有中文文档也有英文文档
============================================
====================================================================================
1.配置拦截器插件
这个是配置在mybatis-config.xml文件中
文档中的示例:
- <!--
- plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
- properties?, settings?,
- typeAliases?, typeHandlers?,
- objectFactory?,objectWrapperFactory?,
- plugins?,
- environments?, databaseIdProvider?, mappers?
- -->
- <plugins>
- <!-- com.github.pagehelper为PageHelper类所在包名 -->
- <plugin interceptor="com.github.pagehelper.PageInterceptor">
- <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
- <property name="param1" value="value1"/>
- </plugin>
- </plugins>
我的配置:
- <plugins>
- <plugin interceptor="com.github.pagehelper.PageInterceptor">
- <!-- config params as the following -->
- <!--<!–分页参数合理化 –>-->
- <property name="reasonable" value="true"/>
- </plugin>
- </plugins>
一些配置参数的说明可以参考文档: 【分页插件参数介绍】
这里就说明一下reasonable的配置:
reasonable
:分页合理化参数,默认值为false
。当该参数设置为 true
时,pageNum<=0
时会查询第一页,pageNum>pages
(超过总数时),会查询最后一页。默认false
时,直接根据参数进行查询。
那么如何选择这些配置参数,文档中也给出了详细说明:【如何选择配置这些参数】
2.在代码中使用
官方文档也有这部分说明和案例,那么我就以自己的使用案例
- @RequestMapping("/emps")
- public String list(@RequestParam(required = false,defaultValue = "1",value = "pageNum")Integer pageNum,
- Map<String,Object> map){
- //引入分页查询,使用PageHelper分页功能
- //在查询之前传入当前页,然后多少记录
- PageHelper.startPage(pageNum,5);
- //startPage后紧跟的这个查询就是分页查询
- List<Employee> emps = employeeService.getAll();
- //使用PageInfo包装查询结果,只需要将pageInfo交给页面就可以
- PageInfo pageInfo = new PageInfo<>(emps,5);
- //pageINfo封装了分页的详细信息,也可以指定连续显示的页数
- map.put("pageInfo",pageInfo);
- return "list";
- }
以上使用说明:
·在查询调用方法前声明分页信息(当前页,每页记录数)
·在查询调用方法对查询结果进行包装成PageInfo对象,也可以是定连续显示的页数,这也是常用功能。
注意:都是与查询方法紧挨着的,不要中间夹杂其它无关语句
之后把信息放在ModelAndView中就可以在前台访问了。
下面说一下为什么要把查询结果包装成PageInfo对象
3.PageInfo类说明
类源码(更多源码去github上查看即可):
- public class PageInfo<T> implements Serializable {
- private static final long serialVersionUID = 1L;
- //当前页
- private int pageNum;
- //每页的数量
- private int pageSize;
- //当前页的数量
- private int size;
- //由于startRow和endRow不常用,这里说个具体的用法
- //可以在页面中"显示startRow到endRow 共size条数据"
- //当前页面第一个元素在数据库中的行号
- private int startRow;
- //当前页面最后一个元素在数据库中的行号
- private int endRow;
- //总记录数
- private long total;
- //总页数
- private int pages;
- //结果集
- private List<T> list;
- //前一页
- private int prePage;
- //下一页
- private int nextPage;
- //是否为第一页
- private boolean isFirstPage = false;
- //是否为最后一页
- private boolean isLastPage = false;
- //是否有前一页
- private boolean hasPreviousPage = false;
- //是否有下一页
- private boolean hasNextPage = false;
- //导航页码数
- private int navigatePages;
- //所有导航页号
- private int[] navigatepageNums;
- //导航条上的第一页
- private int navigateFirstPage;
- //导航条上的最后一页
- private int navigateLastPage;
- public PageInfo() {
- }
- /**
- * 包装Page对象
- *
- * @param list
- */
- public PageInfo(List<T> list) {
- this(list, 8);
- }
- /**
- * 包装Page对象
- *
- * @param list page结果
- * @param navigatePages 页码数量
- */
- public PageInfo(List<T> list, int navigatePages) {
- if (list instanceof Page) {
- Page page = (Page) list;
- this.pageNum = page.getPageNum();
- this.pageSize = page.getPageSize();
- this.pages = page.getPages();
- this.list = page;
- this.size = page.size();
- this.total = page.getTotal();
- //由于结果是>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;
- }
- } else if (list instanceof Collection) {
- this.pageNum = 1;
- this.pageSize = list.size();
- this.pages = this.pageSize > 0 ? 1 : 0;
- this.list = list;
- this.size = list.size();
- this.total = list.size();
- this.startRow = 0;
- this.endRow = list.size() > 0 ? list.size() - 1 : 0;
- }
- if (list instanceof Collection) {
- this.navigatePages = navigatePages;
- //计算导航页
- calcNavigatepageNums();
- //计算前后页,第一页,最后一页
- calcPage();
- //判断页面边界
- judgePageBoudary();
- }
- }
- .......
- }
这里只列出所有属性和构造方法,那么可以清晰的看到一些属性的含义,一些属性是如何初始化,并且初始化值是怎样的,更多详细情况可以自己去查看源码,都有中文注释
那么可以很方便在页面进行值的获取输出
4.在页面获取值(实现分页)
- <!--通过bootstrap的栅格系统布局-->
- <div class="container">
- <!--标题-->
- <div class="row">
- <div class="col-md-12">
- <h1>SSM-CRUD</h1>
- </div>
- </div>
- <!--按钮-->
- <div class="row">
- <div class="col-md-4 col-md-offset-8">
- <button class="btn btn-primary">新增</button>
- <button class="btn btn-danger">删除</button>
- </div>
- </div>
- <!--显示表格数据-->
- <div class="row">
- <div class="col-md-12">
- <table class="table table-hover">
- <tr>
- <th>#</th>
- <th>empName</th>
- <th>gender</th>
- <th>email</th>
- <th>deptName</th>
- <th>操作</th>
- </tr>
- <c:forEach items="${pageInfo.list}" var="emp">
- <tr>
- <th>${emp.empId}</th>
- <th>${emp.empName}</th>
- <th>${emp.gender=="M"?"男":"女" }</th>
- <th>${emp.email}</th>
- <th>${emp.department.deptName}</th>
- <th>
- <button class="btn btn-primary">
- <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
- 编辑
- </button>
- <button class="btn btn-danger">
- <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
- 删除
- </button>
- </th>
- </tr>
- </c:forEach>
- </table>
- </div>
- </div>
- <!--显示分页信息-->
- <div class="row">
- <!--文字信息-->
- <div class="col-md-6">
- 当前第 ${pageInfo.pageNum} 页.总共 ${pageInfo.pages} 页.一共 ${pageInfo.total} 条记录
- </div>
- <!--点击分页-->
- <div class="col-md-6">
- <nav aria-label="Page navigation">
- <ul class="pagination">
- <li><a href="${pageContext.request.contextPath}/emps?pn=1">首页</a></li>
- <!--上一页-->
- <li>
- <c:if test="${pageInfo.hasPreviousPage}">
- <a href="${pageContext.request.contextPath}/emps?pn=${pageInfo.pageNum-1}" aria-label="Previous">
- <span aria-hidden="true">«</span>
- </a>
- </c:if>
- </li>
- <!--循环遍历连续显示的页面,若是当前页就高亮显示,并且没有链接-->
- <c:forEach items="${pageInfo.navigatepageNums}" var="page_num">
- <c:if test="${page_num == pageInfo.pageNum}">
- <li class="active"><a href="#">${page_num}</a></li>
- </c:if>
- <c:if test="${page_num != pageInfo.pageNum}">
- <li><a href="${pageContext.request.contextPath}/emps?pn=${page_num}">${page_num}</a></li>
- </c:if>
- </c:forEach>
- <!--下一页-->
- <li>
- <c:if test="${pageInfo.hasNextPage}">
- <a href="${pageContext.request.contextPath}/emps?pn=${pageInfo.pageNum+1}"
- aria-label="Next">
- <span aria-hidden="true">»</span>
- </a>
- </c:if>
- </li>
- <li><a href="${pageContext.request.contextPath}/emps?pn=${pageInfo.pages}">尾页</a></li>
- </ul>
- </nav>
- </div>
- </div>
- </div>
最后显示:
以上很常见的分页需求,可以非常方便的使用。
并且支持各种数据库,可以有多种方式进行引入插件,对于springBoot也有非常好的整合使用。
PageHelpe开源地址
github项目地址:https://github.com/pagehelper/Mybatis-PageHelper
码云 项目地址:http://git.oschina.net/free/Mybatis_PageHelper