一行代码调用效果:
QueryWrapper<Department> queryWrapper = QueryBuilder.toQueryWrapper(departmentDto);
//dto中的注解示例
public class DepartmentDto { // 默认equals比较,无需指定 private Long parentId; //指定条件匹配方式 @BindQuery(comparison = Comparison.CONTAINS) private String name; }
Mybatis-plus的查询构造器可以方便的构建单表的SQL查询,你可以在controller里接收到请求参数然后转成查询条件,比如部门的搜索查询代码类似这样:
DepartmentDTO dto = …; LambdaQueryWrapper<Department> queryWrapper = new QueryWrapper<Department>().lambda(); if(dto.getOrgId() != null){ queryWrapper.eq(Department::getOrgId, dto.getOrgId()); } if(dto.getName() != null){ queryWrapper.like(Department::getName, dto.getName()); }
其他对象的查询代码也极为相似,差异无非是对象不同、字段不同,如何提供更简单通用的解决方案呢?
可以通过注解实现。
首先,定义注解及支持的匹配方式枚举。
匹配方式枚举定义:
public enum Comparison { EQ, // 相等,默认 IN, // IN STARTSWITH, //以xx起始 CONTAINS, //包含,等同LIKE GT, // 大于 GE, // 大于等于 LT, // 小于 LE // 小于等于 }
注解定义 :
(参与查询的大多数场景是匹配条件为“=相等”,为了减少代码量,我们默认无注解即为“相等”)
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface BindQuery { /** * 查询条件匹配方式 */ Comparison comparison() default Comparison.EQ; }
在DTO中有值的字段才需要参与查询,这需要我们提供一个方法提取dto中的非空字段和值。
示例代码:
/** * 提取非空字段及值 */ private static <DTO> LinkedHashMap<String, Object> extractNotNullValues(DTO dto){ LinkedHashMap<String, Object> resultMap = new LinkedHashMap<>(); Class<?> dtoClass = dto.getClass(); // 转换 List<Field> declaredFields = BeanUtils.extractAllFields(dtoClass); for (Field field : declaredFields) { //忽略static,以及final,transient boolean isStatic = Modifier.isStatic(field.getModifiers()); boolean isFinal = Modifier.isFinal(field.getModifiers()); boolean isTransient = Modifier.isTransient(field.getModifiers()); if (isStatic || isFinal || isTransient) { continue; } //打开私有访问 获取值 field.setAccessible(true); Object value = field.get(dto); if (value != null) { resultMap.put(field.getName(), value); } } return resultMap; }
最后,实现提取非空字段,基于注解匹配方式,构建QueryWrapper:
/** * 转换具体实现 */ private static <DTO> QueryWrapper<DTO> dtoToWrapper(DTO dto){ QueryWrapper wrapper = new QueryWrapper<>(); // 转换 LinkedHashMap<String, Object> fieldValuesMap = extractNotNullValues(dto); if(V.isEmpty(fieldValuesMap)){ return wrapper; } // 构建QueryWrapper for(Map.Entry<String, Object> entry : fieldValuesMap.entrySet()){ Field field = BeanUtils.extractField(dto.getClass(), entry.getKey()); Object value = entry.getValue(); // 字段名转换为列名 String columnName = getColumnName(field); // 对比类型 Comparison comparison = Comparison.EQ; switch (comparison) { case EQ: wrapper.eq(columnName, value); break; case GT: wrapper.gt(columnName, value); break; ... //其他匹配条件 } } return wrapper; }
Diboot - 为开发人员打造的低代码开发平台