org.sagacity.sqltoy.utils.BeanUtil Maven / Gradle / Ivy
package org.sagacity.sqltoy.utils;
import static java.lang.System.err;
import java.io.BufferedReader;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Array;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import org.sagacity.sqltoy.callback.ReflectPropsHandler;
import org.sagacity.sqltoy.config.annotation.Entity;
import org.sagacity.sqltoy.config.annotation.OneToMany;
import org.sagacity.sqltoy.config.annotation.OneToOne;
import org.sagacity.sqltoy.config.annotation.SqlToyEntity;
import org.sagacity.sqltoy.config.model.DataType;
import org.sagacity.sqltoy.config.model.EntityMeta;
import org.sagacity.sqltoy.config.model.KeyAndIndex;
import org.sagacity.sqltoy.config.model.TableCascadeModel;
import org.sagacity.sqltoy.exception.DataAccessException;
import org.sagacity.sqltoy.model.IgnoreKeyCaseMap;
import org.sagacity.sqltoy.plugins.TypeHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @project sagacity-sqltoy
* @description 类处理通用工具,提供反射处理
* @author zhongxuchen
* @version v1.0,Date:2008-11-10
* @modify data:2019-09-05 优化匹配方式,修复setIsXXX的错误
* @modify data:2020-06-23 优化convertType(Object, String) 方法
* @modify data:2020-07-08 修复convertType(Object, String) 转Long类型时精度丢失问题
* @modify data:2021-03-12 支持property中含下划线跟对象方法进行匹配
* @modify data:2022-10-19
* convertType类型匹配改成int类型的匹配,通过DataType将TypeName转化为int,批量时效率大幅提升
* @modify data:2023-08-06 增加对枚举类型的处理
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class BeanUtil {
/**
* 定义日志
*/
protected final static Logger logger = LoggerFactory.getLogger(BeanUtil.class);
public final static Pattern ARRAY_PATTERN = Pattern.compile("\\[\\d+\\]$");
/**
* 保存set方法
*/
private static ConcurrentHashMap setMethods = new ConcurrentHashMap();
/**
* 保存get方法
*/
private static ConcurrentHashMap getMethods = new ConcurrentHashMap();
// 保存pojo的级联关系
private static ConcurrentHashMap cascadeModels = new ConcurrentHashMap();
private static ConcurrentHashMap enumGetKeyMethods = new ConcurrentHashMap();
private static ConcurrentHashMap enumGetKeyExists = new ConcurrentHashMap();
private static ConcurrentHashMap enumClassMap = new ConcurrentHashMap();
// 枚举类型取key值的常用方法名称,枚举类中用getValue、getKey、getId等作为取值的都可自动完成映射
private static String[] enumKeys = { "value", "key", "code", "id", "status", "level", "type" };
// 静态方法避免实例化和继承
private BeanUtil() {
}
/**
* @TODO 通过value\key\code\id 常规逐个排查方式得到获取key的方法
* @param enumValue
* @return
*/
public static Object getEnumValue(Object enumValue) {
if (enumValue == null) {
return null;
}
Object result = null;
Class enumClass = enumValue.getClass();
Method getKeyMethod;
// Map缓存,不会每次都循环
if (enumGetKeyExists.containsKey(enumClass)) {
getKeyMethod = enumGetKeyMethods.get(enumClass);
if (getKeyMethod != null) {
try {
result = getKeyMethod.invoke(enumValue);
} catch (Exception e) {
}
}
} else {
getKeyMethod = matchEnumKeyMethod(enumClass, enumKeys);
if (getKeyMethod != null) {
try {
result = getKeyMethod.invoke(enumValue);
} catch (Exception e) {
}
enumGetKeyMethods.put(enumClass, getKeyMethod);
}
enumGetKeyExists.put(enumClass, 1);
}
if (result == null) {
return enumValue.toString();
}
return result;
}
/**
* @TODO 实例化枚举类型
* @param key
* @param enumClass
* @return
*/
public static Object newEnumInstance(Object key, Class enumClass) {
if (key == null) {
return null;
}
Method getKeyMethod = null;
if (enumGetKeyExists.containsKey(enumClass)) {
getKeyMethod = enumGetKeyMethods.get(enumClass);
} else {
getKeyMethod = matchEnumKeyMethod(enumClass, enumKeys);
if (getKeyMethod != null) {
enumGetKeyMethods.put(enumClass, getKeyMethod);
}
enumGetKeyExists.put(enumClass, 1);
}
if (getKeyMethod == null) {
return null;
}
Object[] enums = enumClass.getEnumConstants();
try {
for (Object enumVal : enums) {
if (key.equals(getKeyMethod.invoke(enumVal))) {
return enumVal;
}
}
} catch (Exception e) {
}
return null;
}
/**
* @TODO 找到枚举类型中获取key的方法
* @param enumClass
* @param props
* @return
*/
private static Method matchEnumKeyMethod(Class enumClass, String... props) {
Method[] methods = enumClass.getMethods();
List realMeth = new ArrayList();
// 有返回值且无参数方法
for (Method mt : methods) {
if (!void.class.equals(mt.getReturnType()) && mt.getParameterTypes().length == 0) {
realMeth.add(mt);
}
}
String prop;
String name;
for (int i = 0; i < props.length; i++) {
prop = props[i].toLowerCase();
for (Method getKeyMethod : realMeth) {
name = getKeyMethod.getName().toLowerCase();
if ("get".concat(prop).equals(name) || prop.equals(name)) {
return getKeyMethod;
}
}
}
return null;
}
/**
*
*
update 2019-09-05 优化匹配方式,修复setIsXXX的错误
* update 2020-04-09 支持setXXX()并返回对象本身,适配链式操作
* update 2021-03-12 支持property中含下划线跟对象属性进行匹配
*
*
* @todo 获取指定名称的方法集
* @param voClass
* @param props
* @return
*/
public static Method[] matchSetMethods(Class voClass, String... props) {
int indexSize = props.length;
Method[] result = new Method[indexSize];
Method[] methods = voClass.getMethods();
// 先过滤出全是set且只有一个参数的方法
List realMeth = new ArrayList();
for (Method mt : methods) {
// 剔除void 判断条件,存在: this setxxxx(){this.xxx=xxx;return this;}场景
// if (mt.getParameterTypes().length == 1 &&
// void.class.equals(mt.getReturnType())) {
if (mt.getParameterTypes().length == 1) {
if (mt.getName().startsWith("set")) {
realMeth.add(mt);
}
}
}
if (realMeth.isEmpty()) {
return result;
}
Method method;
String prop;
boolean matched = false;
String name;
Class type;
String minProp;
Method underlinMethod;
int meter = 0;
boolean isBool;
int index;
for (int i = 0; i < indexSize; i++) {
if (props[i] != null) {
prop = "set".concat(props[i].toLowerCase());
matched = false;
// 将属性名称剔除下划线
minProp = null;
if (prop.contains("_")) {
minProp = prop.replace("_", "");
}
meter = 0;
underlinMethod = null;
index = 0;
for (int j = 0; j < realMeth.size(); j++) {
isBool = false;
method = realMeth.get(j);
name = method.getName().toLowerCase();
// setXXX完全匹配(优先匹配不做下划线替换的场景)
if (prop.equals(name)) {
matched = true;
} else {
// boolean 类型参数
type = method.getParameterTypes()[0];
isBool = (type.equals(Boolean.class) || type.equals(boolean.class)) && prop.startsWith("setis");
if (isBool && prop.replaceFirst("setis", "set").equals(name)) {
matched = true;
}
}
// 匹配去除下划线的场景
if (!matched && minProp != null) {
if (minProp.equals(name) || (isBool && minProp.replaceFirst("setis", "set").equals(name))) {
meter++;
underlinMethod = method;
index = j;
}
}
if (matched) {
result[i] = method;
result[i].setAccessible(true);
realMeth.remove(j);
break;
}
}
// 属性剔除下划线后存在唯一匹配
if (!matched && meter == 1) {
result[i] = underlinMethod;
result[i].setAccessible(true);
realMeth.remove(index);
}
if (realMeth.isEmpty()) {
break;
}
}
}
return result;
}
/**
* @todo 获取指定名称的方法集,不区分大小写
* @param voClass
* @param props
* @return
*/
public static Method[] matchGetMethods(Class voClass, String... props) {
Method[] methods = voClass.getMethods();
List realMeth = new ArrayList();
String name;
// 过滤get 和is 开头的方法
for (Method mt : methods) {
if (!void.class.equals(mt.getReturnType()) && mt.getParameterTypes().length == 0) {
name = mt.getName().toLowerCase();
if (name.startsWith("get") || name.startsWith("is")) {
realMeth.add(mt);
}
}
}
int indexSize = props.length;
Method[] result = new Method[indexSize];
if (realMeth.isEmpty()) {
return result;
}
String prop;
Method method;
boolean matched = false;
Class type;
String minProp;
Method underlinMethod;
int meter = 0;
boolean isBool;
int index;
for (int i = 0; i < indexSize; i++) {
if (props[i] != null) {
prop = props[i].toLowerCase();
matched = false;
// 将属性名称剔除下划线
minProp = null;
if (prop.contains("_")) {
minProp = prop.replace("_", "");
}
meter = 0;
underlinMethod = null;
index = 0;
for (int j = 0; j < realMeth.size(); j++) {
isBool = false;
method = realMeth.get(j);
name = method.getName().toLowerCase();
// get完全匹配
if (name.equals("get".concat(prop))) {
matched = true;
} else {
// boolean型 is开头的方法
type = method.getReturnType();
isBool = name.startsWith("is") && (type.equals(Boolean.class) || type.equals(boolean.class));
if (isBool && (name.equals(prop) || name.equals("is".concat(prop)))) {
matched = true;
}
}
// 匹配属性含下划线场景
if (!matched && minProp != null) {
if (name.equals("get".concat(minProp))
|| (isBool && (name.equals(minProp) || name.equals("is".concat(minProp))))) {
meter++;
underlinMethod = method;
index = j;
}
}
if (matched) {
result[i] = method;
result[i].setAccessible(true);
realMeth.remove(j);
break;
}
}
// 属性剔除下划线后存在唯一匹配
if (!matched && meter == 1) {
result[i] = underlinMethod;
result[i].setAccessible(true);
realMeth.remove(index);
}
if (realMeth.isEmpty()) {
break;
}
}
}
return result;
}
/**
* @todo 获取指定名称的方法集,不区分大小写
* @param voClass
* @param properties
* @return
*/
public static Integer[] matchMethodsType(Class voClass, String... properties) {
if (properties == null || properties.length == 0) {
return null;
}
int indexSize = properties.length;
Method[] methods = voClass.getMethods();
Integer[] fieldsType = new Integer[indexSize];
String methodName;
String typeName;
int methodCnt = methods.length;
String property;
Method method;
for (int i = 0; i < indexSize; i++) {
fieldsType[i] = java.sql.Types.NULL;
property = properties[i].toLowerCase();
for (int j = 0; j < methodCnt; j++) {
method = methods[j];
methodName = method.getName().toLowerCase();
// update 2012-10-25 from equals to ignoreCase
if (!void.class.equals(method.getReturnType()) && method.getParameterTypes().length == 0
&& (methodName.equals("get".concat(property)) || methodName.equals("is".concat(property))
|| (methodName.startsWith("is") && methodName.equals(property)))) {
typeName = method.getReturnType().getSimpleName().toLowerCase();
if ("string".equals(typeName)) {
fieldsType[i] = java.sql.Types.VARCHAR;
} else if ("integer".equals(typeName)) {
fieldsType[i] = java.sql.Types.INTEGER;
} else if ("bigdecimal".equals(typeName)) {
fieldsType[i] = java.sql.Types.DECIMAL;
} else if ("date".equals(typeName)) {
fieldsType[i] = java.sql.Types.DATE;
} else if ("timestamp".equals(typeName)) {
fieldsType[i] = java.sql.Types.TIMESTAMP;
} else if ("int".equals(typeName)) {
fieldsType[i] = java.sql.Types.INTEGER;
} else if ("long".equals(typeName)) {
fieldsType[i] = java.sql.Types.NUMERIC;
} else if ("double".equals(typeName)) {
fieldsType[i] = java.sql.Types.DOUBLE;
} else if ("clob".equals(typeName)) {
fieldsType[i] = java.sql.Types.CLOB;
} else if ("biginteger".equals(typeName)) {
fieldsType[i] = java.sql.Types.BIGINT;
} else if ("blob".equals(typeName)) {
fieldsType[i] = java.sql.Types.BLOB;
} else if ("byte[]".equals(typeName)) {
fieldsType[i] = java.sql.Types.BINARY;
} else if ("boolean".equals(typeName)) {
fieldsType[i] = java.sql.Types.BOOLEAN;
} else if ("char".equals(typeName)) {
fieldsType[i] = java.sql.Types.CHAR;
} else if ("number".equals(typeName)) {
fieldsType[i] = java.sql.Types.NUMERIC;
} else if ("short".equals(typeName)) {
fieldsType[i] = java.sql.Types.NUMERIC;
} else if ("float".equals(typeName)) {
fieldsType[i] = java.sql.Types.FLOAT;
} else if ("datetime".equals(typeName)) {
fieldsType[i] = java.sql.Types.DATE;
} else if ("time".equals(typeName)) {
fieldsType[i] = java.sql.Types.TIME;
} else if ("byte".equals(typeName)) {
fieldsType[i] = java.sql.Types.TINYINT;
} else if (typeName.endsWith("[]")) {
fieldsType[i] = java.sql.Types.ARRAY;
} else {
fieldsType[i] = java.sql.Types.NULL;
}
break;
}
}
}
return fieldsType;
}
/**
* @todo 类的方法调用
* @param bean
* @param methodName
* @param args
* @return
* @throws Exception
*/
public static Object invokeMethod(Object bean, String methodName, Object... args) throws Exception {
try {
Method method = getMethod(bean.getClass(), methodName, args == null ? 0 : args.length);
if (method == null) {
return null;
}
return method.invoke(bean, args);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* @todo 对象比较
* @param target
* @param compared
* @return
*/
public static boolean equals(Object target, Object compared) {
if (null == target) {
return target == compared;
}
return target.equals(compared);
}
/**
* @todo 用于不同类型数据之间进行比较,判断是否相等,当类型不一致时统一用String类型比较
* @param target
* @param compared
* @param ignoreCase
* @return
*/
public static boolean equalsIgnoreType(Object target, Object compared, boolean ignoreCase) {
if (target == null || compared == null) {
return target == compared;
}
if (target.getClass().equals(compared.getClass()) && !(target instanceof CharSequence)) {
return target.equals(compared);
}
if (ignoreCase) {
return target.toString().equalsIgnoreCase(compared.toString());
}
return target.toString().equals(compared.toString());
}
/**
* @TODO 比较两个对象的大小
* @param target
* @param compared
* @return
*/
public static int compare(Object target, Object compared) {
if (null == target && null == compared) {
return 0;
}
if (null == target) {
return -1;
}
if (null == compared) {
return 1;
}
// 直接相等
if (target.equals(compared)) {
return 0;
}
// 日期类型
if ((target instanceof Date || target instanceof LocalDate || target instanceof LocalTime
|| target instanceof LocalDateTime)
|| (compared instanceof Date || compared instanceof LocalDate || compared instanceof LocalTime
|| compared instanceof LocalDateTime)) {
return DateUtil.convertDateObject(target).compareTo(DateUtil.convertDateObject(compared));
} // 数字
else if ((target instanceof Number) || (compared instanceof Number)) {
return new BigDecimal(target.toString()).compareTo(new BigDecimal(compared.toString()));
} else {
return target.toString().compareTo(compared.toString());
}
}
/**
* @TODO 提供对象get/set 类型转换
* @param value
* @param typeValue DataType.getType(typeName) 注意typeName不用转小写
* @param typeName getParameterTypes()[0].getTypeName() 没有转大小写
* @return
* @throws Exception
*/
public static Object convertType(Object value, int typeValue, String typeName) throws Exception {
return convertType(null, value, typeValue, typeName, null);
}
/**
* @todo 类型转换 2022-10-18 已经完成了优化,减少了不必要的判断
* @param typeHandler
* @param value
* @param typeValue
* @param typeName getTypeName()没有转大小写
* @param genericType 泛型类型
* @return
* @throws Exception
*/
public static Object convertType(TypeHandler typeHandler, Object value, int typeValue, String typeName,
Class genericType) throws Exception {
Object paramValue = value;
// 1
if (paramValue == null) {
// 1~5 原生数字类型
if (typeValue >= DataType.primitiveIntType && typeValue <= DataType.primitiveDoubleType) {
return 0;
}
if (DataType.primitiveBooleanType == typeValue) {
return false;
}
if (DataType.primitiveCharType == typeValue) {
return " ".charAt(0);
}
if (DataType.primitiveByteType == typeValue) {
return Byte.valueOf("0").byteValue();
}
return null;
}
// 2 value值的类型跟目标类型一致,直接返回
if (value.getClass().getTypeName().equals(typeName)) {
return value;
}
// 3 针对非常规类型转换,将jdbc获取的字段结果转为java对象属性对应的类型
if (typeHandler != null) {
Object result = typeHandler.toJavaType(typeName, genericType, paramValue);
if (result != null) {
return result;
}
}
// 4 非数组类型,但传递的参数值是数组类型且长度为1提取出数组中的单一值
if (paramValue.getClass().isArray() && typeValue < DataType.aryCharType) {
if (typeValue == DataType.stringType && (paramValue instanceof byte[])) {
paramValue = new String((byte[]) paramValue);
} else if (typeValue == DataType.stringType && (paramValue instanceof char[])) {
paramValue = new String((char[]) paramValue);
} else {
Object[] paramAry = CollectionUtil.convertArray(paramValue);
if (paramAry.length > 1) {
throw new DataAccessException("不能将长度大于1,类型为:" + paramValue.getClass().getTypeName() + " 的数组转化为:"
+ typeName + " 类型的值,请检查!");
}
paramValue = paramAry[0];
if (paramValue == null) {
return null;
}
}
}
// 5 字符串第一优先
if (DataType.stringType == typeValue) {
if (paramValue instanceof java.sql.Clob) {
java.sql.Clob clob = (java.sql.Clob) paramValue;
return clob.getSubString((long) 1, (int) clob.length());
} else if (paramValue instanceof LocalDate) {
return DateUtil.formatDate(paramValue, "yyyy-MM-dd");
} else if (paramValue instanceof LocalTime) {
return DateUtil.formatDate(paramValue, "HH:mm:ss");
} else if (paramValue instanceof java.util.Date) {
return DateUtil.formatDate(paramValue, "yyyy-MM-dd HH:mm:ss");
} else if (paramValue instanceof Enum) {
return getEnumValue(paramValue).toString();
}
return paramValue.toString();
}
// 6 bigDecimal第二优先
if (DataType.wrapBigDecimalType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return null;
}
return new BigDecimal(convertBoolean(valueStr));
}
// 7 Integer第三
if (DataType.wrapIntegerType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return null;
}
return Integer.valueOf(convertBoolean(valueStr).split("\\.")[0]);
}
// 8 第四优先
if (DataType.localDateTimeType == typeValue) {
if (paramValue instanceof LocalDateTime) {
return (LocalDateTime) paramValue;
}
// 修复oracle.sql.timestamp 转localdatetime的缺陷
if ("oracle.sql.TIMESTAMP".equals(paramValue.getClass().getTypeName())) {
return oracleTimeStampConvert(paramValue).toLocalDateTime();
}
return DateUtil.asLocalDateTime(DateUtil.convertDateObject(paramValue));
}
// 9 第五
if (DataType.localDateType == typeValue) {
if (paramValue instanceof LocalDate) {
return (LocalDate) paramValue;
}
if ("oracle.sql.TIMESTAMP".equals(paramValue.getClass().getTypeName())) {
return DateUtil.asLocalDate(oracleDateConvert(paramValue));
}
return DateUtil.asLocalDate(DateUtil.convertDateObject(paramValue));
}
// 10 第六
if (DataType.timestampType == typeValue) {
if (paramValue instanceof java.sql.Timestamp) {
return (java.sql.Timestamp) paramValue;
}
if (paramValue instanceof java.util.Date) {
return new Timestamp(((java.util.Date) paramValue).getTime());
}
if ("oracle.sql.TIMESTAMP".equals(paramValue.getClass().getTypeName())) {
return oracleTimeStampConvert(paramValue);
}
String valueStr = paramValue.toString();
if ("".equals(valueStr.trim())) {
return null;
}
return new Timestamp(DateUtil.parseString(valueStr).getTime());
}
// 11 第7
if (DataType.wrapLongType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return null;
}
// 考虑数据库中存在默认值为0.00 的问题,导致new Long() 报错,因为精度而不用Double.parse(原生long则可以)
return Long.valueOf(convertBoolean(valueStr).split("\\.")[0]);
}
// 12 第8
if (DataType.primitiveIntType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return 0;
}
// 防止小数而不使用Integer.parseInt
return Double.valueOf(convertBoolean(valueStr)).intValue();
}
// 13 第9 字符串转 boolean 型
if (DataType.wrapBooleanType == typeValue) {
String valueStr = paramValue.toString();
if ("true".equals(valueStr.toLowerCase()) || "1".equals(valueStr)) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
// 14 第10 字符串转 boolean 型
if (DataType.primitiveBooleanType == typeValue) {
String valueStr = paramValue.toString();
if ("true".equals(valueStr.toLowerCase()) || "1".equals(valueStr)) {
return true;
}
return false;
}
// 15 第11
if (DataType.dateType == typeValue) {
if (paramValue instanceof java.util.Date) {
return (java.util.Date) paramValue;
}
if (paramValue instanceof Number) {
return new java.util.Date(((Number) paramValue).longValue());
}
if ("oracle.sql.TIMESTAMP".equals(paramValue.getClass().getTypeName())) {
return oracleDateConvert(paramValue);
}
return DateUtil.parseString(paramValue.toString());
}
// 16 第12
if (DataType.wrapBigIntegerType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return null;
}
return new BigInteger(convertBoolean(valueStr).split("\\.")[0]);
}
// 17 第13
if (DataType.wrapDoubleType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return null;
}
return Double.valueOf(convertBoolean(valueStr));
}
// 18 第13
if (DataType.localTimeType == typeValue) {
if (paramValue instanceof LocalTime) {
return (LocalTime) paramValue;
}
if ("oracle.sql.TIMESTAMP".equals(paramValue.getClass().getTypeName())) {
return DateUtil.asLocalTime(oracleTimeStampConvert(paramValue));
}
return DateUtil.asLocalTime(DateUtil.convertDateObject(paramValue));
}
// 19
if (DataType.primitiveLongType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return 0;
}
// 防止小数而不使用Long.parseLong
return Double.valueOf(convertBoolean(valueStr)).longValue();
}
// 20
if (DataType.primitiveDoubleType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return 0;
}
return Double.parseDouble(convertBoolean(valueStr));
}
// 21 byte数组
if (DataType.aryByteType == typeValue) {
if (paramValue instanceof byte[]) {
return (byte[]) paramValue;
}
// blob类型处理
if (paramValue instanceof java.sql.Blob) {
java.sql.Blob blob = (java.sql.Blob) paramValue;
return blob.getBytes(1, (int) blob.length());
}
return paramValue.toString().getBytes();
}
// 22
if (DataType.wrapFloatType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return null;
}
return Float.valueOf(convertBoolean(valueStr));
}
// 23
if (DataType.primitiveFloatType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return 0;
}
return Float.parseFloat(convertBoolean(valueStr));
}
// 24
if (DataType.wrapShortType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return null;
}
return Short.valueOf(Double.valueOf(convertBoolean(valueStr)).shortValue());
}
// 25
if (DataType.primitiveShortType == typeValue) {
String valueStr = enumToString(paramValue);
if ("".equals(valueStr.trim())) {
return 0;
}
return Double.valueOf(convertBoolean(valueStr)).shortValue();
}
// 26
if (DataType.sqlDateType == typeValue) {
if (paramValue instanceof java.sql.Date) {
return (java.sql.Date) paramValue;
}
if (paramValue instanceof java.util.Date) {
return new java.sql.Date(((java.util.Date) paramValue).getTime());
}
if ("oracle.sql.TIMESTAMP".equals(paramValue.getClass().getTypeName())) {
return new java.sql.Date(oracleDateConvert(paramValue).getTime());
}
String valueStr = paramValue.toString();
if ("".equals(valueStr.trim())) {
return null;
}
return new java.sql.Date(DateUtil.parseString(valueStr).getTime());
}
// 27 clob 类型比较特殊,对外转类型全部转为字符串
if (DataType.clobType == typeValue) {
// update 2020-6-23 增加兼容性判断
if (paramValue instanceof String) {
return paramValue.toString();
}
java.sql.Clob clob = (java.sql.Clob) paramValue;
BufferedReader in = new BufferedReader(clob.getCharacterStream());
StringWriter out = new StringWriter();
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
return out.toString();
}
// 28
if (DataType.sqlTimeType == typeValue) {
if (paramValue instanceof java.sql.Time) {
return (java.sql.Time) paramValue;
}
if (paramValue instanceof java.util.Date) {
return new java.sql.Time(((java.util.Date) paramValue).getTime());
}
if ("oracle.sql.TIMESTAMP".equals(paramValue.getClass().getTypeName())) {
return new java.sql.Time(oracleDateConvert(paramValue).getTime());
}
return new java.sql.Time(DateUtil.parseString(paramValue.toString()).getTime());
}
// 29
if (DataType.primitiveByteType == typeValue) {
return Byte.valueOf(paramValue.toString()).byteValue();
}
// 30
if (DataType.primitiveCharType == typeValue) {
String valueStr = paramValue.toString();
if ("".equals(valueStr.trim())) {
return " ".charAt(0);
}
return valueStr.charAt(0);
}
// 31 字符数组
if (DataType.aryCharType == typeValue) {
if (paramValue instanceof char[]) {
return (char[]) paramValue;
}
if (paramValue instanceof java.sql.Clob) {
java.sql.Clob clob = (java.sql.Clob) paramValue;
BufferedReader in = new BufferedReader(clob.getCharacterStream());
StringWriter out = new StringWriter();
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
return out.toString().toCharArray();
}
return paramValue.toString().toCharArray();
}
// 32 update by 2020-4-13增加Byte类型的处理
if (DataType.wrapByteType == typeValue) {
return Byte.valueOf(paramValue.toString());
}
// update 2023-5-26 支持List 和Object[] 数组之间互转
// 33 数组类型
if (DataType.aryOtherType == typeValue) {
if ((paramValue instanceof Array)) {
return convertArray(((Array) paramValue).getArray(), typeName);
} else if ((paramValue instanceof Collection)) {
return convertArray(((Collection) paramValue).toArray(), typeName);
}
}
// 34 List类型
if (DataType.listType == typeValue) {
if (paramValue instanceof Array) {
Object[] tmp = (Object[]) ((Array) paramValue).getArray();
// 存在泛型,转换数组类型
if (genericType != null) {
return CollectionUtil.arrayToList(convertArray(tmp, genericType.getName().concat("[]")));
}
return CollectionUtil.arrayToList(tmp);
} else if (paramValue instanceof Object[]) {
// 存在泛型,转换数组类型
if (genericType != null) {
return CollectionUtil.arrayToList(convertArray(paramValue, genericType.getName().concat("[]")));
}
return CollectionUtil.arrayToList((Object[]) paramValue);
} else if (paramValue instanceof Set) {
Object[] tmp = ((Set) paramValue).toArray();
if (genericType != null) {
return CollectionUtil.arrayToList(convertArray(tmp, genericType.getName().concat("[]")));
}
return CollectionUtil.arrayToList(tmp);
}
}
// 35 Set类型
if (DataType.setType == typeValue) {
if (paramValue instanceof Array) {
Object[] tmp = (Object[]) ((Array) paramValue).getArray();
// 存在泛型,转换数组类型
if (genericType != null) {
return arrayToSet((Object[]) convertArray(tmp, genericType.getName().concat("[]")));
}
return arrayToSet(tmp);
} else if (paramValue instanceof Object[]) {
if (genericType != null) {
return arrayToSet((Object[]) convertArray(paramValue, genericType.getName().concat("[]")));
}
return arrayToSet((Object[]) paramValue);
} else if (paramValue instanceof Collection) {
Object[] tmp = ((Collection) paramValue).toArray();
// 存在泛型,转换数组类型
if (genericType != null) {
return arrayToSet((Object[]) convertArray(tmp, genericType.getName().concat("[]")));
}
return arrayToSet(tmp);
}
}
// 36 枚举类型
if (DataType.enumType == typeValue) {
Class enumClass = enumClassMap.get(typeName);
if (enumClass == null) {
enumClass = Class.forName(typeName);
enumClassMap.put(typeName, enumClass);
}
return newEnumInstance(paramValue, enumClass);
}
return paramValue;
}
/**
* 只处理非null值
*
* @param paramValue
* @return
*/
private static String enumToString(Object paramValue) {
if (paramValue instanceof Enum) {
// getEnumValue 逻辑也不会返回null
return getEnumValue(paramValue).toString();
}
return paramValue.toString();
}
private static HashSet arrayToSet(Object... values) {
HashSet result = new HashSet();
for (Object val : values) {
if (val != null) {
result.add(val);
}
}
return result;
}
public static String convertBoolean(String boolVar) {
if ("true".equals(boolVar)) {
return "1";
}
if ("false".equals(boolVar)) {
return "0";
}
return boolVar;
}
private static Timestamp oracleTimeStampConvert(Object obj) throws Exception {
return ((oracle.sql.TIMESTAMP) obj).timestampValue();
}
private static Date oracleDateConvert(Object obj) throws Exception {
return ((oracle.sql.TIMESTAMP) obj).dateValue();
}
/**
* @todo 利用java.lang.reflect并结合页面的property, 从对象中取出对应方法的值,组成一个List
* @param datas
* @param props
* @return
* @throws RuntimeException
*/
public static List reflectBeansToList(List datas, String... props) throws RuntimeException {
return reflectBeansToList(datas, props, null);
}
/**
* @TODO 切取单列值并以数组返回,服务于loadAll方法
* @param datas
* @param propertyName
* @return
* @throws RuntimeException
*/
public static Object[] sliceToArray(List datas, String propertyName) throws RuntimeException {
List sliceList = reflectBeansToList(datas, new String[] { propertyName }, null);
if (sliceList == null || sliceList.isEmpty()) {
return null;
}
List result = new ArrayList();
List row;
for (int i = 0; i < sliceList.size(); i++) {
row = (List) sliceList.get(i);
if (row != null && row.get(0) != null) {
result.add(row.get(0));
}
}
if (result.isEmpty()) {
return null;
}
Object[] ary = new Object[result.size()];
result.toArray(ary);
return ary;
}
/**
* @todo 利用java.lang.reflect并结合页面的property, 从对象中取出对应方法的值,组成一个List
* @param datas
* @param properties
* @param reflectPropsHandler
* @return
* @throws RuntimeException
*/
public static List reflectBeansToList(List datas, String[] properties, ReflectPropsHandler reflectPropsHandler)
throws RuntimeException {
if (null == datas || datas.isEmpty() || null == properties || properties.length < 1) {
return null;
}
List resultList = new ArrayList();
try {
Object rowObject = null;
int methodLength = properties.length;
// 判断是否存在属性值处理反调
boolean hasHandler = (reflectPropsHandler != null) ? true : false;
// 存在反调,则将对象的属性和属性所在的顺序放入hashMap中,便于后面反调中通过属性调用
if (hasHandler) {
HashMap propertyIndexMap = new HashMap();
for (int i = 0; i < methodLength; i++) {
propertyIndexMap.put(properties[i].toLowerCase(), i);
}
reflectPropsHandler.setPropertyIndexMap(propertyIndexMap);
}
// 判断是否有级联
boolean hasInnerClass = false;
for (String prop : properties) {
if (prop.contains(".")) {
hasInnerClass = true;
break;
}
}
// 级联含子对象模式(属性名称:staff.name 模式)
if (hasInnerClass) {
Object[] rowAry;
for (int i = 0, n = datas.size(); i < n; i++) {
rowObject = datas.get(i);
if (rowObject != null) {
List rowList = new ArrayList();
rowAry = reflectBeanToAry(rowObject, properties, null, reflectPropsHandler);
for (Object cell : rowAry) {
rowList.add(cell);
}
resultList.add(rowList);
}
}
return resultList;
}
// 非级联模式
Method[] realMethods = null;
boolean inited = false;
Object[] params = new Object[] {};
// 增加map类型支持
boolean isMap = false;
if (datas.get(0) != null && Map.class.isAssignableFrom(datas.get(0).getClass())) {
isMap = true;
}
Iterator iter;
String fieldLow;
Map.Entry entry;
Map rowMap;
for (int i = 0, n = datas.size(); i < n; i++) {
rowObject = datas.get(i);
if (null != rowObject) {
List dataList = new ArrayList();
// 2021-10-09 支持map类型
if (isMap) {
if (rowObject instanceof IgnoreKeyCaseMap) {
rowMap = (IgnoreKeyCaseMap) rowObject;
for (int j = 0; j < methodLength; j++) {
dataList.add(rowMap.get(properties[j]));
}
} else {
rowMap = (Map) rowObject;
// 考虑key大小写兼容
for (int j = 0; j < methodLength; j++) {
fieldLow = properties[j].toLowerCase();
iter = rowMap.entrySet().iterator();
while (iter.hasNext()) {
entry = (Map.Entry) iter.next();
if (entry.getKey().toLowerCase().equals(fieldLow)) {
dataList.add(entry.getValue());
break;
}
}
}
}
} else {
// 第一行数据
if (!inited) {
realMethods = matchGetMethods(rowObject.getClass(), properties);
inited = true;
}
for (int j = 0; j < methodLength; j++) {
if (realMethods[j] != null) {
dataList.add(realMethods[j].invoke(rowObject, params));
} else {
dataList.add(null);
}
}
}
// 反调对数据值进行加工处理
if (hasHandler) {
reflectPropsHandler.setRowIndex(i);
reflectPropsHandler.setRowList(dataList);
reflectPropsHandler.process();
resultList.add(reflectPropsHandler.getRowList());
} else {
resultList.add(dataList);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("BeanUtil.reflectBeansToList 方法,第:{}行数据为null,如果是sql查询请检查写法是否正确!", i);
} else {
err.println("BeanUtil.reflectBeansToList 方法,第:{" + i + "}行数据为null,如果是sql查询请检查写法是否正确!");
}
resultList.add(null);
}
}
} catch (Exception e) {
logger.error("反射Java Bean获取数据组装List集合异常!{}", e.getMessage());
e.printStackTrace();
throw new RuntimeException("反射Java Bean获取数据组装List集合异常!" + e.getMessage());
}
return resultList;
}
public static Object[] reflectBeanToAry(Object serializable, String... properties) {
return reflectBeanToAry(serializable, properties, null, null);
}
/**
* @todo 反射出单个对象中的属性并以对象数组返回
* @param serializable
* @param properties
* @param defaultValues
* @param reflectPropsHandler
* @return
*/
public static Object[] reflectBeanToAry(Object serializable, String[] properties, Object[] defaultValues,
ReflectPropsHandler reflectPropsHandler) {
if (null == serializable || null == properties || properties.length == 0) {
return null;
}
int methodLength = properties.length;
String[] realProps = new String[methodLength];
for (int i = 0; i < methodLength; i++) {
realProps[i] = properties[i].trim();
}
Object[] result = new Object[methodLength];
// 判断是否存在属性值处理反调
boolean hasHandler = (reflectPropsHandler != null) ? true : false;
// 存在反调,则将对象的属性和属性所在的顺序放入hashMap中,便于后面反调中通过属性调用
if (hasHandler && !reflectPropsHandler.initPropsIndexMap()) {
HashMap propertyIndexMap = new HashMap();
for (int i = 0; i < methodLength; i++) {
propertyIndexMap.put(realProps[i].toLowerCase(), i);
}
reflectPropsHandler.setPropertyIndexMap(propertyIndexMap);
}
String[] fields;
Iterator> iter;
Map.Entry entry;
boolean isMapped = false;
String fieldLow;
String realFieldLow;
Object fieldValue;
Object tmpValue;
String keyLowString;
boolean hasKey = false;
try {
KeyAndIndex keyAndIndex;
// 通过反射提取属性getMethod返回的数据值
for (int i = 0; i < methodLength; i++) {
if (realProps[i] != null) {
// 支持xxxx.xxx 子对象属性提取
fields = realProps[i].split("\\.");
fieldValue = serializable;
hasKey = false;
// map 类型且key本身就是xxxx.xxxx格式
if (fieldValue instanceof Map) {
iter = ((Map) fieldValue).entrySet().iterator();
fieldLow = realProps[i].toLowerCase();
while (iter.hasNext()) {
entry = (Map.Entry) iter.next();
if (entry.getKey().toLowerCase().equals(fieldLow)) {
fieldValue = entry.getValue();
hasKey = true;
break;
}
}
}
if (!hasKey) {
int index = 0;
int fieldLen = fields.length;
// a.b.c[index] 切割后逐级向下取值
for (String field : fields) {
// 支持map类型 update 2021-01-31
if (fieldValue instanceof Map) {
if (fieldValue instanceof IgnoreKeyCaseMap) {
keyAndIndex = getKeyAndIndex(field);
realFieldLow = (keyAndIndex == null) ? field : keyAndIndex.getKey();
tmpValue = ((IgnoreKeyCaseMap) fieldValue).get(realFieldLow);
// 当前层级取到值,则继续向下
if (tmpValue != null) {
if (keyAndIndex != null) {
fieldValue = getArrayIndexValue(tmpValue, keyAndIndex.getIndex());
} else {
fieldValue = tmpValue;
}
} else {
// 没有取到值终止继续逐级取值,则以当前层级到结尾,a.b.c[index]则以b.c[index]
// a.b.c[index] a.b.c直接是key模式进行尝试
if (keyAndIndex == null) {
fieldValue = getMaybeArrayValue((IgnoreKeyCaseMap) fieldValue,
wrapMapKey(fields, index));
} else {
fieldValue = null;
}
break;
}
} else {
iter = ((Map) fieldValue).entrySet().iterator();
isMapped = false;
fieldLow = field.toLowerCase();
keyAndIndex = getKeyAndIndex(fieldLow);
realFieldLow = (keyAndIndex == null) ? fieldLow : keyAndIndex.getKey();
while (iter.hasNext()) {
entry = (Map.Entry) iter.next();
keyLowString = entry.getKey().toLowerCase();
if (keyLowString.equals(realFieldLow)) {
if (keyAndIndex != null) {
fieldValue = getArrayIndexValue(entry.getValue(),
keyAndIndex.getIndex());
} else {
fieldValue = entry.getValue();
}
isMapped = true;
break;
}
}
// 未匹配到,做a.b.c[index],key直接是a.b.c尝试
if (!isMapped) {
if (keyAndIndex == null) {
fieldValue = getMaybeArrayValue((Map) fieldValue,
wrapMapKey(fields, index));
} else {
fieldValue = null;
}
break;
}
}
} // update 2022-5-25 支持将集合的属性直接映射成数组
else if (fieldValue instanceof List) {
List tmp = (List) fieldValue;
// a.b.c 在最后一个属性c之前的属性取值
if (index < fieldLen - 1) {
fieldValue = sliceToArray(tmp, field);
} else {
Object[] fieldValueAry = new Object[tmp.size()];
for (int j = 0; j < tmp.size(); j++) {
fieldValueAry[j] = getComplexProperty(tmp.get(j), field);
}
fieldValue = fieldValueAry;
}
} else if (fieldValue instanceof Object[]) {
Object[] tmp = (Object[]) fieldValue;
Object[] fieldValueAry = new Object[tmp.length];
for (int j = 0; j < tmp.length; j++) {
fieldValueAry[j] = getComplexProperty(tmp[j], field);
}
fieldValue = fieldValueAry;
} else {
fieldValue = getComplexProperty(fieldValue, field);
}
if (fieldValue == null) {
break;
}
index++;
}
}
result[i] = fieldValue;
}
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
// 默认值
if (defaultValues != null) {
int end = (defaultValues.length > methodLength) ? methodLength : defaultValues.length;
for (int i = 0; i < end; i++) {
if (result[i] == null) {
result[i] = defaultValues[i];
}
}
}
// 反调对数据值进行加工处理
if (hasHandler) {
reflectPropsHandler.setRowIndex(0);
reflectPropsHandler.setRowData(result);
reflectPropsHandler.process();
return reflectPropsHandler.getRowData();
}
return result;
}
private static String wrapMapKey(String[] names, int start) {
StringBuilder resultNameBuilder = new StringBuilder();
for (int i = start; i < names.length; i++) {
if (i > start) {
resultNameBuilder.append(".");
}
resultNameBuilder.append(names[i]);
}
return resultNameBuilder.toString();
}
/**
* @todo 利用java.lang.reflect并结合页面的property, 从对象中取出对应方法的值,组成一个List
* @param dataSet
* @param properties
* @param defaultValues
* @param reflectPropsHandler
* @return
*/
public static List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy