基于Mybatis-Plus进行查询封装
package com.test.common.orm.builder;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.impl.PerpetualCache;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
public final class QueryWrapperBuilder {
private static final Cache FILED_CACHE = new PerpetualCache(IdUtil.simpleUUID());
private static final Cache METHOD_CACHE = new PerpetualCache(IdUtil.simpleUUID());
private static final char[] UPPER_CASE_CHAR_ARRAY = new char[26];
static {
UPPER_CASE_CHAR_ARRAY[0]='A';UPPER_CASE_CHAR_ARRAY[1]='B';UPPER_CASE_CHAR_ARRAY[2]='C';
UPPER_CASE_CHAR_ARRAY[3]='D';UPPER_CASE_CHAR_ARRAY[4]='E';UPPER_CASE_CHAR_ARRAY[5]='F';
UPPER_CASE_CHAR_ARRAY[6]='G';UPPER_CASE_CHAR_ARRAY[7]='H';UPPER_CASE_CHAR_ARRAY[8]='I';
UPPER_CASE_CHAR_ARRAY[9]='J';UPPER_CASE_CHAR_ARRAY[10]='K';UPPER_CASE_CHAR_ARRAY[11]='L';
UPPER_CASE_CHAR_ARRAY[12]='M';UPPER_CASE_CHAR_ARRAY[13]='N';UPPER_CASE_CHAR_ARRAY[14]='O';
UPPER_CASE_CHAR_ARRAY[15]='P';UPPER_CASE_CHAR_ARRAY[16]='Q';UPPER_CASE_CHAR_ARRAY[17]='R';
UPPER_CASE_CHAR_ARRAY[18]='S';UPPER_CASE_CHAR_ARRAY[19]='T';UPPER_CASE_CHAR_ARRAY[20]='U';
UPPER_CASE_CHAR_ARRAY[21]='V';UPPER_CASE_CHAR_ARRAY[22]='W';UPPER_CASE_CHAR_ARRAY[23]='X';
UPPER_CASE_CHAR_ARRAY[24]='Y';UPPER_CASE_CHAR_ARRAY[25]='Z';
}
public static <T>QueryWrapper<T> buildListWrapper(final Class<T> entityClass, final Object voObject, Integer... group) {
Assert.isTrue(null != entityClass,"entityClass cannot be null");
Assert.isTrue(null != voObject,"voObject cannot be null");
if(group != null && group.length > 1) {
throw new IllegalArgumentException("group cannot greater than one");
}
AtomicInteger defaultGroup = new AtomicInteger(-1);
if(null == group || group.length <= 0) {
defaultGroup.set(1);
} else {
defaultGroup.set(group[0]);
}
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
Class<?> voObjectClass = voObject.getClass();
String voClassName = voObjectClass.getName();
Field[] fields = (Field[]) FILED_CACHE.getObject(voClassName);
if(null == fields) {
fields = voObjectClass.getDeclaredFields();
if(fields.length > 0) {
FILED_CACHE.putObject(voClassName, fields);
} else {
throw new IllegalArgumentException("voObject [" + voClassName + "] not has fields");
}
}
Stream<Field> stream = Arrays.stream(fields);
stream.forEach(field -> {
if(field.isAnnotationPresent(QueryOperation.class) || field.isAnnotationPresent(QueryOperations.class)) {
String fieldName = field.getName();
String columnName = fieldToColumnName(fieldName);
Annotation[] annotations = field.getAnnotations();
List<QueryOperation> list = new ArrayList<>();
for(Annotation annotation : annotations) {
if(annotation instanceof QueryOperations) {
QueryOperation[] queryOperations = ((QueryOperations) annotation).value();
list.addAll(Arrays.asList(queryOperations));
} else if(annotation instanceof QueryOperation){
list.add((QueryOperation) annotation);
}
}
QueryOperation queryOperation =
list.stream().filter(annotation ->
annotation.group() == defaultGroup.get())
.findFirst().orElse(null);
if(null != queryOperation) {
String annoColumnName = queryOperation.columnName();
if(StringUtils.hasText(annoColumnName)) {
columnName = annoColumnName;
}
QueryOperationType queryOperationType = queryOperation.value();
String methodName = fileNameToMethodName(fieldName,"get");
String key = voClassName + "@" + methodName;
Method method = (Method) METHOD_CACHE.getObject(key);
if(null == method) {
method = ReflectionUtils.findMethod(voObjectClass, methodName);
METHOD_CACHE.putObject(key,method);
}
Assert.notNull(method,"method : [ " + methodName + " ] not exists in class : [ " + voObjectClass.getName() + "]");
Object o = ReflectionUtils.invokeMethod(method, voObject);
setQueryWrapper(queryWrapper,queryOperationType,columnName,o);
}
}
});
return queryWrapper;
}
public static String fieldToColumnName(String fieldName) {
Assert.isTrue(StringUtils.hasText(fieldName), "fieldName must contains at least one character");
char[] chars = fieldName.toCharArray();
List<Integer> indexList = new ArrayList<>();
for(int i=0;i<chars.length;i++) {
char val = chars[i];
for(char charVal : UPPER_CASE_CHAR_ARRAY) {
if(val == charVal) {
indexList.add(i);
break;
}
}
}
fieldName = fieldName.toLowerCase(Locale.ENGLISH);
StringBuilder columnName = new StringBuilder(fieldName);
indexList.forEach(index->{
columnName.insert(index,"_");
});
return columnName.toString();
}
public static String fileNameToMethodName(final String fieldName,String prefix) {
return prefix + fieldName.substring(0,1).toUpperCase(Locale.ENGLISH) + fieldName.substring(1);
}
private static void setQueryWrapper(QueryWrapper<?> queryWrapper, QueryOperationType queryOperationType,
String columnName, Object o) {
boolean canSet = false;
if(o instanceof String) {
canSet = StringUtils.hasLength((CharSequence)o) ;
} else {
canSet = null != o ;
}
if(canSet) {
if(queryOperationType == QueryOperationType.EQUAL) {
queryWrapper.eq(columnName,o);
} else if(queryOperationType == QueryOperationType.NOT_EQUAL) {
queryWrapper.ne(columnName,o);
} else if(queryOperationType == QueryOperationType.LIKE) {
queryWrapper.like(columnName,o);
} else if(queryOperationType == QueryOperationType.BETWEEN) {
if(!(o instanceof Collection<?>)) {
throw new UnsupportedOperationException("只对集合支持between操作");
}
if(((Collection<?>) o).size() < 2) {
throw new IllegalArgumentException("集合中元素的数量异常");
}
Object[] objArr = ((Collection<?>) o).toArray();
queryWrapper.between(columnName, objArr[0], objArr[1]);
} else if(queryOperationType == QueryOperationType.ORDER_ASC) {
queryWrapper.orderByAsc(columnName);
} else if(queryOperationType == QueryOperationType.ORDER_DESC) {
queryWrapper.orderByDesc(columnName);
}
}
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(QueryOperations.class)
public @interface QueryOperation {
QueryOperationType value() default QueryOperationType.EQUAL;
int group() default 1;
String columnName() default "";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface QueryOperations {
QueryOperation[] value();
}
public enum QueryOperationType {
EQUAL("equal"),NOT_EQUAL("not_equal"),LIKE("like"),BETWEEN("between"),ORDER_DESC("order_desc"),ORDER_ASC("order_asc");
private final String operationType;
QueryOperationType(String operationType) {
this.operationType = operationType;
}
}
}