-
MyBatisPlus自带分页插件,只需简单的配置就可以实现分页功能
-
添加配置类注解@Configuration
@Configuration public class MyBatisPlusConfig { //配置分页插件 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); //数据库类型是MySql,因此参数填写DbType.MYSQL interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
-
创建测试类
@Test void testPageQuery() { // 1.分页查询,new Page()的两个参数分别是:页码、每页大小 Page<User> p = userService.page(new Page<>(2, 2)); // 2.总条数 System.out.println("total = " + p.getTotal()); // 3.总页数 System.out.println("pages = " + p.getPages()); // 4.数据 List<User> records = p.getRecords(); records.forEach(System.out::println); }
-
真实业务中的分页查询
- 在引入分页插件的基础上,通用分页实体的用户分页查询业务
请求参数:"pageNo","pageSize","sortBy","isAsc"
返回值:json列表{ "total": 100006, "pages": 50003, "list": [ { "id": 1685100878975279298, "username": "user_9****", "info": { "age": 24, "intro": "英文老师", "gender": "female" }, "status": "正常", "balance": 2000 }, ... ] }
- 实体类的准备:为了通用性
PageQuery:分页查询条件的实体,包含分页、排序参数
PageDTO:分页结果实体,包含总条数、总页数、当前页数据
UserVO:用户页面视图实体- 引入hutool工具包
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>xxx</version> </dependency>
- PageQuery
import lombok.Data; @Data public class PageQuery { private Integer pageNo; private Integer pageSize; private String sortBy; private Boolean isAsc; }
- UserVO实体
@Data public class UserVO { /** * 用户id */ private Long id; /** * 用户名 */ private String username; /** * 详细信息 */ private UserInfo info; /** * 使用状态(1正常 2冻结) */ private UserStatus status; /** * 账户余额 */ private Integer balance; }
- 分页实体PageDTO
@Data @NoArgsConstructor @AllArgsConstructor public class PageDTO<T> { private Integer total; private Integer pages; private List<T> list; }
- UserController
@RestController @RequestMapping("users") @RequiredArgsConstructor public class UserController { private final UserService userService; @GetMapping("/page") public PageDTO<UserVO> queryUserByPage(PageQuery query){ return userService.queryUserByPage(query); } }
- UserService
PageDTO<UserVO> queryUserByPage(PageQuery query);
- UserServiceImpl
@Override public PageDTO<UserVO> queryUserByPage(PageQuery query) { // 1.构建条件 // 1.1.分页条件 Page<User> page = Page.of(query.getPageNo(), query.getPageSize()); // 1.2.排序条件 if (query.getSortBy() != null) { page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc())); }else{ // 默认按照更新时间排序 page.addOrder(new OrderItem("update_time", false)); } // 2.查询 page(page); // 3.数据非空校验 List<User> records = page.getRecords(); if (records == null || records.size() <= 0) { // 无数据,返回空结果 return new PageDTO<>(page.getTotal(), page.getPages(), Collections.emptyList()); } // 4.有数据,转换 List<UserVO> list = BeanUtil.copyToList(records, UserVO.class); // 5.封装返回 return new PageDTO<UserVO>(page.getTotal(), page.getPages(), list); }
-
优化通用Page分页
- 从PageQuery到MybatisPlus的Page之间转换的过程还是比较麻烦的,在PageQuery这个实体中定义一个工具方法,简化开发。
@Data public class PageQuery { private Integer pageNo; private Integer pageSize; private String sortBy; private Boolean isAsc; public <T> Page<T> toMpPage(OrderItem ... orders){ // 1.分页条件 Page<T> p = Page.of(pageNo, pageSize); // 2.排序条件 // 2.1.先看前端有没有传排序字段 if (sortBy != null) { p.addOrder(new OrderItem(sortBy, isAsc)); return p; } // 2.2.再看有没有手动指定排序字段 if(orders != null){ p.addOrder(orders); } return p; } public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc){ return this.toMpPage(new OrderItem(defaultSortBy, isAsc)); } public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() { return toMpPage("create_time", false); } public <T> Page<T> toMpPageDefaultSortByUpdateTimeDesc() { return toMpPage("update_time", false); } }
- 调用方法
// 1.构建条件 Page<User> page = query.toMpPageDefaultSortByCreateTimeDesc();
- 改造PageDTO实体:查询出分页结果后,数据的非空校验,数据的vo转换都是模板代码,编写起来很麻烦,将其封装到PageDTO的工具方法
@Data @NoArgsConstructor @AllArgsConstructor public class PageDTO<V> { private Long total; private Long pages; private List<V> list; /** * 返回空分页结果 * @param p MybatisPlus的分页结果 * @param <V> 目标VO类型 * @param <P> 原始PO类型 * @return VO的分页对象 */ public static <V, P> PageDTO<V> empty(Page<P> p){ return new PageDTO<>(p.getTotal(), p.getPages(), Collections.emptyList()); } /** * 将MybatisPlus分页结果转为 VO分页结果 * @param p MybatisPlus的分页结果 * @param voClass 目标VO类型的字节码 * @param <V> 目标VO类型 * @param <P> 原始PO类型 * @return VO的分页对象 */ public static <V, P> PageDTO<V> of(Page<P> p, Class<V> voClass) { // 1.非空校验 List<P> records = p.getRecords(); if (records == null || records.size() <= 0) { // 无数据,返回空结果 return empty(p); } // 2.数据转换 List<V> vos = BeanUtil.copyToList(records, voClass); // 3.封装返回 return new PageDTO<>(p.getTotal(), p.getPages(), vos); } /** * 将MybatisPlus分页结果转为 VO分页结果,允许用户自定义PO到VO的转换方式 * @param p MybatisPlus的分页结果 * @param convertor PO到VO的转换函数 * @param <V> 目标VO类型 * @param <P> 原始PO类型 * @return VO的分页对象 */ public static <V, P> PageDTO<V> of(Page<P> p, Function<P, V> convertor) { // 1.非空校验 List<P> records = p.getRecords(); if (records == null || records.size() <= 0) { // 无数据,返回空结果 return empty(p); } // 2.数据转换 List<V> vos = records.stream().map(convertor).collect(Collectors.toList()); // 3.封装返回 return new PageDTO<>(p.getTotal(), p.getPages(), vos); } }
- 最终业务层的代码
@Override public PageDTO<UserVO> queryUserByPage(PageQuery query) { // 1.构建条件 Page<User> page = query.toMpPageDefaultSortByCreateTimeDesc(); // 2.查询 page(page); // 3.封装返回 return PageDTO.of(page, UserVO.class); }
- 若希望自定义PO到VO的转换过程
@Override public PageDTO<UserVO> queryUserByPage(PageQuery query) { // 1.构建条件 Page<User> page = query.toMpPageDefaultSortByCreateTimeDesc(); // 2.查询 page(page); // 3.封装返回 return PageDTO.of(page, user -> { // 拷贝属性到VO UserVO vo = BeanUtil.copyProperties(user, UserVO.class); // 用户名脱敏 String username = vo.getUsername(); vo.setUsername(username.substring(0, username.length() - 2) + "**"); return vo; }); }