Mybatis-plus外掛功能

Hanyta發表於2024-05-25
  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;
        });
    }
    

相關文章