Mybatis分页插件PageHelper

在web开发过程中涉及到表格时,例如dataTable,就会产生分页的需求,通常我们将分页方式分为两种:前端分页和后端分页。

前端分页

一次性请求数据表格中的所有记录(ajax),然后在前端缓存并且计算count和分页逻辑,一般前端组件(例如dataTable)会提供分页动作。

特点是:简单,很适合小规模的web平台;当数据量大的时候会产生性能问题,在查询和网络传输的时间会很长。

后端分页

在ajax请求中指定页码(pageNum)和每页的大小(pageSize),后端查询出当页的数据返回,前端只负责渲染。

特点是:复杂一些;性能瓶颈在MySQL的查询性能,这个当然可以调优解决。一般来说,web开发使用的是这种方式。

我们说的也是后端分页。

Mybatis分页插件PageHelper,国内牛人的一个开源项目,有兴趣的可以去看源码,都有中文注释

github上仓库地址为:GitHub - pagehelper/Mybatis-PageHelper: Mybatis通用分页插件

oschub的项目地址:Mybatis_PageHelper: Mybatis分页插件

它支持基本主流与常用的数据库,这可以在它的文档上看到。

1、POM依赖

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.4</version>
</dependency>

2、Mybatis对PageHelper的配置

打开Mybatis配置文件,一般在Resource路径下。我这里叫mybatis-config.xml。

一些配置参数的说明可以参考文档: 【分页插件参数介绍】

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--PageHelper分页插件-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!--PageHelper插件4.0.0以后的版本支持自动识别使用的数据库-->
            
        </plugin>
    </plugins>
</configuration>

4、Service接口

List<Order> getList(Order order);

5、Service接口实现类

@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public List<Order> getList(Order order) {
        List<Order> list = userDao.FindUserByInfo(order);
        return list;
    }
}

优化后使用

public PageInfo<ResponseEntityDto> page(order param) {
	return PageHelper.startPage(param.getPageNum(), param.getPageSize())
			  .doSelectPageInfo(() -> list(param))
} 
public List<ResponseEntityDto> list(order param) {
	return userDao.getList(param);
}

6、Controller代码

@Controller
public class UserController {
	
    @Autowired
    private UserService userService;
	
	
    /**
     * order    实体类
     * page     当前页
     * pageSize 当前页的数量(我这里是10条)
     */  
    @RequestMapping("/user.do")
    public String userList( Model model, Order order,
                           @RequestParam(required = true, defaultValue = "1") Integer page,
                           @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
        //引入分页查询,使用PageHelper分页功能,在查询之前传入当前页,然后多少记录
        PageHelper.startPage(page, pageSize);
       
		List<Order> userList = userService.getList(order);
        //使用PageInfo包装查询结果,只需要将pageInfo交给页面就可以
        PageInfo<Order> page = new PageInfo<Order>(userList);
		
        /*** 分页配置信息返回*/
        page.setLastPage((int) page.getTotal() / pageSize + 1);
        page.setFirstPage(1);
        model.addAttribute("page", page);
        return "Pagination";
    }
}
 @PostMapping("/api/v1/task/list")
    public PageInfo<order> taskList(@RequestBody PagedRequest<order> pageParam) {
        PageInfo<order> page = taskService.getList(pageParam);
        return page;
    }

以上使用说明:
在查询调用方法前声明分页信息(当前页,每页记录数)

在查询调用方法对查询结果进行包装成PageInfo对象,也可以是定连续显示的页数,这也是常用功能。

注意:都是与查询方法紧挨着的,不要中间夹杂其它无关语句

之后把信息放在ModelAndView中就可以在前台访问了。

6、 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() {
    }
    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;
            //计算导航页
            this.calcNavigatepageNums();
            //计算前后页,第一页,最后一页
            this.calcPage();
            //判断页面边界
            this.judgePageBoudary();
        }
    }
}

7、前端页面

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";%>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <base href="<%=basePath%>">
    <title>分页</title>
    <script src="js/jquery-3.1.1.min.js"></script>
    <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
</head>
<body>
<div class="row" id="deviceRecordList">
    <div class="col-lg-12" style="height: 15px;top:0px" id="paging">
        <div class="table-responsive">
            <table class="table table-striped table-bordered bootstrap-datatable datatable">
                <thead>
                <tr>
                    <th>序号</th>
                    <th>科目</th>
                    <th>收费类型</th>
                    <th>单价</th>
                    <th>数量</th>
                    <th>总金额</th>
                    <th>开始时间</th>
                    <th>结束时间</th>
                    <th>结束类型</th>
                </tr>
                </thead>
                <tbody>
                <c:forEach items="${userList}" var="c" varStatus="status">
                    <tr>
                        <td>${status.index+1 }</td>
                        <td>${c.id}</td>
                        <td>${c.order_date}</td>
                        <td>
                            <span class="label label-warning">${c.member_label}</span>
                        </td>
                        <td>${c.codeno}</td>
                        <td>${c.remark}</td>
                        <td>${c.order_state}</td>
                        <td>${c.product_money}</td>
                        <td>${c.send_time }</td>
                    </tr>
                </c:forEach>

                </tbody>
            </table>
            <!-- 分页 -->
            <div style="text-align:center;" id="deviceId">
                <ul class="pagination">
                    <c:if test="${!page.isFirstPage}">
                        <li><a href="user.do?page=${page.firstPage}">首页</a></li>
                        <li><a href="user.do?page=${page.prePage}">上一页</a></li>
                    </c:if>
                    <c:forEach items="${page.navigatepageNums}" var="navigatepageNum">

                        <c:if test="${navigatepageNum==page.pageNum}">
                            <li class="active"><a href="user.do?page=${navigatepageNum}">${navigatepageNum}</a></li>
                        </c:if>
                        <c:if test="${navigatepageNum!=page.pageNum}">
                            <li><a href="user.do?page=${navigatepageNum}">${navigatepageNum}</a></li>
                        </c:if>
                    </c:forEach>
                    <c:if test="${!page.isLastPage}">
                        <li><a href="user.do?page=${page.nextPage}">下一页</a></li>
                        <li><a href="user.do?page=${page.lastPage}">尾页</a></li>
                    </c:if>

                    <li><a href="javascript:void(0);">共${page.total}条记录,</a></li>
                    <%--共<i class="blue">${page.total}</i>条记录,当前显示第&nbsp;<i--%>
                    <%--class="blue">${page.pageNum}/${page.pages}</i>&nbsp;页--%>
                </ul>
            </div>
        </div>
    </div>
</div>
</body>
</html>

8、分页效果如下

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值