refactor: 优化 QueryType 枚举值命名并修复部分错误

This commit is contained in:
2024-01-23 23:37:38 +08:00
parent 6dc20e8909
commit f16b968b3f
4 changed files with 156 additions and 153 deletions

View File

@@ -21,8 +21,9 @@ import java.lang.annotation.*;
/** /**
* 查询注解 * 查询注解
* *
* @author Zheng Jie<a href="https://gitee.com/elunez/eladmin">ELADMIN</a>
* @author Charles7c * @author Charles7c
* @author Jasmine
* @author Zheng Jie<a href="https://gitee.com/elunez/eladmin">ELADMIN</a>
* @since 1.0.0 * @since 1.0.0
*/ */
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
@@ -31,15 +32,17 @@ import java.lang.annotation.*;
public @interface Query { public @interface Query {
/** /**
* 属性名数组 * 列名
* columns为空 走实体类的字段并且根据queryType来查询; *
* columns不为空且columns长度为1走columns[0]的字段并且根据queryType来查询 * <p>
* columns为空且columns长度大于1走columns的所有字段 并且根据queryType来查询 columns之间的处理是OR操作。 * columns 为空时,默认取值字段名(自动转换为下划线命名);<br>
* columns 不为空且 columns 长度大于 1多个列查询条件之间为或关系OR
* </p>
*/ */
String[] columns() default {}; String[] columns() default {};
/** /**
* 查询类型(等值查询、模糊查询、范围查询等) * 查询类型(等值查询、模糊查询、范围查询等)
*/ */
QueryType type() default QueryType.EQUAL; QueryType type() default QueryType.EQ;
} }

View File

@@ -16,10 +16,10 @@
package top.charles7c.continew.starter.data.mybatis.plus.query; package top.charles7c.continew.starter.data.mybatis.plus.query;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -30,13 +30,13 @@ import top.charles7c.continew.starter.core.util.validate.ValidationUtils;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* 查询助手 * 查询助手
* *
* @author Zheng Jie<a href="https://gitee.com/elunez/eladmin">ELADMIN</a>
* @author Charles7c * @author Charles7c
* @author Jasmine
* @author Zheng Jie<a href="https://gitee.com/elunez/eladmin">ELADMIN</a>
* @since 1.0.0 * @since 1.0.0
*/ */
@Slf4j @Slf4j
@@ -44,12 +44,12 @@ import java.util.Objects;
public class QueryHelper { public class QueryHelper {
/** /**
* 根据查询条件构建 MyBatis Plus 查询条件封装对象 * 根据查询条件构建查询条件封装对象
* *
* @param query 查询条件 * @param query 查询条件
* @param <Q> 查询条件数据类型 * @param <Q> 查询条件数据类型
* @param <R> 查询数据类型 * @param <R> 查询数据类型
* @return MyBatis Plus 查询条件封装对象 * @return 查询条件封装对象
*/ */
public static <Q, R> QueryWrapper<R> build(Q query) { public static <Q, R> QueryWrapper<R> build(Q query) {
QueryWrapper<R> queryWrapper = new QueryWrapper<>(); QueryWrapper<R> queryWrapper = new QueryWrapper<>();
@@ -57,87 +57,80 @@ public class QueryHelper {
if (null == query) { if (null == query) {
return queryWrapper; return queryWrapper;
} }
// 获取查询条件中所有的字段 // 解析并拼接查询条件
List<Field> fieldList = ReflectUtils.getNonStaticFields(query.getClass()); List<Field> fieldList = ReflectUtils.getNonStaticFields(query.getClass());
fieldList.forEach(field -> buildQuery(query, field, queryWrapper)); fieldList.forEach(field -> buildWrapper(query, field, queryWrapper));
return queryWrapper; return queryWrapper;
} }
/** /**
* 构建 MyBatis Plus 查询条件封装对象 * 构建查询条件封装对象
* *
* @param query 查询条件 * @param query 查询条件
* @param field 字段 * @param field 字段
* @param queryWrapper MyBatis Plus 查询条件封装对象 * @param queryWrapper 查询条件封装对象
* @param <Q> 查询条件数据类型 * @param <Q> 查询条件数据类型
* @param <R> 查询数据类型 * @param <R> 查询数据类型
*/ */
public static <Q, R> void buildQuery(Q query, Field field, QueryWrapper<R> queryWrapper) { public static <Q, R> void buildWrapper(Q query, Field field, QueryWrapper<R> queryWrapper) {
boolean accessible = field.canAccess(query); boolean accessible = field.canAccess(query);
try { try {
field.setAccessible(true); field.setAccessible(true);
String fieldName = field.getName();
String columnName = StrUtil.toUnderlineCase(fieldName);
// 如果字段值为空,直接返回 // 如果字段值为空,直接返回
Object fieldValue = field.get(query); Object fieldValue = field.get(query);
if (ObjectUtil.isEmpty(fieldValue)) { if (ObjectUtil.isEmpty(fieldValue)) {
return; return;
} }
// 建议:数据库规范中列建议采用下划线连接法命名,程序规范中变量建议采用驼峰法命名
// 获取 Query 注解信息 String fieldName = field.getName();
String columnName = StrUtil.toUnderlineCase(fieldName);
// 没有 @Query 注解,默认等值查询
Query queryAnnotation = field.getAnnotation(Query.class); Query queryAnnotation = field.getAnnotation(Query.class);
// 没有@Query注解默认走实体类的字段 EQ精确 查询; if (null == queryAnnotation) {
if (Objects.isNull(queryAnnotation)) {
queryWrapper.eq(columnName, fieldValue); queryWrapper.eq(columnName, fieldValue);
return; return;
} }
// 解析单列查询
String[] columns = queryAnnotation.columns(); String[] columns = queryAnnotation.columns();
if (ArrayUtils.isEmpty(columns)) { final int columnLength = ArrayUtil.length(columns);
columnName = StrUtil.toUnderlineCase(columnName); if (columnLength == 0 || columnLength == 1) {
} else if (columns.length == 1) { columnName = columnLength == 1 ? columns[0] : columnName;
columnName = StrUtil.toUnderlineCase(columns[0]); parse(queryAnnotation.type(), columnName, fieldValue, queryWrapper);
} else {
QueryType queryType = queryAnnotation.type();
queryWrapper.and(wrapper -> {
for (String column : columns) {
String underline = StrUtil.toUnderlineCase(column);
// 解析多属性查询
switch (queryType) {
case EQUAL -> queryWrapper.or().eq(underline, fieldValue);
case NOT_EQUAL -> queryWrapper.or().ne(underline, fieldValue);
case GREATER_THAN -> queryWrapper.or().gt(underline, fieldValue);
case LESS_THAN -> queryWrapper.or().lt(underline, fieldValue);
case GREATER_THAN_OR_EQUAL -> queryWrapper.or().ge(underline, fieldValue);
case LESS_THAN_OR_EQUAL -> queryWrapper.or().le(underline, fieldValue);
case BETWEEN -> {
List<Object> between = new ArrayList<>((List<Object>)fieldValue);
ValidationUtils.throwIf(between.size() != 2, "[{}] 必须是一个范围", fieldName);
queryWrapper.or().between(underline, between.get(0), between.get(1));
}
case LEFT_LIKE -> queryWrapper.or().likeLeft(underline, fieldValue);
case INNER_LIKE -> queryWrapper.or().like(underline, fieldValue);
case RIGHT_LIKE -> queryWrapper.or().likeRight(underline, fieldValue);
case IN -> {
ValidationUtils.throwIfEmpty(fieldValue, "[{}] 不能为空", fieldName);
queryWrapper.or().in(underline, (List<Object>)fieldValue);
}
case NOT_IN -> {
ValidationUtils.throwIfEmpty(fieldValue, "[{}] 不能为空", fieldName);
queryWrapper.or().notIn(underline, (List<Object>)fieldValue);
}
case IS_NULL -> queryWrapper.or().isNull(underline);
case IS_NOT_NULL -> queryWrapper.or().isNotNull(underline);
default -> throw new IllegalArgumentException(String.format("暂不支持 [%s] 查询类型", queryType));
}
}
});
return; return;
} }
// 解析查询条件 // 解析多列查询
parse(queryAnnotation.type(), columnName, fieldValue, queryWrapper); QueryType queryType = queryAnnotation.type();
queryWrapper.nested(wrapper -> {
for (String column : columns) {
switch (queryType) {
case EQ -> queryWrapper.or().eq(column, fieldValue);
case NE -> queryWrapper.or().ne(column, fieldValue);
case GT -> queryWrapper.or().gt(column, fieldValue);
case GE -> queryWrapper.or().ge(column, fieldValue);
case LT -> queryWrapper.or().lt(column, fieldValue);
case LE -> queryWrapper.or().le(column, fieldValue);
case BETWEEN -> {
List<Object> between = new ArrayList<>((List<Object>)fieldValue);
ValidationUtils.throwIf(between.size() != 2, "[{}] 必须是一个范围", fieldName);
queryWrapper.or().between(column, between.get(0), between.get(1));
}
case LIKE -> queryWrapper.or().like(column, fieldValue);
case LIKE_LEFT -> queryWrapper.or().likeLeft(column, fieldValue);
case LIKE_RIGHT -> queryWrapper.or().likeRight(column, fieldValue);
case IN -> {
ValidationUtils.throwIfEmpty(fieldValue, "[{}] 不能为空", fieldName);
queryWrapper.or().in(column, (List<Object>)fieldValue);
}
case NOT_IN -> {
ValidationUtils.throwIfEmpty(fieldValue, "[{}] 不能为空", fieldName);
queryWrapper.or().notIn(column, (List<Object>)fieldValue);
}
case IS_NULL -> queryWrapper.or().isNull(column);
case IS_NOT_NULL -> queryWrapper.or().isNotNull(column);
default -> throw new IllegalArgumentException(String.format("暂不支持 [%s] 查询类型", queryType));
}
}
});
} catch (BadRequestException e) { } catch (BadRequestException e) {
log.error("Build query occurred an validation error: {}. Query: {}, Field: {}.", e log.error("Build query occurred an validation error: {}. Query: {}, Field: {}.", e
.getMessage(), query, field, e); .getMessage(), query, field, e);
@@ -155,30 +148,28 @@ public class QueryHelper {
* @param queryType 查询类型 * @param queryType 查询类型
* @param columnName 驼峰字段名 * @param columnName 驼峰字段名
* @param fieldValue 字段值 * @param fieldValue 字段值
* @param queryWrapper MyBatis Plus 查询条件封装对象 * @param queryWrapper 查询条件封装对象
* @param <R> 查询数据类型 * @param <R> 查询数据类型
*/ */
private static <R> void parse(QueryType queryType, private static <R> void parse(QueryType queryType,
String columnName, String columnName,
Object fieldValue, Object fieldValue,
QueryWrapper<R> queryWrapper) { QueryWrapper<R> queryWrapper) {
// 解析单个属性查询
// 注意:数据库规范中列采用下划线连接法命名,程序规范中变量采用驼峰法命名
switch (queryType) { switch (queryType) {
case EQUAL -> queryWrapper.eq(columnName, fieldValue); case EQ -> queryWrapper.eq(columnName, fieldValue);
case NOT_EQUAL -> queryWrapper.ne(columnName, fieldValue); case NE -> queryWrapper.ne(columnName, fieldValue);
case GREATER_THAN -> queryWrapper.gt(columnName, fieldValue); case GT -> queryWrapper.gt(columnName, fieldValue);
case LESS_THAN -> queryWrapper.lt(columnName, fieldValue); case GE -> queryWrapper.ge(columnName, fieldValue);
case GREATER_THAN_OR_EQUAL -> queryWrapper.ge(columnName, fieldValue); case LT -> queryWrapper.lt(columnName, fieldValue);
case LESS_THAN_OR_EQUAL -> queryWrapper.le(columnName, fieldValue); case LE -> queryWrapper.le(columnName, fieldValue);
case BETWEEN -> { case BETWEEN -> {
List<Object> between = new ArrayList<>((List<Object>)fieldValue); List<Object> between = new ArrayList<>((List<Object>)fieldValue);
ValidationUtils.throwIf(between.size() != 2, "[{}] 必须是一个范围", columnName); ValidationUtils.throwIf(between.size() != 2, "[{}] 必须是一个范围", columnName);
queryWrapper.between(columnName, between.get(0), between.get(1)); queryWrapper.between(columnName, between.get(0), between.get(1));
} }
case LEFT_LIKE -> queryWrapper.likeLeft(columnName, fieldValue); case LIKE -> queryWrapper.like(columnName, fieldValue);
case INNER_LIKE -> queryWrapper.like(columnName, fieldValue); case LIKE_LEFT -> queryWrapper.likeLeft(columnName, fieldValue);
case RIGHT_LIKE -> queryWrapper.likeRight(columnName, fieldValue); case LIKE_RIGHT -> queryWrapper.likeRight(columnName, fieldValue);
case IN -> { case IN -> {
ValidationUtils.throwIfEmpty(fieldValue, "[{}] 不能为空", columnName); ValidationUtils.throwIfEmpty(fieldValue, "[{}] 不能为空", columnName);
queryWrapper.in(columnName, (List<Object>)fieldValue); queryWrapper.in(columnName, (List<Object>)fieldValue);

View File

@@ -30,62 +30,72 @@ import lombok.RequiredArgsConstructor;
public enum QueryType { public enum QueryType {
/** /**
* 等值查询例如WHERE `age` = 18 * 等于 =例如WHERE `age` = 18
*/ */
EQUAL(1, "="), EQ,
/** /**
* 非等值查询例如WHERE `age` != 18 * 不等于 !=例如WHERE `age` != 18
*/ */
NOT_EQUAL(2, "!="), NE,
/** /**
* 大于查询例如WHERE `age` > 18 * 大于 >例如WHERE `age` > 18
*/ */
GREATER_THAN(3, ">"), GT,
/** /**
* 小于查询例如WHERE `age` < 18 * 大于等于 >= 例如WHERE `age` >= 18
*/ */
LESS_THAN(4, "<"), GE,
/** /**
* 大于等于查询例如WHERE `age` >= 18 * 小于 <例如WHERE `age` < 18
*/ */
GREATER_THAN_OR_EQUAL(5, ">="), LT,
/** /**
* 小于等于查询例如WHERE `age` <= 18 * 小于等于 <=例如WHERE `age` <= 18
*/ */
LESS_THAN_OR_EQUAL(6, "<="), LE,
/** /**
* 范围查询例如WHERE `age` BETWEEN 10 AND 18 * 范围查询例如WHERE `age` BETWEEN 10 AND 18
*/ */
BETWEEN(7, "BETWEEN"), BETWEEN,
/** /**
* 左模糊查询例如WHERE `nickname` LIKE '%s' * LIKE '%值%'例如WHERE `nickname` LIKE '%s%'
*/ */
LEFT_LIKE(8, "LIKE '%s'"), LIKE,
/** /**
* 中模糊查询例如WHERE `nickname` LIKE '%s%' * LIKE '%值'例如WHERE `nickname` LIKE '%s'
*/ */
INNER_LIKE(9, "LIKE '%s%'"), LIKE_LEFT,
/** /**
* 右模糊查询例如WHERE `nickname` LIKE 's%' * LIKE '值%'例如WHERE `nickname` LIKE 's%'
*/ */
RIGHT_LIKE(10, "LIKE 's%'"), LIKE_RIGHT,
/** /**
* 包含查询例如WHERE `age` IN (10, 20, 30) * 包含查询例如WHERE `age` IN (10, 20, 30)
*/ */
IN(11, "IN"), IN,
/** /**
* 不包含查询例如WHERE `age` NOT IN (20, 30) * 不包含查询例如WHERE `age` NOT IN (20, 30)
*/ */
NOT_IN(12, "NOT IN"), NOT_IN,
/** /**
* 空查询例如WHERE `email` IS NULL * 空查询例如WHERE `email` IS NULL
*/ */
IS_NULL(13, "IS NULL"), IS_NULL,
/** /**
* 非空查询例如WHERE `email` IS NOT NULL * 非空查询例如WHERE `email` IS NOT NULL
*/ */
IS_NOT_NULL(14, "IS NOT NULL"),; IS_NOT_NULL,;
private final Integer value;
private final String description;
} }

View File

@@ -51,7 +51,6 @@ import top.charles7c.continew.starter.file.excel.util.ExcelUtils;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@@ -77,8 +76,8 @@ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseDO,
protected final Class<L> listClass = this.currentListClass(); protected final Class<L> listClass = this.currentListClass();
protected final Class<D> detailClass = this.currentDetailClass(); protected final Class<D> detailClass = this.currentDetailClass();
protected final Class<Q> queryClass = this.currentQueryClass(); protected final Class<Q> queryClass = this.currentQueryClass();
private final Field[] entityFields = this.entityClass.getDeclaredFields(); private final List<Field> entityFields = ReflectUtils.getNonStaticFields(this.entityClass);
private final List<Field> queryFields = ReflectUtils.getNonStaticFields(queryClass); private final List<Field> queryFields = ReflectUtils.getNonStaticFields(this.queryClass);
@Override @Override
public PageResp<L> page(Q query, PageQuery pageQuery) { public PageResp<L> page(Q query, PageQuery pageQuery) {
@@ -193,46 +192,6 @@ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseDO,
return this.getById(id, true); return this.getById(id, true);
} }
/**
* 填充数据
*
* @param obj 待填充信息
*/
protected void fill(Object obj) {
if (null == obj) {
return;
}
OperateTemplate operateTemplate = SpringUtil.getBean(OperateTemplate.class);
operateTemplate.execute(obj);
}
/**
* 设置排序
*
* @param queryWrapper 查询 Wrapper
* @param sortQuery 排序查询条件
*/
protected void sort(QueryWrapper<T> queryWrapper, SortQuery sortQuery) {
Sort sort = Opt.ofNullable(sortQuery).orElseGet(SortQuery::new).getSort();
for (Sort.Order order : sort) {
if (null != order) {
String property = order.getProperty();
String checkProperty;
// 携带表别名,获取.后面的字段名
if (property.contains(StringConstants.DOT)) {
checkProperty = CollectionUtil.getLast(StrUtil.split(property, StringConstants.DOT));
} else {
checkProperty = property;
}
Optional<Field> optional = Arrays.stream(entityFields)
.filter(field -> checkProperty.equals(field.getName()))
.findFirst();
ValidationUtils.throwIf(optional.isEmpty(), "无效的排序字段 [{}]。", property);
queryWrapper.orderBy(true, order.isAscending(), StrUtil.toUnderlineCase(property));
}
}
}
/** /**
* 根据 ID 查询 * 根据 ID 查询
* *
@@ -249,9 +208,49 @@ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseDO,
} }
/** /**
* 获取当前详情信息类型 * 设置排序
* *
* @return 当前详情信息类型 * @param queryWrapper 查询条件封装对象
* @param sortQuery 排序查询条件
*/
protected void sort(QueryWrapper<T> queryWrapper, SortQuery sortQuery) {
Sort sort = Opt.ofNullable(sortQuery).orElseGet(SortQuery::new).getSort();
for (Sort.Order order : sort) {
if (null != order) {
String property = order.getProperty();
String checkProperty;
// 携带表别名则获取 . 后面的字段名
if (property.contains(StringConstants.DOT)) {
checkProperty = CollectionUtil.getLast(StrUtil.split(property, StringConstants.DOT));
} else {
checkProperty = property;
}
Optional<Field> optional = entityFields.stream()
.filter(field -> checkProperty.equals(field.getName()))
.findFirst();
ValidationUtils.throwIf(optional.isEmpty(), "无效的排序字段 [{}]", property);
queryWrapper.orderBy(true, order.isAscending(), StrUtil.toUnderlineCase(property));
}
}
}
/**
* 填充数据
*
* @param obj 待填充信息
*/
protected void fill(Object obj) {
if (null == obj) {
return;
}
OperateTemplate operateTemplate = SpringUtil.getBean(OperateTemplate.class);
operateTemplate.execute(obj);
}
/**
* 封装查询条件
*
* @return 查询条件封装对象
*/ */
protected QueryWrapper<T> handleQueryWrapper(Q query) { protected QueryWrapper<T> handleQueryWrapper(Q query) {
QueryWrapper<T> queryWrapper = new QueryWrapper<>(); QueryWrapper<T> queryWrapper = new QueryWrapper<>();
@@ -259,8 +258,8 @@ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseDO,
if (null == query) { if (null == query) {
return queryWrapper; return queryWrapper;
} }
// 获取查询条件中所有的字段 // 解析并拼接查询条件
queryFields.forEach(field -> QueryHelper.buildQuery(query, field, queryWrapper)); queryFields.forEach(field -> QueryHelper.buildWrapper(query, field, queryWrapper));
return queryWrapper; return queryWrapper;
} }
@@ -343,9 +342,9 @@ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseDO,
} }
/** /**
* 获取当前查询类型 * 获取当前查询条件类型
* *
* @return 当前查询类型 * @return 当前查询条件类型
*/ */
protected Class<Q> currentQueryClass() { protected Class<Q> currentQueryClass() {
return (Class<Q>)this.typeArguments[4]; return (Class<Q>)this.typeArguments[4];