org.sagacity.sqltoy.utils.MapperUtils Maven / Gradle / Ivy
package org.sagacity.sqltoy.utils;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.sagacity.sqltoy.config.annotation.SqlToyFieldAlias;
import org.sagacity.sqltoy.config.model.DTOEntityMapModel;
import org.sagacity.sqltoy.config.model.DataType;
import org.sagacity.sqltoy.model.IgnoreKeyCaseMap;
import org.sagacity.sqltoy.model.Page;
import org.sagacity.sqltoy.model.PropsMapperConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @project sagacity-sqltoy
* @description 提供针对sqltoy的DTO到POJO、POJO到DTO的映射工具
* @author zhongxuchen
* @version v1.0,Date:2020-8-8
* @modify 2020-09-04 支持VO<->VO,DTO<->DTO,VO<->DTO 的互转
* @modify 2022-10-19 支持对象的多级父类属性的映射
* @modify 2023-05-01 支持多级子对象映射,代码全面改造完全工具类化,无需再依赖SqlToyContext
* @modify 2024-03-15 支持DTO<-->POJO 双向映射中@SqlToyFieldAlias,由gleam反馈
* @modify 2024-05-10 进一步强化对象间映射,增加指定属性映射fieldsMap参数
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class MapperUtils {
/**
* 定义日志
*/
protected final static Logger logger = LoggerFactory.getLogger(MapperUtils.class);
/**
* 利用缓存来提升匹配效率
*/
private static Map dtoEntityMapperCache = new HashMap();
private static ConcurrentHashMap> classHasAliasMap = new ConcurrentHashMap<>();
// 递归最大层级
private static int MAX_RECURSION = 3;
private MapperUtils() {
}
/**
* @TODO DTO<-->POJO 双向映射
* @param
* @param source
* @param resultType
* @param ignoreProperties 忽略的属性
* @return
* @throws RuntimeException
*/
@Deprecated
public static T map(Serializable source, Class resultType, String... ignoreProperties)
throws RuntimeException {
return map(source, resultType, new PropsMapperConfig(ignoreProperties).isIgnore(true));
}
/**
* @TODO DTO<-->POJO 双向映射
* @param
* @param source
* @param resultType
* @param propsMapperConfig 映射属性配置
* @return
* @throws RuntimeException
*/
public static T map(Serializable source, Class resultType,
PropsMapperConfig propsMapperConfig) throws RuntimeException {
if (source == null) {
return null;
}
if (resultType == null || BeanUtil.isBaseDataType(resultType)) {
throw new IllegalArgumentException("resultType 不能为null,且resultType不能为基本类型!");
}
return map(source, resultType, 0, propsMapperConfig);
}
@Deprecated
public static List mapList(List sourceList, Class resultType,
String... ignoreProperties) throws RuntimeException {
return mapList(sourceList, resultType, new PropsMapperConfig(ignoreProperties).isIgnore(true));
}
/**
* @TODO List <--> List 互相映射
* @param
* @param sourceList
* @param resultType
* @param propsMapperConfig
* @return
* @throws RuntimeException
*/
public static List mapList(List sourceList, Class resultType,
PropsMapperConfig propsMapperConfig) throws RuntimeException {
if (sourceList == null) {
return null;
}
if (resultType == null || BeanUtil.isBaseDataType(resultType)) {
throw new IllegalArgumentException("resultType 不能为null,且resultType不能为基本类型!");
}
// resultType不能是接口和抽象类
if (Modifier.isAbstract(resultType.getModifiers()) || Modifier.isInterface(resultType.getModifiers())) {
throw new IllegalArgumentException("resultType:" + resultType.getName() + " 是抽象类或接口,非法参数!");
}
if (sourceList.isEmpty()) {
return new ArrayList();
}
return mapList(sourceList, resultType, 0, propsMapperConfig);
}
/**
* @TODO 分页映射
* @param
* @param sourcePage
* @param resultType
* @param ignoreProperties 忽略的属性
* @return
*/
@Deprecated
public static Page map(Page sourcePage, Class resultType,
String... ignoreProperties) {
return map(sourcePage, resultType, new PropsMapperConfig(ignoreProperties).isIgnore(true));
}
/**
* @TODO 分页映射
* @param
* @param sourcePage
* @param resultType
* @param propsMapperConfig
* @return
*/
public static Page map(Page sourcePage, Class resultType,
PropsMapperConfig propsMapperConfig) {
if (sourcePage == null) {
return null;
}
if (resultType == null || BeanUtil.isBaseDataType(resultType)) {
throw new IllegalArgumentException("resultType 不能为null,且resultType不能为基本类型!");
}
Page result = new Page();
result.setPageNo(sourcePage.getPageNo());
result.setPageSize(sourcePage.getPageSize());
result.setRecordCount(sourcePage.getRecordCount());
result.setSkipQueryCount(sourcePage.getSkipQueryCount());
if (sourcePage.getRows() == null || sourcePage.getRows().isEmpty()) {
return result;
}
result.setRows(mapList(sourcePage.getRows(), resultType, propsMapperConfig));
return result;
}
/**
* @TODO 两个实体对象属性值复制
* @param source
* @param target
* @param ignoreProperties 忽略的不参与复制的属性
* @throws RuntimeException
*/
@Deprecated
public static void copyProperties(Serializable source, Serializable target, String... ignoreProperties)
throws RuntimeException {
copyProperties(source, target, new PropsMapperConfig(ignoreProperties).isIgnore(true));
}
/**
* @TODO 两个实体对象属性值复制
* @param source
* @param target
* @param propsMapperConfig new
* PropsMapperConfig(String...properties).isIgnore(true|false)
* 默认为false
* @throws RuntimeException
*/
public static void copyProperties(Serializable source, Serializable target, PropsMapperConfig propsMapperConfig)
throws RuntimeException {
if (source == null || target == null) {
return;
}
if (BeanUtil.isBaseDataType(source.getClass()) || BeanUtil.isBaseDataType(target.getClass())) {
throw new IllegalArgumentException("copyProperties不支持基本类型对象的属性值映射!");
}
List sourceList = new ArrayList();
sourceList.add(source);
List targetList = new ArrayList();
targetList.add(target);
copyProperties(sourceList, targetList, propsMapperConfig);
}
/**
* @TODO List集合属性映射
* @param sourceList
* @param targetList
* @param copyPropsConfig
* @throws RuntimeException
*/
public static void copyProperties(List sourceList, List targetList, PropsMapperConfig propsMapperConfig)
throws RuntimeException {
if (sourceList == null || sourceList.isEmpty()) {
throw new RuntimeException("copyProperties操作sourceList为空对象");
}
if (targetList == null || targetList.isEmpty()) {
throw new RuntimeException("copyProperties操作targetList为空对象");
}
if (sourceList.size() != targetList.size()) {
throw new RuntimeException("copyProperties操作sourceList和targetList集合数据记录:" + sourceList.size() + "!="
+ targetList.size() + "不相同!");
}
Class sourceClass = sourceList.get(0).getClass();
Class targetClass = targetList.get(0).getClass();
if (BeanUtil.isBaseDataType(sourceClass) || BeanUtil.isBaseDataType(targetClass)) {
throw new IllegalArgumentException("copyProperties不支持基本类型对象的属性值映射!");
}
PropsMapperConfig propConfig = (propsMapperConfig == null) ? new PropsMapperConfig() : propsMapperConfig;
Method[] getMethods;
Method[] setMethods;
// 属性参数未定义即表示全部属性匹配
if (propConfig.isIgnore() || propConfig.getProperties() == null) {
Object[] getSetMethods = matchGetSetMethods(sourceClass, targetClass, propConfig.getFieldsMap(),
propConfig.getProperties());
if (getSetMethods == null) {
return;
}
getMethods = (Method[]) getSetMethods[0];
setMethods = (Method[]) getSetMethods[1];
} else {
// 指定属性映射
getMethods = BeanUtil.matchGetMethods(sourceClass, propConfig.getProperties());
HashMap aliasMap = new HashMap<>();
aliasMap.putAll(getClassAliasMap(sourceClass, true));
aliasMap.putAll(getClassAliasMap(targetClass, false));
aliasMap.putAll(propConfig.getFieldsMap());
setMethods = BeanUtil.matchSetMethods(targetClass, getMappedProps(propConfig.getProperties(), aliasMap));
}
if (getMethods.length < 1 || setMethods.length < 1) {
return;
}
try {
List dataSets = invokeGetValues(sourceList, getMethods);
listToList(dataSets, targetList, setMethods, propsMapperConfig.getSkipNull());
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("copyProperties类型:[" + sourceClass.getName() + "-->"
+ targetClass.getName() + "]映射操作失败:" + e.getMessage());
}
}
@Deprecated
public static void copyProperties(List sourceList, List targetList, String... ignoreProperties)
throws RuntimeException {
copyProperties(sourceList, targetList, new PropsMapperConfig(ignoreProperties).isIgnore(true));
}
/**
* @TODO 实现POJO和VO单个对象之间的相互转换和赋值
* @param
* @param source
* @param resultType
* @param recursionLevel 避免循环递归,默认不能超过3层
* @param ignoreProperties
* @return
* @throws RuntimeException
*/
private static T map(Serializable source, Class resultType, int recursionLevel,
PropsMapperConfig propsMapperConfig) throws RuntimeException {
// 转成List做统一处理
List sourceList = new ArrayList();
sourceList.add(source);
List result = mapList(sourceList, resultType, recursionLevel, propsMapperConfig);
if (result == null || result.isEmpty()) {
return null;
}
return result.get(0);
}
/**
* @TODO 实现POJO和VO对象集合之间的相互转换和赋值
* @param
* @param sqlToyContext
* @param sourceList
* @param targetClass
* @param recursionLevel 避免循环递归,默认不能超过3层
* @param propsMapperConfig 设置映射属性的模型
* @return
* @throws RuntimeException
*/
private static List mapList(List sourceList, Class targetClass, int recursionLevel,
PropsMapperConfig propsMapperConfig) throws RuntimeException {
Class sourceClass = sourceList.iterator().next().getClass();
Method[] getMethods;
Method[] setMethods;
PropsMapperConfig propConfig = (propsMapperConfig == null) ? new PropsMapperConfig() : propsMapperConfig;
// 属性参数未定义即表示全部属性匹配
if (propConfig.isIgnore() || propConfig.getProperties() == null) {
Object[] getSetMethods = matchGetSetMethods(sourceClass, targetClass, propConfig.getFieldsMap(),
propConfig.getProperties());
if (getSetMethods == null) {
return null;
}
getMethods = (Method[]) getSetMethods[0];
setMethods = (Method[]) getSetMethods[1];
} else {
// 指定属性映射
getMethods = BeanUtil.matchGetMethods(sourceClass, propConfig.getProperties());
HashMap aliasMap = new HashMap<>();
aliasMap.putAll(getClassAliasMap(sourceClass, true));
aliasMap.putAll(getClassAliasMap(targetClass, false));
aliasMap.putAll(propConfig.getFieldsMap());
setMethods = BeanUtil.matchSetMethods(targetClass, getMappedProps(propConfig.getProperties(), aliasMap));
}
if (getMethods.length < 1 || setMethods.length < 1) {
return null;
}
try {
List dataSets = invokeGetValues(sourceList, getMethods);
return reflectListToBean(dataSets, targetClass, setMethods, recursionLevel);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("map/mapList,类型:[" + sourceClass.getName() + "-->" + targetClass.getName()
+ "]映射操作失败:" + e.getMessage());
}
}
/**
* @TODO 通过映射关系,提取最终的映射属性名称
* @param sourceProps
* @param sourceTargetMap
* @return
*/
private static String[] getMappedProps(String[] sourceProps, Map sourceTargetMap) {
if (sourceTargetMap == null || sourceTargetMap.isEmpty()) {
return sourceProps;
}
IgnoreKeyCaseMap ignoreKeyCaseMap = new IgnoreKeyCaseMap<>(sourceTargetMap);
String[] resultProps = new String[sourceProps.length];
String key;
for (int i = 0; i < resultProps.length; i++) {
key = sourceProps[i];
if (ignoreKeyCaseMap.containsKey(key)) {
resultProps[i] = ignoreKeyCaseMap.get(key);
} else {
resultProps[i] = key;
}
}
return resultProps;
}
/**
* @TODO 通过get方法获取对象的值放入List中
* @param sourceList
* @param getMethods
* @return
* @throws Exception
*/
private static List invokeGetValues(List sourceList, Method[] getMethods) throws Exception {
List result = new ArrayList();
Object row;
for (int i = 0, n = sourceList.size(); i < n; i++) {
row = sourceList.get(i);
if (row != null) {
List rowData = new ArrayList();
for (Method method : getMethods) {
if (method == null) {
rowData.add(null);
} else {
rowData.add(method.invoke(row));
}
}
result.add(rowData);
}
}
return result;
}
/**
* @TODO 组织构造dto和pojo的映射模型放入缓存,并通过get和set方法调用完成复制过程(比BeanUtils.copyProperties效率高)
* @param sourceClass
* @param resultType
* @param fieldsNameMap
* @return
*/
private static DTOEntityMapModel getDTOEntityMap(Class sourceClass, Class resultType,
Map fieldsNameMap) {
String sourceKey = sourceClass.getName();
String resultKey = resultType.getName();
String mapKey = (fieldsNameMap == null || fieldsNameMap.isEmpty()) ? "" : fieldsNameMap.toString();
String key = "fromClass=".concat(sourceKey).concat(";toClass=").concat(resultKey).concat(";mapKey=")
.concat(mapKey);
// 通过缓存获取
if (dtoEntityMapperCache.containsKey(key)) {
return dtoEntityMapperCache.get(key);
}
DTOEntityMapModel result = sourceMapTarget(sourceClass, resultType, fieldsNameMap);
dtoEntityMapperCache.put(key, result);
return result;
}
/**
* @TODO 解析2个类之间属性名称相同的方法,建立getXXX 和 setXXX 的映射关系
* @param fromClass
* @param targetClass
* @return
*/
private static DTOEntityMapModel sourceMapTarget(Class fromClass, Class targetClass,
Map fieldsNameMap) {
// 不支持基本类型
if (BeanUtil.isBaseDataType(fromClass) || BeanUtil.isBaseDataType(targetClass)) {
return null;
}
// 是否要匹配别名(两个不同对象之间,属性名称不一致,通过注解提供别名模式进行映射)
boolean checkAlias = fromClass.equals(targetClass) ? false : true;
DTOEntityMapModel result = new DTOEntityMapModel();
String fieldName;
SqlToyFieldAlias alias;
IgnoreKeyCaseMap targetPropsMap = new IgnoreKeyCaseMap();
// targetClass类型属性
Class parentClass = targetClass;
IgnoreKeyCaseMap aliasMap = new IgnoreKeyCaseMap();
while (!parentClass.equals(Object.class)) {
for (Field field : parentClass.getDeclaredFields()) {
fieldName = field.getName();
// 不同对象,检查是否有别名
if (checkAlias) {
alias = field.getAnnotation(SqlToyFieldAlias.class);
if (alias != null) {
aliasMap.put(alias.value(), fieldName);
}
}
targetPropsMap.put(fieldName, fieldName);
}
parentClass = parentClass.getSuperclass();
}
// 将指定的属性名称映射最后放入其中
if (fieldsNameMap != null && !fieldsNameMap.isEmpty()) {
aliasMap.putAll(fieldsNameMap);
}
// fromClass
List fromClassProps = new ArrayList();
List targetProps = new ArrayList();
// dto以及其所有父类
parentClass = fromClass;
String aliasName;
while (!parentClass.equals(Object.class)) {
for (Field field : parentClass.getDeclaredFields()) {
fieldName = field.getName();
aliasName = fieldName;
// 不同对象,检查是否有别名
if (checkAlias) {
alias = field.getAnnotation(SqlToyFieldAlias.class);
if (alias != null) {
aliasName = alias.value();
}
}
if (!fromClassProps.contains(fieldName)) {
if (targetPropsMap.containsKey(fieldName)) {
fromClassProps.add(fieldName);
targetProps.add(targetPropsMap.get(fieldName));
} else if (targetPropsMap.containsKey(aliasName)) {
fromClassProps.add(fieldName);
targetProps.add(targetPropsMap.get(aliasName));
} else if (aliasMap.containsKey(fieldName)) {
fromClassProps.add(fieldName);
targetProps.add(aliasMap.get(fieldName));
}
}
}
parentClass = parentClass.getSuperclass();
}
// 模型赋值
result.fromClassName = fromClass.getName();
result.fromProps = (String[]) fromClassProps.toArray(new String[fromClassProps.size()]);
result.targetClassName = targetClass.getName();
result.targetProps = (String[]) targetProps.toArray(new String[targetProps.size()]);
// 没有匹配的属性
if (fromClassProps.isEmpty()) {
return result;
}
result.fromGetMethods = BeanUtil.matchGetMethods(fromClass, result.fromProps);
result.targetSetMethods = BeanUtil.matchSetMethods(targetClass, result.targetProps);
return result;
}
// 提取映射对应的methods
/**
* @todo 利用java.lang.reflect并结合页面的property, 从对象中取出对应方法的值,组成一个List
* @param dataSet
* @param voClass
* @param realMethods
* @param recursionLevel 递归层级
* @return
* @throws Exception
*/
private static List reflectListToBean(List dataSet, Class voClass, Method[] realMethods, int recursionLevel)
throws Exception {
List result = new ArrayList();
int indexSize = realMethods.length;
String[] methodTypes = new String[indexSize];
int[] methodTypeValues = new int[indexSize];
Class[] methodGenTypes = new Class[indexSize];
Boolean[] isList = new Boolean[indexSize];
// 判断List 场景泛型是否是基本类型
Boolean[] notListBaseType = new Boolean[indexSize];
Class methodType;
// 自动适配属性的数据类型
for (int i = 0; i < indexSize; i++) {
isList[i] = Boolean.FALSE;
notListBaseType[i] = Boolean.TRUE;
if (null != realMethods[i]) {
methodType = realMethods[i].getParameterTypes()[0];
methodTypes[i] = methodType.getTypeName();
methodTypeValues[i] = DataType.getType(methodType);
// 非普通类型、非枚举、非Map(DTO)
if ((methodTypeValues[i] == DataType.objectType || methodTypeValues[i] == DataType.listType
|| methodTypeValues[i] == DataType.setType) && !methodType.isEnum()
&& !Map.class.isAssignableFrom(methodType)) {
methodGenTypes[i] = realMethods[i].getParameterTypes()[0];
}
// 泛型
if (realMethods[i].getGenericParameterTypes()[0] instanceof ParameterizedType) {
methodType = (Class) ((ParameterizedType) realMethods[i].getGenericParameterTypes()[0])
.getActualTypeArguments()[0];
methodGenTypes[i] = methodType;
// 非基本类型、非List、非Map、非枚举、非数组
if (!BeanUtil.isBaseDataType(methodType) && !List.class.equals(methodType)
&& !ArrayList.class.equals(methodType) && !methodType.isEnum()
&& !Map.class.isAssignableFrom(methodType) && !methodType.isArray()) {
notListBaseType[i] = Boolean.FALSE;
}
if (realMethods[i].getParameterTypes()[0].equals(List.class)
|| realMethods[i].getParameterTypes()[0].equals(ArrayList.class)) {
isList[i] = Boolean.TRUE;
}
}
}
}
int size;
Object bean;
List row;
List cellList;
Object cellData = null;
Object convertData = null;
PropsMapperConfig emptyConfig = new PropsMapperConfig();
for (int i = 0, end = dataSet.size(); i < end; i++) {
row = (List) dataSet.get(i);
if (row != null) {
bean = voClass.getDeclaredConstructor().newInstance();
size = row.size();
for (int j = 0; j < size; j++) {
cellData = row.get(j);
if (cellData != null && realMethods[j] != null) {
// 基本类型
if (methodTypeValues[j] != DataType.objectType && methodTypeValues[j] != DataType.listType
&& methodTypeValues[j] != DataType.setType) {
realMethods[j].invoke(bean,
BeanUtil.convertType(cellData, methodTypeValues[j], methodTypes[j]));
} // List
else if (methodGenTypes[j] != null && (cellData instanceof List) && isList[j]) {
cellList = (List) cellData;
if (!cellList.isEmpty()) {
if (!notListBaseType[j] && recursionLevel < MAX_RECURSION) {
// 类型映射
List subItems = mapList((List) cellData, methodGenTypes[j], recursionLevel + 1,
emptyConfig);
if (subItems != null && !subItems.isEmpty()) {
realMethods[j].invoke(bean, subItems);
}
}
// 基本类型或特殊类型
else if (cellList.get(0) != null
&& cellList.get(0).getClass().equals(methodGenTypes[j])) {
realMethods[j].invoke(bean, cellList);
}
}
} // DTO->DTO 对象之间转换
else if (recursionLevel < MAX_RECURSION && methodGenTypes[j] != null
&& (cellData instanceof Serializable)) {
convertData = map((Serializable) cellData, methodGenTypes[j], recursionLevel + 1,
emptyConfig);
if (convertData != null) {
realMethods[j].invoke(bean, convertData);
}
} // 类型相同直接赋值
else if (cellData.getClass().getTypeName().equals(methodTypes[j])) {
realMethods[j].invoke(bean, cellData);
}
}
}
result.add(bean);
}
}
return result;
}
/**
* @TODO List和List属性映射,只支持基本类型和类型相同的属性映射
* @param dataSet
* @param targetList
* @param realMethods
* @param skipNull
* @throws Exception
*/
private static void listToList(List dataSet, List targetList, Method[] realMethods, boolean skipNull)
throws Exception {
int indexSize = realMethods.length;
String[] methodTypes = new String[indexSize];
int[] methodTypeValues = new int[indexSize];
Class methodType;
// 自动适配属性的数据类型
for (int i = 0; i < indexSize; i++) {
if (null != realMethods[i]) {
methodType = realMethods[i].getParameterTypes()[0];
methodTypes[i] = methodType.getTypeName();
methodTypeValues[i] = DataType.getType(methodType);
}
}
int size;
Object bean;
List row;
Object cellData = null;
for (int i = 0, end = dataSet.size(); i < end; i++) {
row = (List) dataSet.get(i);
if (row != null) {
bean = targetList.get(i);
size = row.size();
for (int j = 0; j < size; j++) {
cellData = row.get(j);
if (realMethods[j] != null) {
if (cellData != null) {
// 基本类型
if (methodTypeValues[j] != DataType.objectType && methodTypeValues[j] != DataType.listType
&& methodTypeValues[j] != DataType.setType) {
realMethods[j].invoke(bean,
BeanUtil.convertType(cellData, methodTypeValues[j], methodTypes[j]));
} // 类型相同直接赋值
else if (cellData.getClass().getTypeName().equals(methodTypes[j])) {
realMethods[j].invoke(bean, cellData);
}
} else if (!skipNull) {
realMethods[j].invoke(bean,
BeanUtil.convertType(cellData, methodTypeValues[j], methodTypes[j]));
}
}
}
}
}
}
/**
* @TODO 两个类属性匹配,获取对应的getMehtod和setMethod
* @param sourceClass
* @param targetClass
* @param fieldsNameMap
* @param ignoreProperties
* @return
*/
private static Object[] matchGetSetMethods(Class sourceClass, Class targetClass, Map fieldsNameMap,
String... ignoreProperties) {
DTOEntityMapModel mapModel = getDTOEntityMap(sourceClass, targetClass, fieldsNameMap);
if (mapModel == null || mapModel.fromGetMethods == null || mapModel.targetSetMethods == null) {
return null;
}
Method[] getMethods = mapModel.fromGetMethods;
Method[] setMethods = mapModel.targetSetMethods;
// 判断get方法和set方法是否都是null,都是null无需进行后续操作
boolean getAllNull = true;
boolean setAllNull = true;
for (int i = 0; i < getMethods.length; i++) {
if (getMethods[i] != null) {
getAllNull = false;
}
if (setMethods[i] != null) {
setAllNull = false;
}
}
// get方法或set方法都为null,表示是一些类似serialVersionUID类的公共属性,直接返回null
if (getAllNull || setAllNull) {
return null;
}
// 不做映射处理的属性,针对targetClass
if (ignoreProperties != null && ignoreProperties.length > 0) {
List getRealMethods = new ArrayList();
List setRealMethods = new ArrayList();
String methodName;
String ignorePropLow;
Class paramType;
boolean skip;
List ignoreProps = new ArrayList();
for (String ignoreProp : ignoreProperties) {
ignoreProps.add(ignoreProp.toLowerCase());
}
// 以set方法为映射主体
for (int i = 0; i < setMethods.length; i++) {
if (setMethods[i] != null) {
methodName = setMethods[i].getName().toLowerCase();
paramType = setMethods[i].getParameterTypes()[0];
skip = false;
for (int j = 0; j < ignoreProps.size(); j++) {
ignorePropLow = ignoreProps.get(j);
// boolean 类型去除is
if (methodName.equals("set".concat(ignorePropLow))
|| (ignorePropLow.startsWith("is") && paramType.equals(boolean.class)
&& methodName.equals("set".concat(ignorePropLow.substring(2))))) {
skip = true;
// 移除匹配上的属性,避免下次继续匹配
ignoreProps.remove(j);
j--;
break;
}
}
if (!skip) {
getRealMethods.add(getMethods[i]);
setRealMethods.add(setMethods[i]);
}
}
}
if (setRealMethods.size() == 0) {
logger.warn("最终映射对应的属性数量为零,请检查ignoreProperties是否正确,过滤了全部匹配属性!");
return null;
}
getMethods = new Method[setRealMethods.size()];
setMethods = new Method[setRealMethods.size()];
getRealMethods.toArray(getMethods);
setRealMethods.toArray(setMethods);
}
Object[] result = new Object[2];
result[0] = getMethods;
result[1] = setMethods;
return result;
}
/**
* @TODO 提取对象中@SqlToyFieldAlias 属性跟其他对象映射关系
* @param targetClass
* @param doFrom
* @return
*/
private static HashMap getClassAliasMap(Class targetClass, boolean doFrom) {
String typeName = targetClass.getTypeName();
String direction = doFrom ? "from" : "target";
String mapKey = "class=" + typeName + ";direct=" + direction;
HashMap aliasMap = classHasAliasMap.get(mapKey);
if (aliasMap == null) {
aliasMap = new HashMap();
Class parentClass = targetClass;
SqlToyFieldAlias alias;
while (!parentClass.equals(Object.class)) {
for (Field field : parentClass.getDeclaredFields()) {
// 不同对象,检查是否有别名
alias = field.getAnnotation(SqlToyFieldAlias.class);
if (alias != null) {
if (doFrom) {
aliasMap.put(field.getName(), alias.value());
} else {
aliasMap.put(alias.value(), field.getName());
}
}
}
parentClass = parentClass.getSuperclass();
}
classHasAliasMap.put(mapKey, aliasMap);
}
return aliasMap;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy