SSM项目下的分页
在进行分页时,我们要明白前端页面需要给后端传递的数据有哪些,后端又要传递给前端页面什么数据。
前端给后台:当前页是第几页,每一页的大小
后台给前端:当前页的数据,总条数
1、创建实体类(包含总条数和当前页的数据)
@Data public class PageBean { /** * 总条数 */ private long total; /** * 当前页数的数据 */ private List data; public static PageBean setPageAndData(long total,List data){ PageBean pageBean = new PageBean(); pageBean.setTotal(total); pageBean.setData(data); return pageBean; } }
2、pageHelper分页插件
使用方法
1. 引入分页插件
引入分页插件有下面2种方式,推荐使用 Maven 方式。
你可以从下面的地址中下载最新版本的 jar 包
-
https://oss.sonatype.org/content/repositories/releases/com/github/pagehelper/pagehelper/
-
http://repo1.maven.org/maven2/com/github/pagehelper/pagehelper/
由于使用了sql 解析工具,你还需要下载 jsqlparser.jar(需要和PageHelper 依赖的版本一致) :
在 pom.xml 中添加如下依赖:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>最新版本</version>
</dependency>
最新版本号可以从首页查看。
2. 配置拦截器插件
特别注意,新版拦截器是 com.github.pagehelper.PageInterceptor
。 com.github.pagehelper.PageHelper
现在是一个特殊的 dialect
实现类,是分页插件的默认实现类,提供了和以前相同的用法。
2.1. 在 MyBatis 配置 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>
2.2. 在 Spring 配置文件中配置拦截器插件
使用 spring 的属性配置方式,可以使用 plugins
属性像下面这样配置:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注意其他配置 --> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <!--使用下面的方式配置参数,一行配置一个 --> <value> params=value1 </value> </property> </bean> </array> </property> </bean>
3. 如何在代码中使用
分页插件支持以下几种调用方式:
//第一种,RowBounds方式的调用 List<User> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(0, 10)); //第二种,Mapper接口方式的调用,推荐这种使用方式。 PageHelper.startPage(1, 10); List<User> list = userMapper.selectIf(1); //第三种,Mapper接口方式的调用,推荐这种使用方式。 PageHelper.offsetPage(1, 10); List<User> list = userMapper.selectIf(1); //第四种,参数方法调用 //存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数 public interface CountryMapper { List<User> selectByPageNumSize( @Param("user") User user, @Param("pageNum") int pageNum, @Param("pageSize") int pageSize); } //配置supportMethodsArguments=true //在代码中直接调用: List<User> list = userMapper.selectByPageNumSize(user, 1, 10); //第五种,参数对象 //如果 pageNum 和 pageSize 存在于 User 对象中,只要参数有值,也会被分页 //有如下 User 对象 public class User { //其他fields //下面两个参数名和 params 配置的名字一致 private Integer pageNum; private Integer pageSize; } //存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数 public interface CountryMapper { List<User> selectByPageNumSize(User user); } //当 user 中的 pageNum!= null && pageSize!= null 时,会自动分页 List<User> list = userMapper.selectByPageNumSize(user); //第六种,ISelect 接口方式 //jdk6,7用法,创建接口 Page<User> page = PageHelper.startPage(1, 10).doSelectPage(new ISelect() { @Override public void doSelect() { userMapper.selectGroupBy(); } }); //jdk8 lambda用法 Page<User> page = PageHelper.startPage(1, 10).doSelectPage(()-> userMapper.selectGroupBy()); //也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(new ISelect() { @Override public void doSelect() { userMapper.selectGroupBy(); } }); //对应的lambda用法 pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> userMapper.selectGroupBy()); //count查询,返回一个查询语句的count数 long total = PageHelper.count(new ISelect() { @Override public void doSelect() { userMapper.selectLike(user); } }); //lambda total = PageHelper.count(()->userMapper.selectLike(user));
使用PageInfo
的用法(常用):
//获取第1页,10条内容,默认查询总数count PageHelper.startPage(1, 10); List<User> list = userMapper.selectAll(); //用PageInfo对结果进行包装 PageInfo page = new PageInfo(list); //测试PageInfo全部属性 //PageInfo包含了非常全面的分页属性 assertEquals(1, page.getPageNum()); assertEquals(10, page.getPageSize()); assertEquals(1, page.getStartRow()); assertEquals(10, page.getEndRow()); assertEquals(183, page.getTotal()); assertEquals(19, page.getPages()); assertEquals(1, page.getFirstPage()); assertEquals(8, page.getLastPage()); assertEquals(true, page.isFirstPage()); assertEquals(false, page.isLastPage()); assertEquals(false, page.isHasPreviousPage()); assertEquals(true, page.isHasNextPage());
案例
mapper层是逆向工程自动生成的,所以只能用拼接的方式来写SQL语句
Service层实现类代码
@Override public List<Book> searchPage(BookCriteria bookCriteria) { BookExample bookExample = new BookExample(); BookExample.Criteria criteria1 = bookExample.createCriteria(); BookExample.Criteria criteria2 = bookExample.createCriteria(); BookExample.Criteria criteria3 = bookExample.createCriteria(); if (bookCriteria.getFirstType() != -1 && bookCriteria.getFirstType() != 0) { criteria1.andFirstTypeIdEqualTo(bookCriteria.getFirstType()); } if (bookCriteria.getSecondType() != -1 && bookCriteria.getSecondType() != 0) { criteria1.andSecondTypeIdEqualTo(bookCriteria.getSecondType()); } if (!StringUtils.isEmpty(bookCriteria.getSearchStr())) { criteria1.andBookNameLike("%" + bookCriteria.getSearchStr() + "%"); } if (bookCriteria.getFirstType() != -1 && bookCriteria.getFirstType() != 0) { criteria2.andFirstTypeIdEqualTo(bookCriteria.getFirstType()); } if (bookCriteria.getSecondType() != -1 && bookCriteria.getSecondType() != 0) { criteria2.andSecondTypeIdEqualTo(bookCriteria.getSecondType()); } if (!StringUtils.isEmpty(bookCriteria.getSearchStr())) { criteria2.andAuthorNameLike("%" + bookCriteria.getSearchStr() + "%"); } if (bookCriteria.getFirstType() != -1 && bookCriteria.getFirstType() != 0) { criteria3.andFirstTypeIdEqualTo(bookCriteria.getFirstType()); } if (bookCriteria.getSecondType() != -1 && bookCriteria.getSecondType() != 0) { criteria3.andSecondTypeIdEqualTo(bookCriteria.getSecondType()); } if (!StringUtils.isEmpty(bookCriteria.getSearchStr())) { criteria3.andDescriptionLike("%" + bookCriteria.getSearchStr() + "%"); } bookExample.or(criteria2); bookExample.or(criteria3); bookExample.setOrderByClause("book_id desc"); List<Book> books = bookMapper.selectByExample(bookExample); books.forEach(book -> { Integer firstTypeId = book.getFirstTypeId(); Booktype booktype = booktypeMapper.selectByPrimaryKey(firstTypeId); book.setFirstTypeName(booktype == null? "未知分类" : booktype.getTypeName()); Integer secondTypeId = book.getSecondTypeId(); Booktype booktype1 = booktypeMapper.selectByPrimaryKey(secondTypeId); book.setSecondTypeName(booktype1 == null? "未知分类" : booktype1.getTypeName()); }); return books; }
Controller层代码
/** * 分页查询进阶版 * 分页条件查询 * @param bookCriteria * @return */ @GetMapping("searchPage") @ResponseBody public AjaxResult searchPage(BookCriteria bookCriteria) { //开启分页,这一行代码的下面一行代码将会被分页 PageHelper.startPage(bookCriteria.getCurrentPage(), bookCriteria.getPageSize()); List<Book> all = bookService.searchPage(bookCriteria); //当前页的内容 PageInfo<Book> pageInfo = new PageInfo<>(all); //获取总条数 long total = pageInfo.getTotal(); return AjaxResult.success(PageBean.setPageAndData(total, all)); }
前端JS代码
var currentPage = 1; var pageSize = 5; /** * 分页查询所有 */ function searchPage() { //获取的值是key=value形式 // console.log($("#searchForm").serialize()) $.get("/book/searchPage?currentPage=" + currentPage + "&pageSize=" + pageSize + "&" + $("#searchForm").serialize(), function (response) { if (response.data) { var str = ""; response.data.data.forEach(function (item) { str += "<tr>\n" + " <td><input type=\"checkbox\"></td>\n" + " <td>" + item.bookId + "</td>\n" + " <td>" + item.bookName + "</td>\n" + " <td>" + item.authorName + "</td>\n" + " <td>" + item.firstTypeName + "</td>\n" + " <td>" + item.secondTypeName + "</td>\n" + " <td><img src=\"" + item.imgUrl + "\" style=\"vertical-align: middle\" width=\"35px\"\n" + " height=\"35px\" alt=\"\"></td>\n" + " <td>\n" + " <button itemid=\"" + item.bookId + "\" type=\"button\" class=\"btn btn-success updateBtn\" data-toggle=\"modal\" data-target=\"#createDialog\">编辑</button>\n" + " <button itemid=\"" + item.bookId + "\" type=\"button\" class=\"btn btn-danger deletedBtn\">删除</button>\n" + " </td>\n" + " </tr>"; }); $("tbody").html(str); initPage(response.data.total); } delBtn(); addBtn(); alterBtn(); }) } //调用分页函数 searchPage(); /** * 初始化分页插件 * */ function initPage(total) { $("#pagination").pagination(total, //分布总数量,必须参数 { callback: pageChangeHandler, //PageCallback() 为翻页调用次函数。 prev_text: "« 上一页", next_text: "下一页 »", items_per_page: pageSize, num_edge_entries: 2, //两侧首尾分页条目数 num_display_entries: 4, //连续分页主体部分分页条目数 current_page: currentPage - 1, //当前页索引 load_first_page: false }); }; /** * 下一页 * @param index */ function pageChangeHandler(index) { currentPage = index + 1; searchPage(); }