重构之美 - MybatisPlus如何使用一个工具类实现通用分页查询

MybatisPlus 高效分页查询封装

【最新更新:2021.07.24】
【更新功能:新增模糊识别,集合匹配;修复自定义分页请求后返回已经删除的数据】

背景

  1. 你还在不断的用wrapper 去 eq 、like吗?
  2. 你还在纠结字段排序后分页结果如何展示问题吗?
  3. 你还在同样的逻辑上做CV工程师,还不去优化吗?
    快来看看老夫实现的这一款通用封装查询:
package com.mykj.util;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.google.common.base.CaseFormat;
import com.mykj.EmptyUtil;
import com.mykj.StringUtil;
import com.mykj.constant.DefaultExceptionEnums;
import com.mykj.constant.SortRuleType;
import com.mykj.controller.request.PageRequest;
import com.mykj.controller.response.PageResponse;
import com.mykj.exception.GlobalServiceExceptionUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.weaver.ast.Var;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @description:
 * @author: fuchen
 * @date: 2021/4/18 10:32 下午
 **/
@Slf4j
public class PageUtils {

    public static <T> PageResponse<T> buildPageResponse(PageRequest request, Page<T> page) {
        return new PageResponse<T>(page.getTotal(), page.getRecords(), request);
    }

    /**
     * 根据分页条件和分页请求 获得分页结果
     * @param request 前端分页请求 --可以自定义属性名
     * @param queryWrapper  分页查询条件 支持自定义查询
     * @param pageService 调用分页的服务IService
     * @param <T> 响应结果
     * @return
     */
    public static <T> PageResponse<T> buildPageResponse(PageRequest request, QueryWrapper<T> queryWrapper,  IService<T> pageService) {
        // todo 驼峰转下划线后输出到前端
        // 构造分页条件 并执行分页查询
        Page<T> page = pageService.page(buildPageRequest(request), queryWrapper);
        return new PageResponse<T>(page.getTotal(), page.getRecords(), request);
    }

    /**
     * 构造查询分页响应结果
     * @param request 前端分页请求 --不支持自定义属性名
     * @param pageService 调用分页的服务IService
     * @return 给前端响应的分页结果
     */
    public static <T> PageResponse<T> buildPageResponse(PageRequest request, IService<T> pageService) {
        // todo 驼峰转下划线后输出到前端
        // 构造查询条件
        QueryWrapper<T> queryWrapper = buildQueryWrapper(request);
        // 构造分页条件 并执行分页查询
        Page<T> page = pageService.page(buildPageRequest(request), queryWrapper);
        return new PageResponse<T>(page.getTotal(), page.getRecords(), request);
    }

    /**
     * 构造查询分页请求
     * @param request 前端分页请求
     * @return
     */
    private static <T> Page<T> buildPageRequest(PageRequest request) {
        // 构造分页请求
        Page<T> page = new Page<>(request.getPage(), request.getPageSize());
        String sortField = request.getSortField();
        // 调整排序规则
        if (EmptyUtil.isValidRequestParam(sortField)) {
            if (SortRuleType.ASC == request.getSortRule()) {
                page.addOrder(OrderItem.asc(sortField));
            } else {
                page.addOrder(OrderItem.desc(sortField));
            }
        }
        return page;
    }


    /**
     * 构造分页的查询 wrapper
     * @param obj
     */
    private static <T> QueryWrapper<T> buildQueryWrapper(PageRequest obj){
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        Method[] methods = obj.getClass().getDeclaredMethods();
        try {
            for (Method m : methods) {
                if (m.getName().startsWith("get")) {
                 // 执行方法get方法 获取属性值
                    Object value = m.invoke(obj);
                    // 获取java 属性名
                    String propertyName = StringUtil.getParamNameWithoutPrefix(m.getName(), null);
                    // 获取db columnName
                    String column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, propertyName);
                    // bugfix 修复删除的查询
                    if (EmptyUtil.isNotEmpty(value)) {
                        if (value instanceof String) {
                            queryWrapper.like(column, value);
                        } else {
                            queryWrapper.eq(column, value);
                        }
                        if (value instanceof Collection) {
                            Collection<?> collection = (Collection<?>) value;
                            queryWrapper.in(collection.size() > 0, column, collection);
                        }
                    }
                    // 必带的条件
                    queryWrapper.eq("delete_status", 0);
                 }
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            log.error("请检查请求分页的参数是否有自定义的字段,目前并不支持自定义请求参数");
            throw GlobalServiceExceptionUtil.sysError(DefaultExceptionEnums.SYSTEM_BUST);
        }
        return queryWrapper;
    }
}

PageRequest



package com.mykj.controller.request;


import com.mykj.annoation.In;
import com.mykj.constant.SortRuleType;
import lombok.Data;

import javax.validation.constraints.Min;

/**
 * 统一分页请求
 * @author fuchen
 */
@Data
public class PageRequest {

    @Min(0L)
    private Integer page = 1;

    @Min(1L)
    private Integer pageSize = 10;

    /**
     * 排序字段
     */
    private String sortField;

    /**
     * 排序规则: desc asc
     */
    @In(values = {SortRuleType.DESC, SortRuleType.ASC})
    private Integer sortRule;

    public PageRequest() { }

    public PageRequest(int page, int pageSize) {
        this.page = page;
        this.pageSize = pageSize;
    }



}


使用

有了上面的封装,卧槽在遇到各种分页查询场景,都轻而一举的服用代码:

在这里插入图片描述
这不香吗,所有的分页查询场景,都可以支持改方式


待升级

目前对于请求参数是自定义类型【非db字段或者对象嵌套】的数据,还无法 做的很好的支持,且遇到模糊查询的场景也是需要后期继续优化的,庆幸的是笔者写这篇的时候,已经在努力的尝试了,尽量完善这个功能啦。。。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值