【最新更新:2021.07.24】
【更新功能:新增模糊识别,集合匹配;修复自定义分页请求后返回已经删除的数据】
背景
- 你还在不断的用wrapper 去 eq 、like吗?
- 你还在纠结字段排序后分页结果如何展示问题吗?
- 你还在同样的逻辑上做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字段或者对象嵌套】的数据,还无法 做的很好的支持,且遇到模糊查询的场景也是需要后期继续优化的,庆幸的是笔者写这篇的时候,已经在努力的尝试了,尽量完善这个功能啦。。。