定义DTO
package com.lbdj.user.service.dto;
import com.lbdj.toolkit.utils.ReturnField;
import com.lbdj.toolkit.utils.SFunction;
import lombok.Data;
/**
* 用户DTO
*
* @author 作者
* @since 2023-06-27
*/
@Data
public class LbdjUserDTO {
/**
* 主键
*/
private Long id;
private String userNo;
/**
* 昵称
*/
private String nickName;
/**
* 密码
*/
private String password;
/**
* 查询条数
*/
private Integer limit;
/**
* 需要返回的列(DTO列名)
*/
private String columnStr;
public <T> void setReturnField(SFunction<T, ?>... columns) {
this.columnStr = ReturnField.select(columns);
}
}
DTO调用方式
工具类1(适用在没有mybatis-plus包的情况下)
package com.lbdj.toolkit.utils;
import java.io.Serializable;
import java.util.function.Function;
@FunctionalInterface
public interface SFunction<T, R> extends Function<T, R>, Serializable {
}
package com.lbdj.toolkit.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;
@SuppressWarnings("unused")
public class SerializedLambda implements Serializable {
private static final long serialVersionUID = 8025925345765570181L;
private Class<?> capturingClass;
private String functionalInterfaceClass;
private String functionalInterfaceMethodName;
private String functionalInterfaceMethodSignature;
private String implClass;
private String implMethodName;
private String implMethodSignature;
private int implMethodKind;
private String instantiatedMethodType;
private Object[] capturedArgs;
/**
* 通过反序列化转换 lambda 表达式,该方法只能序列化 lambda 表达式,不能序列化接口实现或者正常非 lambda 写法的对象
*
* @param lambda lambda对象
* @return 返回解析后的 SerializedLambda
*/
public static SerializedLambda resolve(SFunction<?, ?> lambda) {
if (!lambda.getClass().isSynthetic()) {
throw new RuntimeException("该方法仅能传入 lambda 表达式产生的合成类");
}
try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(serialize(lambda))) {
@Override
protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
Class<?> clazz;
try {
clazz = toClassConfident(objectStreamClass.getName());
} catch (Exception ex) {
clazz = super.resolveClass(objectStreamClass);
}
return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz;
}
}) {
return (SerializedLambda) objIn.readObject();
} catch (ClassNotFoundException | IOException e) {
throw new RuntimeException("This is impossible to happen",e);
}
}
/**
* 获取接口 class
*
* @return 返回 class 名称
*/
public String getFunctionalInterfaceClassName() {
return normalizedName(functionalInterfaceClass);
}
/**
* 获取 class 的名称
*
* @return 类名
*/
public String getImplClassName() {
return normalizedName(implClass);
}
/**
* 获取实现者的方法名称
*
* @return 方法名称
*/
public String getImplMethodName() {
return implMethodName;
}
/**
* 正常化类名称,将类名称中的 / 替换为 .
*
* @param name 名称
* @return 正常的类名
*/
private String normalizedName(String name) {
return name.replace('/', '.');
}
/**
* @return 获取实例化方法的类型
*/
public Class<?> getInstantiatedType() {
String instantiatedTypeName = normalizedName(instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(';')));
return toClassConfident(instantiatedTypeName);
}
/**
* @return 字符串形式
*/
@Override
public String toString() {
String interfaceName = getFunctionalInterfaceClassName();
String implName = getImplClassName();
return String.format("%s -> %s::%s",
interfaceName.substring(interfaceName.lastIndexOf('.') + 1),
implName.substring(implName.lastIndexOf('.') + 1),
implMethodName);
}
public static Class<?> toClassConfident(String name) {
try {
return classForName(name);
} catch (ClassNotFoundException e) {
try {
return Class.forName(name);
} catch (ClassNotFoundException ex) {
throw new RuntimeException("找不到指定的class!请仅在明确确定会有 class 的时候,调用该方法", e);
}
}
}
private static ClassLoaderWrapper classLoaderWrapper = new ClassLoaderWrapper();
public static Class<?> classForName(String className) throws ClassNotFoundException {
return classLoaderWrapper.classForName(className);
}
public static byte[] serialize(Object object) {
if (object == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(object);
oos.flush();
} catch (IOException ex) {
throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
}
return baos.toByteArray();
}
}
package com.lbdj.toolkit.utils;
public class ClassLoaderWrapper {
ClassLoader defaultClassLoader;
ClassLoader systemClassLoader;
ClassLoaderWrapper() {
try {
systemClassLoader = ClassLoader.getSystemClassLoader();
} catch (SecurityException ignored) {
// AccessControlException on Google App Engine
}
}
public Class<?> classForName(String name) throws ClassNotFoundException {
return classForName(name, getClassLoaders(null));
}
Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {
for (ClassLoader cl : classLoader) {
if (null != cl) {
try {
return Class.forName(name, true, cl);
} catch (ClassNotFoundException e) {
// we'll ignore this until all classloaders fail to locate the class
}
}
}
throw new ClassNotFoundException("Cannot find class: " + name);
}
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
return new ClassLoader[]{
classLoader,
defaultClassLoader,
Thread.currentThread().getContextClassLoader(),
getClass().getClassLoader(),
systemClassLoader};
}
}
package com.lbdj.toolkit.utils;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
* 通过lambda获取字段名
*/
public class ReturnField {
/**
* SerializedLambda 反序列化缓存
*/
private static final Map<String, WeakReference<SerializedLambda>> FUNC_CACHE = new ConcurrentHashMap<>();
@SafeVarargs
public final static <T> String select(SFunction<T, ?>... columns) {
if(columns == null || columns.length == 0){
return null;
}
HashSet<String> returnField = new HashSet<>(8);
Arrays.stream(columns).forEach(col -> {
String fieldName = parseFunction(col);
returnField.add(fieldName);
});
StringBuffer colStrBuffer = new StringBuffer();
returnField.forEach(m -> {
colStrBuffer.append(m).append(",");
});
if (colStrBuffer.toString().endsWith(",")) {
colStrBuffer.replace(colStrBuffer.toString().length() - 1, colStrBuffer.toString().length(), "");
}
String colStr = colStrBuffer.toString();
return colStr;
}
public static <T> String parseFunction(SFunction<T, ?> function) {
SerializedLambda serializedLambda = resolve(function);
String fieldName = methodToProperty(serializedLambda.getImplMethodName());
return fieldName;
}
public static String methodToProperty(String name) {
if (name.startsWith("is")) {
name = name.substring(2);
} else {
if (!name.startsWith("get") && !name.startsWith("set")) {
throw new RuntimeException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
}
name = name.substring(3);
}
if (name.length() == 1 || name.length() > 1 && !Character.isUpperCase(name.charAt(1))) {
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}
public static <T> SerializedLambda resolve(SFunction<T, ?> func) {
Class<?> clazz = func.getClass();
String name = clazz.getName();
return Optional.ofNullable(FUNC_CACHE.get(name))
.map(WeakReference::get)
.orElseGet(() -> {
SerializedLambda lambda = SerializedLambda.resolve(func);
FUNC_CACHE.put(name, new WeakReference<>(lambda));
return lambda;
});
}
}
工具类2(适用在有mybatis-plus包的情况下)
Mapper通用查询方法
@Override
public List<LbdjUserDTO> selectBase(LbdjUserDTO request) {
LbdjUser user = BeanConvertUtils.convert(request, LbdjUser::new, null);
QueryWrapper<LbdjUser> queryWrapper = new QueryWrapper<>();
//封装返回字段&查询条件
InitCommonQueryUtils.initQuery(user, request.getColumnStr(), queryWrapper);
queryWrapper.last(" limit " + request.getLimit());
List<LbdjUser> result = list(queryWrapper);
if (CollectionUtils.isEmpty(result)) {
return Arrays.asList();
}
return BeanConvertUtils.convertList(result, LbdjUserDTO::new);
}
package com.lbdj.user.service.common.utils;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lbdj.user.service.common.advice.exception.RRException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class InitCommonQueryUtils {
public static <T> void initQuery(T entity, String columnStr, QueryWrapper<T> queryWrapper) {
Class<T> type = (Class<T>) entity.getClass();
TableName annotation = type.getAnnotation(TableName.class);
if (annotation == null) {
throw new RRException("非数据库实体类");
}
//返回字段
StringBuilder columns = new StringBuilder();
//查询条件
HashMap<String, Object> paramMap = new HashMap<>();
Field[] declaredFields = type.getDeclaredFields();
List<String> columnArr = null;
if (null != columnStr && !"".equals(columnStr)) {
columnArr = Arrays.asList(columnStr.split(","));
}
/**
* 有兼容历史问题,表中字段半驼峰、非驼峰问题
*/
for (Field declaredField : declaredFields) {
//设置属性可访问
declaredField.setAccessible(true);
//属性名
String name = declaredField.getName();
//获取主键
TableId tableId = declaredField.getAnnotation(TableId.class);
//获取非主键的
TableField tableField = declaredField.getAnnotation(TableField.class);
//拼接返回字段
appendReturnField(name, columnArr, columns, tableId, tableField);
//拼接查询条件
appendCondition(entity, paramMap, declaredField, name, tableId, tableField);
}
//返回字段
if (columns.length() > 0) {
queryWrapper.select(columns.toString());
}
//查询条件
if (paramMap.size() > 0) {
queryWrapper.allEq(paramMap, false);
}
}
private static void appendReturnField(String name,
List<String> columnArr,
StringBuilder columns,
TableId tableId,
TableField tableField) {
if (null == columnArr) {
return;
}
if (!columnArr.contains(name)) {
return;
}
if (tableId != null) {
if (columns.length() > 0) {
columns.append(",");
}
columns.append(tableId.value());
return;
}
if (tableField != null) {
if (columns.length() > 0) {
columns.append(",");
}
if (tableField.exist()) {
//是数据表字段,不是数据表字段不处理
columns.append(tableField.value());
}
}
}
private static <T> void appendCondition(T entity,
HashMap<String, Object> paramMap,
Field declaredField,
String name,
TableId tableId,
TableField tableField) {
// 获取属性的值
Object value = null;
try {
value = declaredField.get(entity);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
if (null == value) {
return;
}
if (tableId != null) {
paramMap.put(tableId.value(), value);
return;
}
if (tableField != null) {
if (tableField.exist()) {
//是数据表字段,不是数据表字段不处理
paramMap.put(tableField.value(), value);
}
return;
}
//处理没有加注解的属性(兼容完全服务驼峰规范的数据表)
if (!Modifier.isStatic(declaredField.getModifiers())) {
paramMap.put(name, value);
}
}
}