package com.common.core.utils;
|
|
import org.hibernate.Hibernate;
|
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.FatalBeanException;
|
import org.springframework.util.Assert;
|
import org.springframework.util.ReflectionUtils;
|
|
import javax.persistence.Column;
|
import javax.persistence.Id;
|
import javax.validation.constraints.NotNull;
|
import java.beans.PropertyDescriptor;
|
import java.io.PrintWriter;
|
import java.io.StringWriter;
|
import java.lang.annotation.Annotation;
|
import java.lang.reflect.Array;
|
import java.lang.reflect.Field;
|
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.Method;
|
import java.math.BigDecimal;
|
import java.math.BigInteger;
|
import java.util.UUID;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* Bean工具类.
|
*
|
* @author LuoGang
|
* @date 2019-04-13 16:53
|
*/
|
public class BeanHelper {
|
|
/**
|
* 分隔符号
|
*/
|
public static final char UNDERLINE = '_';
|
|
/**
|
* 符号.
|
*/
|
public static final String POINT = ".";
|
|
/**
|
* 系统的换行符
|
*/
|
public static final String LINE_SEPARATOR = System.getProperty("line.separator", "\n");
|
|
/**
|
* 根据class缓存其所有的PropertyDescriptor
|
*/
|
private static Map<Class<?>, PropertyDescriptor[]> propertyDescriptorsCache = new HashMap<>();
|
|
/**
|
* 得到cls定义的所有字段,不包含class
|
*
|
* @param cls Class
|
* @return cls下定义的字段
|
*/
|
public static PropertyDescriptor[] getPropertyDescriptors(Class<?> cls) {
|
PropertyDescriptor[] cache = propertyDescriptorsCache.get(cls);
|
if (cache == null) {
|
List<PropertyDescriptor> pds = new ArrayList<>();
|
PropertyDescriptor[] arr = BeanUtils.getPropertyDescriptors(cls);
|
for (PropertyDescriptor pd : arr) {
|
if ("class".equals(pd.getName())) {
|
// 不需要class这个属性
|
continue;
|
}
|
|
pds.add(pd);
|
}
|
|
cache = pds.toArray(new PropertyDescriptor[pds.size()]);
|
propertyDescriptorsCache.put(cls, cache);
|
}
|
|
return cache;
|
}
|
|
/**
|
* 得到obj对象定义的所有字段。注意obj可能是Hibernate的托管对象,要处理
|
*
|
* @param obj
|
* @return obj定义的字段
|
* @see {@link Hibernate#getClass(Object)}
|
*/
|
public static PropertyDescriptor[] getPropertyDescriptors(Object obj) {
|
Class<?> cls = Hibernate.getClass(obj);
|
return getPropertyDescriptors(cls);
|
}
|
|
/**
|
* 得到属性的类型,返回class name.
|
*
|
* @param entity 实体类
|
* @param propertyName 字段名
|
* @return
|
*/
|
public static final String getPropertyType(Object entity, String propertyName) {
|
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(Hibernate.getClass(entity), propertyName);
|
if (null != pd) {
|
return pd.getPropertyType().getName();
|
} else {
|
return null;
|
}
|
}
|
|
/**
|
* 得到属性的PropertyDescriptor
|
*
|
* @param entity 实体对象
|
* @param propertyName 字段名
|
* @return 字段的PropertyDescriptor对象
|
*/
|
public static final PropertyDescriptor getPropertyDescriptor(Object entity, String propertyName) {
|
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(Hibernate.getClass(entity), propertyName);
|
return pd;
|
}
|
|
/**
|
* 为对象entity设置value.
|
*
|
* @param entity 实体类
|
* @param propertyName 字段名
|
* @param value 值
|
*/
|
public static final void setPropertyValue(Object entity, String propertyName, Object value) {
|
if (propertyName.indexOf(POINT) > -1) {
|
String[] propertyNames = StringUtils.split(propertyName, '.');
|
for (int i = 0, l = propertyNames.length - 1; i < l; i++) {
|
entity = getPropertyValue(entity, propertyNames[i]);
|
if (entity == null) {
|
return;
|
}
|
}
|
propertyName = propertyNames[propertyNames.length - 1];
|
}
|
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(Hibernate.getClass(entity), propertyName);
|
if (pd != null) {
|
setPropertyValue(entity, pd, value);
|
}
|
}
|
|
public static final void setPropertyValue(Object entity, String propertyName, Object value,Class clazz) {
|
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, propertyName);
|
if (pd != null) {
|
setPropertyValue(entity, pd, value);
|
}
|
}
|
/**
|
* 为对象entity设置value.
|
*
|
* @param entity 实体类
|
* @param pd 要读取的属性PropertyDescriptord对象
|
* @param value 值
|
*/
|
public static final void setPropertyValue(@NotNull Object entity, @NotNull PropertyDescriptor pd, Object value) {
|
Method writeMethod = pd.getWriteMethod();
|
if (writeMethod != null) {
|
try {
|
value = BeanHelper.convert(value, pd.getPropertyType());
|
if (value == null || pd.getPropertyType().isAssignableFrom(value.getClass())) { // 必须是同样类型的才匹配,否则不处理
|
ReflectionUtils.invokeMethod(writeMethod, entity, value);
|
}
|
} catch (Exception e) {
|
throw new RuntimeException(entity.getClass() + POINT + pd.getName() + "写入值:" + value + "出现异常\n" + e.getMessage(), e);
|
}
|
}
|
}
|
|
/**
|
* 得到entity中propertyName属性的值.
|
*
|
* @param entity 实体对象
|
* @param propertyName 要读取的属性名
|
* @return 得到的值
|
*/
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
public static final <T> T getPropertyValue(Object entity, String propertyName) {
|
if (entity == null) {
|
return null;
|
}
|
if (entity instanceof Map) {
|
return (T) ((Map) entity).get(propertyName);
|
}
|
|
if (propertyName.indexOf(POINT) > 0) {
|
String[] propertyNames = StringUtils.split(propertyName, '.');
|
for (String name : propertyNames) {
|
entity = getPropertyValue(entity, name);
|
}
|
return (T) entity;
|
}
|
|
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(Hibernate.getClass(entity), propertyName);
|
if (pd == null) {
|
Field field = ReflectionUtils.findField(Hibernate.getClass(entity), propertyName);
|
if (field != null) {
|
Method setAccessible = ReflectionUtils.findMethod(field.getClass(), "setAccessible", Boolean.TYPE);
|
ReflectionUtils.invokeMethod(setAccessible, field, true);
|
return (T) ReflectionUtils.getField(field, entity);
|
}
|
}
|
return getPropertyValue(entity, pd);
|
}
|
|
/**
|
* 得到entity中PropertyDescriptor属性的值.
|
*
|
* @param entity 实体对象
|
* @param pd 要读取的属性PropertyDescriptord对象
|
* @return 得到的值
|
*/
|
@SuppressWarnings("unchecked")
|
public static final <T> T getPropertyValue(Object entity, PropertyDescriptor pd) {
|
if (entity == null || pd == null || pd.getReadMethod() == null) {
|
return null;
|
}
|
Method readMethod = pd.getReadMethod();
|
try {
|
// if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
// readMethod.setAccessible(true);
|
// }
|
// return (T) readMethod.invoke(entity);
|
return (T) ReflectionUtils.invokeMethod(readMethod, entity);
|
} catch (Exception e) {
|
throw new RuntimeException(e);
|
}
|
|
}
|
|
/**
|
* 得到组或Collection中下标index的值.
|
*
|
* @param array 数组或Collection
|
* @param index 下标,0开始
|
* @return 得到的值
|
*/
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
public static final <T> T getValue(Object array, int index) {
|
if (array == null || index < 0) {
|
return null;
|
}
|
|
if (array instanceof Collection) { // 集合
|
if (((Collection) array).size() <= index) { // 下标越界
|
return null;
|
}
|
|
if (array instanceof List) {
|
return (T) (((List) array).get(index));
|
}
|
|
Iterator it = ((Collection) array).iterator();
|
while (index-- > 0) {
|
it.next();
|
}
|
|
return (T) it.next();
|
}
|
|
if (array.getClass().isArray()) { // 数组
|
if (Array.getLength(array) <= index) { // 下标越界
|
return null;
|
}
|
return (T) Array.get(array, index);
|
}
|
return null;
|
}
|
|
/**
|
* 新建clazz对象,并复制source中的属性
|
*
|
* @param source
|
* @param clazz
|
* @return
|
*/
|
public static <T> T copyAs(Object source, Class<T> clazz) {
|
T target = BeanUtils.instantiateClass(clazz);
|
copy(source, target);
|
return target;
|
}
|
|
/**
|
* 复制一个链表,目标链表节点类型是指定的Class
|
*
|
* @param list 源数据
|
* @param clazz 目标链表节点类型
|
* @return
|
*/
|
public static <T> List<T> copyAs(Collection<?> list, Class<T> clazz) {
|
return list.stream().map(source -> copyAs(source, clazz)).collect(Collectors.toList());
|
}
|
|
/**
|
* 对给定的source对象初始化所有保留类型的字段默认值。其中数字默认为0,boolean默认为false.
|
*
|
* @param source 要处理的对象
|
* @param ignoreProperties 不需要处理的字段
|
*/
|
public static final <T> void initPrimitiveFields(T source, String... ignoreProperties) {
|
Class<?> cls = Hibernate.getClass(source);
|
PropertyDescriptor[] targetPds = getPropertyDescriptors(cls);
|
List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : Collections.emptyList();
|
Class<?> propertyClass;
|
for (PropertyDescriptor pd : targetPds) {
|
if (ignoreList.contains(pd.getName()) || pd.getWriteMethod() == null || getPropertyValue(source, pd) != null) {
|
continue;
|
}
|
propertyClass = pd.getPropertyType();
|
if (Boolean.class.equals(propertyClass) || Boolean.TYPE.equals(propertyClass)) {
|
// boolean类型默认为false
|
setPropertyValue(source, pd, false);
|
} else if (Number.class.isAssignableFrom(propertyClass)) {
|
// 数字类型默认为0
|
setPropertyValue(source, pd, 0);
|
}
|
}
|
}
|
|
/**
|
* 直接clone一个对象
|
*
|
* @param source 要复制的对象
|
* @param ignoreProperties 忽略的字段
|
* @return 复制的对象
|
*/
|
@SuppressWarnings("unchecked")
|
public static final <T> T copy(T source, String... ignoreProperties) {
|
Class<T> cls = Hibernate.getClass(source);
|
T obj = BeanUtils.instantiateClass(cls);
|
return BeanHelper.copy(source, obj, ignoreProperties);
|
}
|
|
/**
|
* 将source中所有不为null的值copy到target中.
|
* 与{@link BeanUtils#copyProperties(Object, Object, String...)}不同之处在于本方法不copy为null的属性
|
*
|
* @param source 要复制的源对象
|
* @param target 目标对象
|
* @param ignoreProperties 需要忽略的字段
|
* @return 返回target
|
* @see BeanUtils#copyProperties(Object, Object, String...)
|
*/
|
public static final <T> T copy(Object source, T target, String... ignoreProperties) {
|
return BeanHelper.copy(source, target, false, ignoreProperties);
|
}
|
|
/**
|
* 将source中所有不为null的Encrypt值copy到target中.(eg:copy soure.nameEncrypt to target.name)
|
* 与{@link BeanUtils#copyProperties(Object, Object, String...)}不同之处在于本方法不copy为null的属性
|
*
|
* @param source 要复制的源对象
|
* @param target 目标对象
|
* @param ignoreProperties 需要忽略的字段
|
* @return 返回target
|
* @see BeanUtils#copyProperties(Object, Object, String...)
|
*/
|
public static final <T> T copyEncrypt(Object source, T target, String... ignoreProperties) {
|
return BeanHelper.copyEncrypt(source, target, false,"Encrypt", ignoreProperties);
|
}
|
|
/**
|
* 将source中所有不为null的值copy到target中.
|
* 仅复制基础类型的数据,只对JAVA保留类型/数字/String/Date以及其数组的数据进行复制
|
* 与{@link BeanUtils#copyProperties(Object, Object, String...)}不同之处在于本方法不copy为null的属性
|
*
|
* @param source 要复制的源对象
|
* @param target 目标对象
|
* @param ignoreProperties 需要忽略的字段
|
* @return 返回target
|
* @see BeanUtils#copyProperties(Object, Object, String...)
|
*/
|
public static final <T> T copyBasic(Object source, T target, String... ignoreProperties) {
|
return BeanHelper.copy(source, target, true, ignoreProperties);
|
}
|
|
/**
|
* 判断指定的clazz是否为基础数据类型
|
*
|
* @param clazz
|
* @return
|
*/
|
public static boolean isBasicClass(Class<?> clazz) {
|
if (clazz.isArray()) {
|
clazz = clazz.getComponentType();
|
}
|
if ((clazz.isPrimitive()// JAVA的保留类型,boolean, byte, char, short, int, long, float, double.
|
|| Number.class.isAssignableFrom(clazz) // 数字
|
|| Boolean.class.isAssignableFrom(clazz) // Boolean
|
|| Character.class.isAssignableFrom(clazz) // Character
|
|| CharSequence.class.isAssignableFrom(clazz) // 字符串
|
|| Date.class.isAssignableFrom(clazz))// 日期
|
) {
|
return true;
|
}
|
return false;
|
}
|
|
/**
|
* 将source中所有不为null的值copy到target中.
|
* 与{@link BeanUtils#copyProperties(Object, Object, String...)}不同之处在于本方法不copy为null的属性
|
*
|
* @param source 要复制的源对象
|
* @param target 目标对象
|
* @param basicOnly 是否仅复制基础类型的数据,如果为true,则只对JAVA保留类型/数字/String/Date以及其数组的数据进行复制
|
* @param ignoreProperties 需要忽略的字段
|
* @return 返回target
|
* @see BeanUtils#copyProperties(Object, Object, String...)
|
*/
|
public static final <T> T copy(Object source, T target, boolean basicOnly, String... ignoreProperties) {
|
Assert.notNull(source, "Source must not be null");
|
Assert.notNull(target, "Target must not be null");
|
|
Class<?> cls = Hibernate.getClass(source);
|
Class<?> actualEditable = Hibernate.getClass(target);
|
|
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
|
List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;
|
|
for (PropertyDescriptor targetPd : targetPds) {
|
if (basicOnly) {
|
Class<?> propertyType = targetPd.getPropertyType();
|
if (propertyType.isArray()) {
|
propertyType = propertyType.getComponentType();
|
}
|
if (!isBasicClass(propertyType)) {
|
// 复杂对象不处理
|
continue;
|
}
|
}
|
|
Method writeMethod = targetPd.getWriteMethod();
|
if (writeMethod != null && (ignoreList == null || (!ignoreList.contains(targetPd.getName())))) {
|
PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(cls, targetPd.getName());
|
if (sourcePd != null) {
|
Method readMethod = sourcePd.getReadMethod();
|
if (readMethod != null) {// && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
|
try {
|
// if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
// readMethod.setAccessible(true);
|
// }
|
Object value = ReflectionUtils.invokeMethod(readMethod, source);
|
if (value == null) {
|
// 为null的值不处理
|
continue;
|
}
|
|
setPropertyValue(target, targetPd, value);
|
|
} catch (Throwable ex) {
|
throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", ex);
|
}
|
}
|
}
|
}
|
}
|
|
return target;
|
}
|
|
/**
|
* 将source中所有不为null的值copy到target中.
|
* 与{@link BeanUtils#copyProperties(Object, Object, String...)}不同之处在于本方法不copy为null的属性
|
*
|
* @param source 要复制的源对象
|
* @param target 目标对象
|
* @param basicOnly 是否仅复制基础类型的数据,如果为true,则只对JAVA保留类型/数字/String/Date以及其数组的数据进行复制
|
* @param suffix 要复制的字段添加后缀
|
* @param ignoreProperties 需要忽略的字段
|
* @return 返回target
|
* @see BeanUtils#copyProperties(Object, Object, String...)
|
*/
|
public static final <T> T copyEncrypt(Object source, T target, boolean basicOnly,String suffix, String... ignoreProperties) {
|
Assert.notNull(source, "Source must not be null");
|
Assert.notNull(target, "Target must not be null");
|
|
Class<?> cls = Hibernate.getClass(source);
|
Class<?> actualEditable = Hibernate.getClass(target);
|
|
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
|
List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;
|
|
for (PropertyDescriptor targetPd : targetPds) {
|
if (basicOnly) {
|
Class<?> propertyType = targetPd.getPropertyType();
|
if (propertyType.isArray()) {
|
propertyType = propertyType.getComponentType();
|
}
|
if (!isBasicClass(propertyType)) {
|
// 复杂对象不处理
|
continue;
|
}
|
}
|
|
Method writeMethod = targetPd.getWriteMethod();
|
if (writeMethod != null && (ignoreList == null || (!ignoreList.contains(targetPd.getName())))) {
|
PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(cls, targetPd.getName()+suffix);
|
if (sourcePd != null) {
|
Method readMethod = sourcePd.getReadMethod();
|
if (readMethod != null) {// && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
|
try {
|
// if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
// readMethod.setAccessible(true);
|
// }
|
Object value = ReflectionUtils.invokeMethod(readMethod, source);
|
if (value == null) {
|
// 为null的值不处理
|
continue;
|
}
|
|
setPropertyValue(target, targetPd, value);
|
|
} catch (Throwable ex) {
|
throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", ex);
|
}
|
}
|
}
|
}
|
}
|
|
return target;
|
}
|
|
/**
|
* 生成32位的uuid.没有短横线"-".
|
*
|
* @return 没有短横线的UUID
|
* @see UUID#randomUUID()
|
*/
|
public static final String uuid() {
|
return UUID.randomUUID().toString().replace("-", "");
|
}
|
|
/**
|
* 判断a是否和b相等.
|
* 如果均是空白字符,视为相等; null和空白字符视为相等; 如果a,b均为字符串,区分大小写.忽略字符串前后的空格
|
*
|
* @param a
|
* @param b
|
* @return a是否等于b
|
*/
|
public static boolean equals(Object a, Object b) {
|
if (Objects.equals(a, b)) {
|
return true;
|
}
|
if (a == null) {
|
return b instanceof String && StringUtils.isBlank((String) b);
|
}
|
if (b == null) {
|
return a instanceof String && StringUtils.isBlank((String) a);
|
}
|
|
if (a instanceof String && b instanceof String) {
|
// 两个均为字符串
|
if (StringUtils.isBlank((String) a) && StringUtils.isBlank((String) b)) {
|
return true;
|
}
|
if (((String) a).trim().equals(((String) b).trim())) {
|
return true;
|
}
|
}
|
if (a instanceof Date && b instanceof Date) {
|
return ((Date) a).getTime() == ((Date) b).getTime();
|
}
|
|
if (a instanceof Number && b instanceof Number) {
|
return new BigDecimal(a.toString()).equals(new BigDecimal(b.toString()));
|
}
|
|
if (a.getClass().equals(b.getClass())) {
|
PropertyDescriptor[] pds = getPropertyDescriptors(a.getClass());
|
for (PropertyDescriptor pd : pds) {
|
if (!equals(getPropertyValue(a, pd), getPropertyValue(b, pd))) {
|
return false;
|
}
|
}
|
return true;
|
}
|
|
return false;
|
}
|
|
/**
|
* 判断a是否和b相等.忽略字符串前后的空格
|
* 如果均是空白字符,视为相等; null和空白字符视为相等; 如果a,b均为字符串,不区分大小写.
|
*
|
* @param a
|
* @param b
|
* @return a是否等于b
|
*/
|
public static boolean equalsIgnoreCase(Object a, Object b) {
|
if (a instanceof String && b instanceof String) { // 两个均为字符串
|
if (StringUtils.isBlank((String) a) && StringUtils.isBlank((String) b)) {
|
return true;
|
}
|
if (((String) a).trim().equalsIgnoreCase(((String) b).trim())) {
|
return true;
|
}
|
} else {
|
return equals(a, b);
|
}
|
|
return false;
|
}
|
|
/**
|
* 比较数组是否相同,如果是字符串,忽略大小写和前后的空格
|
*
|
* @param a
|
* @param b
|
* @return
|
*/
|
public static boolean equalsIgnoreCase(Object[] a, Object[] b) {
|
if (a == b) {
|
return true;
|
}
|
if (a == null || b == null) {
|
return false;
|
}
|
|
int length = a.length;
|
if (b.length != length) {
|
return false;
|
}
|
|
for (int i = 0; i < length; i++) {
|
if (!equalsIgnoreCase(a[i], b[i])) {
|
return false;
|
}
|
}
|
|
return true;
|
}
|
|
/**
|
* 比较数组的前length个数据是否相同,如果是字符串,忽略大小写和前后的空格
|
*
|
* @param a
|
* @param b
|
* @return
|
*/
|
public static boolean equalsIgnoreCase(Object[] a, Object[] b, int length) {
|
if (a.length > length) {
|
a = ArrayUtils.subarray(a, 0, length);
|
}
|
if (b.length > length) {
|
b = ArrayUtils.subarray(b, 0, length);
|
}
|
return equalsIgnoreCase(a, b);
|
}
|
|
/**
|
* 输出异常的堆栈信息.
|
*
|
* @param e 异常信息
|
* @return
|
*/
|
public static String toString(Throwable e) {
|
StringWriter w = new StringWriter();
|
PrintWriter pw = new PrintWriter(w);
|
e.printStackTrace(pw);
|
return w.toString();
|
}
|
|
/**
|
* 将列名转换为按驼峰命名的属性名.
|
*
|
* @param columnName 列名
|
* @return JAVA驼峰命名规范的属性名
|
*/
|
public static String columnToProperty(String columnName) {
|
char[] chars = columnName.toLowerCase().toCharArray();
|
StringBuilder buf = new StringBuilder();
|
boolean flag = false;
|
for (int i = 0, l = chars.length; i < l; i++) {
|
char c = chars[i];
|
if (c == '_' || c == '-' || c == ' ') { // 下一个单词大写
|
flag = buf.length() > 0;
|
} else {
|
buf.append(flag ? Character.toUpperCase(c) : c);
|
flag = false;
|
}
|
}
|
return buf.toString();
|
}
|
|
/**
|
* java字段名转换为列名.单词之间用下划线_隔开.
|
*
|
* @param propertyName 属性名
|
* @return 转换后的列名
|
*/
|
public static String propertyToColumn(String propertyName) {
|
char[] chars = propertyName.toCharArray();
|
StringBuilder buf = new StringBuilder();
|
for (int i = 0, l = chars.length; i < l; i++) {
|
char c = chars[i];
|
if (Character.isUpperCase(c)) {
|
// 单词大写
|
if (buf.length() > 0) {
|
buf.append('_');
|
}
|
}
|
buf.append(c);
|
}
|
return buf.toString().toLowerCase();
|
}
|
|
/**
|
* 得到pd属性的列名.
|
*
|
* @param pd 要得到列名的属性
|
* @return 列名
|
*/
|
public static String getColumnName(PropertyDescriptor pd) {
|
Column column = pd.getReadMethod() == null ? null : pd.getReadMethod().getAnnotation(Column.class);
|
if (column == null && pd.getWriteMethod() != null) {
|
// getter方法没有@Column注解,通过setter方法读取
|
column = pd.getWriteMethod().getAnnotation(Column.class);
|
}
|
|
if (column != null && !column.name().isEmpty()) {
|
return column.name();
|
}
|
return propertyToColumn(pd.getName());
|
}
|
|
/**
|
* 将Map中的数据读取到到实体对象中.
|
*
|
* @param data Map数据.
|
* @param entity 实体对象.
|
* @return 参数entity本身.
|
*/
|
public static void readValue(Map<?, ?> data, Object entity) {
|
data.entrySet().forEach(entry -> {
|
String key = entry.getKey().toString();
|
Object value = entry.getValue();
|
if (!key.contains(String.valueOf(UNDERLINE))) {
|
Class<?> clazz = Hibernate.getClass(entity);
|
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, key);
|
if (pd != null) {
|
setPropertyValue(entity, pd, value);
|
return;
|
}
|
}
|
setPropertyValueByColumn(entity, key, value);
|
});
|
}
|
|
/**
|
* 将实体转换为map中的数据.只包含不为null的字段
|
*
|
* @param map
|
* @param entity
|
* @param <K> String 或 Object
|
*/
|
@SuppressWarnings({"unchecked"})
|
public static <K> void putValue(Map<K, Object> map, Object entity) {
|
if (entity == null) {
|
return;
|
}
|
PropertyDescriptor[] pds = getPropertyDescriptors(entity);
|
Arrays.stream(pds).forEach(pd -> {
|
// String key = pd.getName();
|
Object value = getPropertyValue(entity, pd);
|
if (value != null) {
|
map.put((K) pd.getName(), value);
|
}
|
});
|
}
|
|
/**
|
* 将实体对象转换为Map.返回的map中只包含不为null的字段
|
*
|
* @param entity
|
* @param <K> String 或 Object
|
* @return
|
*/
|
public static <K> Map<K, Object> toMap(Object entity) {
|
Map<K, Object> map = new HashMap<>();
|
putValue(map, entity);
|
return map;
|
}
|
|
/**
|
* 根据列名,将数据value写入到实体entity中.会根据列名的下划线分隔符写入到子对象中.
|
*
|
* @param entity 实体对象
|
* @param columnName SQL读取的列名
|
* @param value 要写入的数据值
|
* @return 是否有设置值.
|
*/
|
public static boolean setPropertyValueByColumn(Object entity, String columnName, Object value) {
|
columnName = StringUtils.strip(columnName, "_");
|
Class<?> clazz = Hibernate.getClass(entity);
|
String propertyName = columnToProperty(columnName);
|
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, propertyName);
|
if (pd != null) {
|
setPropertyValue(entity, pd, value);
|
return true;
|
}
|
|
// 可能是包含子对象
|
int p = columnName.indexOf("_"); // 以下划线分隔的字段名
|
String field;
|
while (p > 0) {
|
field = columnName.substring(0, p);
|
propertyName = columnToProperty(field);
|
pd = BeanUtils.getPropertyDescriptor(clazz, propertyName);
|
if (pd != null) {
|
break;
|
}
|
p = columnName.indexOf("_", p + 1);
|
}
|
if (pd == null) {
|
return false;
|
}
|
|
Object e = getPropertyValue(entity, pd);
|
boolean flag = e == null;
|
if (flag) {
|
e = BeanUtils.instantiateClass(pd.getPropertyType());
|
}
|
boolean change = setPropertyValueByColumn(e, columnName.substring(p + 1), value);
|
if (flag && change) {
|
setPropertyValue(entity, pd, e);
|
}
|
return change;
|
}
|
|
/**
|
* 将obj对象转换为指定的cls类型.如果没有转换则返回obj
|
*
|
* @param obj 要转换的数据,一般指从数据库读取的数据
|
* @param cls 要转换为的类型,一般为实体类的字段class
|
* @return
|
*/
|
public static Object convert(Object obj, Class<?> cls) {
|
if (obj == null) {
|
return null;
|
}
|
if (cls.isAssignableFrom(obj.getClass())) {
|
return obj;
|
}
|
if (String.class.equals(cls)) {
|
return obj.toString();
|
}
|
|
if (Date.class.equals(cls)) {
|
return DateUtils.parse(obj.toString());
|
}
|
if (Double.class.equals(cls) || Double.TYPE.equals(cls) || Float.class.equals(cls) || Float.TYPE.equals(cls) || Long.class.equals(cls)
|
|| Long.TYPE.equals(cls) || Integer.class.equals(cls) || Integer.TYPE.equals(cls) || Short.class.equals(cls) || Short.TYPE.equals(cls)
|
|| Byte.class.equals(cls) || Byte.TYPE.equals(cls)) {
|
// 数字类型
|
BigDecimal bd;
|
if (obj instanceof Number) {
|
bd = new BigDecimal(obj.toString());
|
} else if (obj instanceof Date) {
|
bd = new BigDecimal(((Date) obj).getTime());
|
} else {
|
bd = new BigDecimal(obj.toString());
|
}
|
|
if (Double.TYPE.equals(cls)||Double.class.equals(cls)) {
|
return bd.doubleValue();
|
}
|
|
if (Float.TYPE.equals(cls)||Float.class.equals(cls)) {
|
return bd.floatValue();
|
}
|
|
if (Long.TYPE.equals(cls)||Long.class.equals(cls)) {
|
return bd.longValue();
|
}
|
|
if (Integer.TYPE.equals(cls)||Integer.class.equals(cls)) {
|
return bd.intValue();
|
}
|
|
if (Short.TYPE.equals(cls)||Short.class.equals(cls)) {
|
return bd.shortValue();
|
}
|
|
if (Byte.TYPE.equals(cls)||Byte.class.equals(cls)) {
|
return bd.byteValue();
|
}
|
}
|
|
if (BigDecimal.class.isAssignableFrom(cls)) {
|
// 大数类型
|
if (obj instanceof Long || obj instanceof Integer || obj instanceof Short || obj instanceof Byte) {
|
return BigDecimal.valueOf(((Number) obj).longValue());
|
} else if (obj instanceof Number) {
|
return BigDecimal.valueOf(((Number) obj).doubleValue());
|
} else if (obj instanceof Date) {
|
return BigDecimal.valueOf(((Date) obj).getTime());
|
} else {
|
return new BigDecimal(obj.toString());
|
}
|
}
|
|
if (BigInteger.class.isAssignableFrom(cls)) {
|
// 大整数类型
|
if (obj instanceof Number) {
|
return BigInteger.valueOf(((Number) obj).longValue());
|
} else if (obj instanceof Date) {
|
return BigInteger.valueOf(((Date) obj).getTime());
|
} else {
|
return new BigInteger(obj.toString());
|
}
|
}
|
|
return obj;
|
}
|
|
/**
|
* 将原生数据数组转换为Object[]
|
*
|
* @param primitives boolean[]/byte[]/short[]/char[]/int[]/long[]/float[]/double[]等类型的数组
|
* @return Object[]数组
|
*/
|
public static Object[] toObject(Object primitives) {
|
if (primitives == null) {
|
return null;
|
}
|
if (!primitives.getClass().isArray()) {
|
return new Object[]{primitives};
|
}
|
// final Class<?> cls = primitives.getClass().getComponentType();
|
if (primitives instanceof boolean[]) {
|
return ArrayUtils.toObject((boolean[]) primitives);
|
}
|
if (primitives instanceof byte[]) {
|
return ArrayUtils.toObject((byte[]) primitives);
|
}
|
if (primitives instanceof short[]) {
|
return ArrayUtils.toObject((char[]) primitives);
|
}
|
if (primitives instanceof char[]) {
|
return ArrayUtils.toObject((char[]) primitives);
|
}
|
if (primitives instanceof int[]) {
|
return ArrayUtils.toObject((int[]) primitives);
|
}
|
if (primitives instanceof long[]) {
|
return ArrayUtils.toObject((long[]) primitives);
|
}
|
if (primitives instanceof float[]) {
|
return ArrayUtils.toObject((float[]) primitives);
|
}
|
if (primitives instanceof double[]) {
|
return ArrayUtils.toObject((double[]) primitives);
|
}
|
|
return (Object[]) primitives;
|
}
|
|
/**
|
* 将下划线的字段改为驼峰命名
|
*
|
* @param param
|
* @return
|
*/
|
public static String underlineToCamel(String param) {
|
if (param == null || "".equals(param.trim())) {
|
return "";
|
}
|
int len = param.length();
|
StringBuilder sb = new StringBuilder(len);
|
for (int i = 0; i < len; i++) {
|
char c = param.charAt(i);
|
if (c == UNDERLINE) {
|
if (++i < len) {
|
sb.append(Character.toUpperCase(param.charAt(i)));
|
}
|
} else {
|
sb.append(c);
|
}
|
}
|
return sb.toString();
|
}
|
|
/**
|
* 首字母转小写
|
*
|
* @param s
|
* @return
|
*/
|
public static String toLowerCaseFirstOne(String s) {
|
if (Character.isLowerCase(s.charAt(0))) {
|
return s;
|
} else {
|
return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
|
}
|
}
|
|
|
/**
|
* @param name 转换前的驼峰式命名的字符串
|
* @return 转换后下划线大写方式命名的字符串
|
*/
|
public static String humpToDivide(String name, String connStr) {
|
StringBuilder result = new StringBuilder();
|
if (name != null && name.length() > 0) {
|
// 将第一个字符处理成大写
|
result.append(name.substring(0, 1).toUpperCase());
|
// 循环处理其余字符
|
for (int i = 1; i < name.length(); i++) {
|
String s = name.substring(i, i + 1);
|
// 在大写字母前添加下划线
|
if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0))) {
|
result.append(connStr);
|
}
|
// 其他字符直接转成大写
|
result.append(s);
|
}
|
}
|
return result.toString().toLowerCase(Locale.ENGLISH);
|
}
|
|
/**
|
* 判断对象是否为null/empty/blan
|
*
|
* @param value
|
* @return
|
*/
|
public static boolean isBlank(Object value) {
|
if (value == null) {
|
return true;
|
}
|
if (value instanceof CharSequence) {
|
return StringUtils.isBlank((CharSequence) value);
|
}
|
if (value.getClass().isArray() && Array.getLength(value) < 1) {
|
return true;
|
}
|
if (value instanceof Collection && ((Collection<?>) value).isEmpty()) {
|
return true;
|
}
|
if (value instanceof Map && ((Map<?, ?>) value).isEmpty()) {
|
return true;
|
}
|
|
return false;
|
}
|
|
/**
|
* 判断对象是否为null/empty/blan
|
*
|
* @param value
|
* @return
|
*/
|
public static boolean isEmpty(Object value) {
|
if (value == null) {
|
return true;
|
}
|
if (value instanceof CharSequence) {
|
return StringUtils.isEmpty((CharSequence) value);
|
}
|
if (value.getClass().isArray() && Array.getLength(value) < 1) {
|
return true;
|
}
|
if (value instanceof Collection && ((Collection<?>) value).isEmpty()) {
|
return true;
|
}
|
if (value instanceof Map && ((Map<?, ?>) value).isEmpty()) {
|
return true;
|
}
|
|
return false;
|
}
|
}
|