Mybatis-plus插件功能

  1. MyBatisPlus自带分页插件,只需简单的配置就可以实现分页功能

  2. 添加配置类注解@Configuration

    @Configuration
    public class MyBatisPlusConfig {
        //配置分页插件
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            //数据库类型是MySql,因此参数填写DbType.MYSQL
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            return interceptor;
        }
    }
    
  3. 创建测试类

    @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);
    }
    
  4. 真实业务中的分页查询

    • 在引入分页插件的基础上,通用分页实体的用户分页查询业务

    请求参数:"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);
    }
    
  5. 优化通用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;
        });
    }
    
posted @ 2024-05-25 12:10  Hanyta  阅读(33)  评论(0编辑  收藏  举报