SSM+Maven使用PageHelper插件分页
官方网站:
https://pagehelper.github.io/docs/howtouse/#2-%E9%85%8D%E7%BD%AE%E6%8B%A6%E6%88%AA%E5%99%A8%E6%8F%92%E4%BB%B6
PageHelper是一款开源的MyBatis插件,它提供了对MySQL、Oracle、DB2等主流数据库的支持,极大地简化了后端处理分页查询的过程,使用PageHelper对后端开发有很大帮助
PageHelper 使用的注意点
1. 只有紧跟在 PageHelper.startPage 方法后的第一个 Mybatis 的查询(Select)方法会被分页。
2. 不能同时配置多个分页插件
3. 分页插件不支持带有 for update 语句的分页,需要手动分页
4. 不支持一对一和一对多结果映射的分页查询,如果分页显示20条数据,这20条数据中每一个包含30条子数据,则子数据只能显示20条,其余会丢失。
一:在 pom.xml 中添加如下依赖:
<!-- 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.8</version> </dependency>
二:配置pageHelper
在Spring核心配置文件application.xml 中,配置org.mybatis.spring.SqlSessionFactoryBean时添加属性
<!-- 配置SqlSessionFactory这是mybatis工厂 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property><!-- 注入数据源 --> <property name="mapperLocations" value="classpath:com/aaa/dao/*.xml"></property><!--自动扫描dao映射文件 --> <!-- <property name="typeAliases" value="com.aaa.entity"></property> --><!--类型别名 dao映射可以直接返回实体对象--> <!-- pagrHelper分页插件 --> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <!--使用下面的方式配置参数,一行配置一个 分页参数参考官方--> <!-- <value> helperDialect=mysql reasonable=true supportMethodsArguments=true params=count=countSql autoRuntimeDialect=true </value> --> <props> <!--数据库类型--> <prop key="helperDialect">mysql</prop> <!--页码超出范围自动修正--> <prop key="reasonable">true</prop> </props> </property> </bean> </array> </property> </bean>
三:在要分页的方法上添加分页插件拦截器
PageHelper 常用类信息
有三个主要类需要了解:
Page 分页对象:继承 ArrayList,对查询结果进行进一步的封装处理
主要属性:
pageNum : 起始页码
pageSize : 每页显示条数
startRow : 起始行
endRow : 结束行
total : 总记录数
pages : 总页数
reasonable : 分页合理化,布尔值,是否对超出范围的页码自动优化处理
PageHelper 通用分页拦截器常用方法:
Page < E > startPage(int pageNum,int pageSize):根据起始页和每页条数查询,返回一个Page结果集;
Page < E > offsetPage(int offset,int limit):根据起始索引和查询条数查询,返回一个Page结果集;
PageInfo 响应给前端的分页对象:对Page结果进行包装
主要属性:
pageNum : 当前页
pageSize : 每页的数量
size : 当前页的数量(最后一页不足每页条数)
startRow : 当前页面第一个元素在数据库中的行号
endRow : 当前页面最后一个元素在数据库中的行号
pages : 总页数
prePage: 上一页的页码
nextPage: 下一页的页码
构造方法:
public PageInfo(List list) {
this(list, 8);
}
1.controller采用异步返回JSON
先执行startPage()或offsetPage()方法,将返回的分页信息通过 PageInfo 的构造方法进行封装
@RequestMapping("/queryTbGoods") @ResponseBody public PageInfo queryTbGoods(@RequestParam(required=true,defaultValue="1") Integer pageNum,@RequestParam(required=false,defaultValue="3") Integer pageSize,@RequestParam Map map){ //System.out.println(map.get("goodsName")+":参数:"+map.get("typeName")); /*开启分页插件拦截器*/ PageHelper.startPage(pageNum, pageSize); List<Map<String,Object>> list=ts.queryTbGoods(map); /*封装结果集返回当前页信息(页码, 条数等)*/ PageInfo page= new PageInfo(list); //System.out.println(page.getTotal()+":"+page.getPages()); return page; }
2.前端页面JSP采用BootsStrop前端布局
1.引入依赖
<!-- 使用模态窗口引入bootstrap --> <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resouces/js/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resouces/js/bootstrap/css/bootstrap-theme.min.css"> <script src="${pageContext.request.contextPath}/resouces/js/jquery.min.js"></script> <script src="${pageContext.request.contextPath}/resouces/js/bootstrap/js/bootstrap.min.js"></script> <!--最基础jQuery.js都是基于这个 --> <script type="text/javascript" src="resouces/jquery-1.11.3.min.js"></script> <!-- 异步转换参数js --> <script type="text/javascript" src="resouces/jqueryExt.js"></script> <!-- 上传文件js --> <script type="text/javascript" src="resouces/jquery.form.js"></script>
2.分页按钮排版代码
<ul class="pager" > <li> 当前页:<span id="curPage"></span>总页数:<span id="totalPages"></span>总共:<span id="totals"></span>条记录 </li> <li><a id="first" onclick="changePage(this)">首页</a></li> <li><a id="prev" onclick="changePage(this)">上一页</a></li> <li><a id="next" onclick="changePage(this)">下一页</a></li> <li><a id="last" onclick="changePage(this)">尾页</a></li> <li><input type="number" id="txtCurPage" min="1" max="10"></input><input type="button" class="btn btn-default" value="go" onclick="gotoPage()"/></li> </ul>
2.Ajax异步
/* 查询商品表 */ function queryTbGoods(page){ var name=$("#goodsNames").val(); var tyName=$("#typeNames").val(); /* alert(name+":参数:"+tyName); */ $.ajax({ url:"goods/queryTbGoods", type:"post", data:{"goodsName":name,"typeName":tyName,"pageNum":page,"pageSize":3}, dataType:"json", success:function(data){ alert(data.pages); $("#tbody").empty(); $.each(data.list,function(key,obj){ /* alert(obj.typeId.typeName); */ var tr="<tr>"; tr+="<td>"+obj.goodsId+"</td>"; tr+="<td>"+obj.goodsName+"</td>"; tr+="<td>"+obj.typeName+"</td>"; tr+="<td>"+obj.goodsDesc+"</td>"; tr+="<td>"+obj.goodsUnitPrice+"</td>"; /* tr+="<td><img style=' width:80px; height:80px;' src='"+obj.goodsImageName+"'/></td>"; */ tr+="<td>"+obj.sellCount+"</td>"; tr+="<td>"+obj.goodsDate+"</td>"; tr+="<td><input type='button' id="+obj.goodsId+" data-toggle='modal' data-target='#myModal' title="+obj.goodsId+" class='findById btn btn-default' value='修改'></td>"; tr+="<td><input type='button' id="+obj.goodsId+" class='delete btn btn-default' value='删除'></td>"; tr+="</tr>"; $("#tbody").append(tr); //重新初始化分页链接 $("#curPage").html(data.pageNum);//当前页 $("#totalPages").html(data.pages);//总页数 $("#totals").html(data.total);//总条数 $("#first").attr("data",1);//首页 $("#prev").attr("data",data.prePage);//上一页 $("#next").attr("data",data.nextPage);//下一页 $("#last").attr("data",data.pages);//尾页 $("#txtCurPage").val(data.pageNum).attr("max",data.pages); }); } }); } //改变页面 function changePage(obj){ var page=$(obj).attr("data");//取出data属性值 queryTbGoods(page); } //跳转到指定页面 function gotoPage(page){ var page=$("#txtCurPage").val(); queryTbGoods(page); }
3.jsp全部代码
<%@ page language="java" import="java.util.*" pageEncoding="utf-8" isELIgnored="false"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <!-- 使用模态窗口引入bootstrap --> <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resouces/js/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resouces/js/bootstrap/css/bootstrap-theme.min.css"> <script src="${pageContext.request.contextPath}/resouces/js/jquery.min.js"></script> <script src="${pageContext.request.contextPath}/resouces/js/bootstrap/js/bootstrap.min.js"></script> <!--最基础jQuery.js都是基于这个 --> <script type="text/javascript" src="resouces/jquery-1.11.3.min.js"></script> <!-- 异步转换参数js --> <script type="text/javascript" src="resouces/jqueryExt.js"></script> <!-- 上传文件js --> <script type="text/javascript" src="resouces/jquery.form.js"></script> </head> <body> <table class="table table-hover"> <thead > <tr class="success"> <th>商品编号</th> <th>商品名称</th> <th>商品类型</th> <th>商品Desc</th> <th>商品价格</th> <!-- <th>商品图片</th> --> <th>商品数量</th> <th>日期</th> <!-- <th>操作</th> --> <th colspan="3">查询 <input type="text" onblur="queryTbGoods()" size="6" class="goodsName" id="goodsNames" placeholder="请输入名称" name="goodsName"> <input type="text" onblur="queryTbGoods()" size="6" class="goodsName" id="typeNames" placeholder="请输入类型" name="typeName"> <input type="button" data-toggle="modal" data-target="#myModal" class="emptys btn btn-default" value="添加"> </th> </tr> </thead> <tbody id="tbody"> </tbody> </table> <!-- 模态框弹出录入内容 --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="modalTitle1" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × <!-- 关闭按钮 --> </button> <h4 class="modal-title" id="modalTitle1">录入商品</h4> </div> <div class="modal-body"> <!--form提交表单 --> <form class="form-horizontal" id="form1" enctype="multipart/form-data"> <div class="form-group"> <label for="roleName" class="col-sm-2 control-label">商品名</label> <div class="col-sm-4"> <input type="hidden" id="goodsId" name="goodsId" class="form-control" placeholder="请输入"> <input type="text" id="goodsName" name="goodsName" class="form-control" placeholder="请输入商品名"> </div> </div> <div class="form-group"> <label for="description" class="col-sm-2 control-label">商品类型</label> <div class="col-sm-4"> <select class="sele form-control" name="typeId"> </select> </div> </div> <div class="form-group"> <label for="description" class="col-sm-2 control-label">商品Desc</label> <div class="col-sm-4"> <input type="text" id="goodsDesc" class="form-control" name="goodsDesc" placeholder="请输入"> </div> </div> <div class="form-group"> <label for="description" class="col-sm-2 control-label">商品价格</label> <div class="col-sm-4"> <input type="text" id="goodsUnitPrice" class="form-control" name="goodsUnitPrice" placeholder="请输入"> </div> </div> <!-- <div class="form-group"> <label for="description" class="col-sm-2 control-label">商品图片</label> <div class="col-sm-4"> <input type="file" name="goodsImage"/> </div> </div> --> <div class="form-group"> <label for="description" class="col-sm-2 control-label">数量</label> <div class="col-sm-4"> <input type="text" id="sellCount" class="form-control" name="sellCount" placeholder="请输入"> </div> </div> <div class="form-group"> <label for="description" class="col-sm-2 control-label">日期</label> <div class="col-sm-4"> <input type="date" id="goodsDate" class="form-control" name="goodsDate" placeholder="请输入"> </div> </div> <input type="button" id="saveUploadOrUpdate" data-toggle='modal' data-target='#myModal' class="btn btn-primary" value="保存"> </form> </div> <div class="modal-footer"> <button type="button" class="up btn btn-default" data-dismiss="modal">关闭 </button> </div> </div> <!-- /.modal-content --> </div> <!-- /.modal --> </div> <ul class="pager" > <li> 当前页:<span id="curPage"></span>总页数:<span id="totalPages"></span>总共:<span id="totals"></span>条记录 </li> <li><a id="first" onclick="changePage(this)">首页</a></li> <li><a id="prev" onclick="changePage(this)">上一页</a></li> <li><a id="next" onclick="changePage(this)">下一页</a></li> <li><a id="last" onclick="changePage(this)">尾页</a></li> <li><input type="number" id="txtCurPage" min="1" max="10"></input><input type="button" class="btn btn-default" value="go" onclick="gotoPage()"/></li> </ul> </body> </html> <script> $(function(){ queryTbGoods(); queryTbGoodsType(); }); /* 查询商品表 */ function queryTbGoods(page){ var name=$("#goodsNames").val(); var tyName=$("#typeNames").val(); /* alert(name+":参数:"+tyName); */ $.ajax({ url:"goods/queryTbGoods", type:"post", data:{"goodsName":name,"typeName":tyName,"pageNum":page,"pageSize":3}, dataType:"json", success:function(data){ alert(data.pages); $("#tbody").empty(); $.each(data.list,function(key,obj){ /* alert(obj.typeId.typeName); */ var tr="<tr>"; tr+="<td>"+obj.goodsId+"</td>"; tr+="<td>"+obj.goodsName+"</td>"; tr+="<td>"+obj.typeName+"</td>"; tr+="<td>"+obj.goodsDesc+"</td>"; tr+="<td>"+obj.goodsUnitPrice+"</td>"; /* tr+="<td><img style=' width:80px; height:80px;' src='"+obj.goodsImageName+"'/></td>"; */ tr+="<td>"+obj.sellCount+"</td>"; tr+="<td>"+obj.goodsDate+"</td>"; tr+="<td><input type='button' id="+obj.goodsId+" data-toggle='modal' data-target='#myModal' title="+obj.goodsId+" class='findById btn btn-default' value='修改'></td>"; tr+="<td><input type='button' id="+obj.goodsId+" class='delete btn btn-default' value='删除'></td>"; tr+="</tr>"; $("#tbody").append(tr); //重新初始化分页链接 $("#curPage").html(data.pageNum);//当前页 $("#totalPages").html(data.pages);//总页数 $("#totals").html(data.total);//总条数 $("#first").attr("data",1);//首页 $("#prev").attr("data",data.prePage);//上一页 $("#next").attr("data",data.nextPage);//下一页 $("#last").attr("data",data.pages);//尾页 $("#txtCurPage").val(data.pageNum).attr("max",data.pages); }); } }); } //改变页面 function changePage(obj){ var page=$(obj).attr("data");//取出data属性值 queryTbGoods(page); } //跳转到指定页面 function gotoPage(page){ var page=$("#txtCurPage").val(); queryTbGoods(page); } /*查询商品类型 */ function queryTbGoodsType(){ $.ajax({ url:"goods/queryTbGoodsType", type:"post", data:"", dataType:"json", success:function(data){ for(var i=0;i<data.length;i++){ var obj=data[i]; $(".sele").append("<option value='"+obj.typeId+"'>"+obj.typeName+"</option>"); } } }); } /* 添加修改之前清空form表单 */ $(document).on("click",".emptys",function(){ $("#goodsId").val(""); $("#goodsName").val(""); $("#goodsDesc").val(""); $("#goodsUnitPrice").val(""); $("#sellCount").val(""); $("#goodsDate").val(""); }); /*添加修改 */ $(document).on("click","#saveUploadOrUpdate",function(){ /* alert($("#form1").serialize()); */ $.ajax({ url:"goods/saveOrUpdateTbgoods", type:"post", data:$("#form1").serialize(), dataType:"text", success:function(data){ alert(data); queryTbGoods(); } }); }); /*修改前查询 */ $(document).on("click",".findById",function(){ var id=this.id; $.ajax({ url:"goods/findByIdTbGoods", type:"post", data:{"goodsId":id}, dataType:"json", success:function(data){ $("#goodsId").val(data.goodsId); $("#goodsName").val(data.goodsName); $("#goodsDesc").val(data.goodsDesc); $("#goodsUnitPrice").val(data.goodsUnitPrice); $("#sellCount").val(data.sellCount); $("#goodsDate").val(data.goodsDate); } }); }); $(document).on("click",".delete",function(){ var id=this.id; if (confirm("您确定要删除此信息吗?")){ $.ajax({ url:"goods/deleteGoods", type:"post", data:{"goodsId":id}, dataType:"text", success:function(data){ alert(data); queryTbGoods(); } }); }else{ return false; } }); </script>
4.效果图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通