当前位置 博文首页 > GooReey的博客:利用Java反射实现两个具有相同属性bean赋值

    GooReey的博客:利用Java反射实现两个具有相同属性bean赋值

    作者:[db:作者] 时间:2021-08-30 22:22

    一、前情提要?

    1、需求

    由于某种原因,您可能在项目中遇到类似的需求:

    1. 你需要读取一个文件,比如html、json、zip等等类型的文件;
    2. 需要将文件内容存到bean中;
    3. 将bean中内容存储到数据库中;

    2、您可能遇到的问题

    1. html的内容字段与你存储的数据库字段,字段名无法完全对应,比如大小写问题?
    2. 因为是读取文件,所以不知道数据的类型,只能暂时都看做String类型,但这又与数据库中的定义不符,所以也是需要转换的。

    二、代码实例

    1、文件中字段名

    package com.guor.entity;
    
    import java.util.Date;
    
    public class UserTxt {
        private String ID;
        private String USERname;
        private String Age;
        private String Address;
        private String School;
        private String create_date;
        private String update_date;
        private String DELeted;
    }

    2、数据库中字段名

    package com.guor.entity;
    
    import java.util.Date;
    
    public class User {
        private Integer id;
        private String username;
        private Integer age;
        private String address;
        private String school;
        private Date createDate;
        private Date updateDate;
        private Integer deleted;
    }
    

    3、反射工具类

    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.Map;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    @Slf4j
    public class ReflectUtil {
    ?? ?/**
     ?? ? * 不同类型,类似属性名称,两个bean之间的赋值,默认数据源bean类型都为String
     ?? ? */
            ?? ?public static <T, V> V convertByReflect(T srcObject, Class<V> targetClazz) {
    ?? ??? ?V targetClass = null;
    ?? ??? ?try {
    ?? ??? ??? ?Class<?> srcClazz = Class.forName(srcObject.getClass().getName());
    ?? ??? ??? ?targetClass = targetClazz.newInstance();
    ?? ??? ??? ?// 获取两个实体类的所有属性
    ?? ??? ??? ?Field[] srcFields = srcClazz.getDeclaredFields();
    ?? ??? ??? ?Field[] targetFields = targetClazz.getDeclaredFields();
    ?? ??? ??? ?// 遍历srcFields,获取属性值,然后遍历targetObject查找是否有相同的属性,如有相同则根据类型赋值
    ?? ??? ??? ?for (Field srcField : srcFields) {
    ?? ??? ??? ??? ?Object value = invokeGetMethod(srcObject, srcField.getName());
    ?? ??? ??? ??? ?for (Field targetField : targetFields) {
    ?? ??? ??? ??? ??? ?if (srcField.getName().toLowerCase().equals(targetField.getName().toLowerCase())) {
    ?? ??? ??? ??? ??? ??? ?// 两个类型是否相同
    ?? ??? ??? ??? ??? ??? ?if (srcField.getType().equals(targetField.getType())) {
    ?? ??? ??? ??? ??? ??? ??? ?setFieldValue(targetField, targetClass, value);
    ?? ??? ??? ??? ??? ??? ?} else {
    ?? ??? ??? ??? ??? ??? ??? ?setFieldValueByType(targetField, targetClass, value);
    ?? ??? ??? ??? ??? ??? ?}
    ?? ??? ??? ??? ??? ?}
    ?? ??? ??? ??? ?}
    ?? ??? ??? ?}
    ?? ??? ?} catch (Exception e) {
    ?? ??? ??? ?log.error("convertByReflect Error {}", e.getMessage());
    ?? ??? ??? ?return null;
    ?? ??? ?}
    ?? ??? ?return targetClass;
    ?? ?}
    ?? ?
        public static <V, T> T mapToBean(Map<String, V> map, Class<T> targetClazz) {
    ?? ??? ?T targetClass = null;
    ?? ??? ?try {
    ?? ??? ??? ?targetClass = targetClazz.newInstance();
    ?? ??? ??? ?Field[] targetFields = targetClazz.getDeclaredFields();
    ?? ??? ??? ?for (Map.Entry<String, V> entry : map.entrySet()) {
    ?? ??? ??? ??? ?for (Field targetField : targetFields) {
    ?? ??? ??? ??? ??? ?if (entry.getKey().toLowerCase().equals(targetField.getName().toLowerCase())) {
    ?? ??? ??? ??? ??? ??? ?// 两个类型是否相同
    ?? ??? ??? ??? ??? ??? ?if (entry.getValue().getClass().getTypeName().equals(targetField.getType())) {
    ?? ??? ??? ??? ??? ??? ??? ?setFieldValue(targetField, targetClass, entry.getValue());
    ?? ??? ??? ??? ??? ??? ?} else {
    ?? ??? ??? ??? ??? ??? ??? ?setFieldValueByType(targetField, targetClass, entry.getValue());
    ?? ??? ??? ??? ??? ??? ?}
    ?? ??? ??? ??? ??? ?}
    ?? ??? ??? ??? ?}
    ?? ??? ??? ?}
    ?? ??? ?} catch (Exception e) {
    ?? ??? ??? ?log.error("mapToBean Error {}", e.getMessage());
    ?? ??? ??? ?return null;
    ?? ??? ?}
    ?? ??? ?return targetClass;
    ?? ?}
    ?? ?
            ?? ?/**
     ?? ? * 不同类型,类似属性名称,两个List<bean>之间的赋值,默认数据源bean类型都为String
     ?? ? *?
     ?? ? * @param srcObjectList 数据源List<bean>
     ?? ? * @param targetClazz ? 目标类Class
     ?? ? * @return
     ?? ? */
       public static <T, V> List<V> convertListByReflect(List<T> srcObjectList, Class<V> targetClazz) {
    ?? ??? ?List<V> retList = new ArrayList<V>();
    ?? ??? ?try {
    ?? ??? ??? ?V targetClass = targetClazz.newInstance();
    ?? ??? ??? ?for (T srcObject : srcObjectList) {
    ?? ??? ??? ??? ?targetClass = convertByReflect(srcObject, targetClazz);
    ?? ??? ??? ??? ?if (targetClass == null) {
    ?? ??? ??? ??? ??? ?return new ArrayList<V>();
    ?? ??? ??? ??? ?}
    ?? ??? ??? ??? ?retList.add(targetClass);
    ?? ??? ??? ?}
    ?? ??? ?} catch (Exception e) {
    ?? ??? ??? ?log.error("convertByReflect Error {}", e.getMessage());
    ?? ??? ??? ?return new ArrayList<V>();
    ?? ??? ?}
    ?? ??? ?return retList;
    ?? ?}
    
    ?? ?/**
     ?? ? * 获取值
     ?? ? *?
     ?? ? * @param clazz ? ? 类
     ?? ? * @param fieldName 类的属性名称
     ?? ? * @return
     ?? ? */
            ?? ?private static Object invokeGetMethod(Object clazz, String fieldName) {
    ?? ??? ?String methodName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    ?? ??? ?Method method = null;
    ?? ??? ?try {
    ?? ??? ??? ?method = Class.forName(clazz.getClass().getName()).getDeclaredMethod("get" + methodName);
    ?? ??? ??? ?return method.invoke(clazz);
    ?? ??? ?} catch (Exception e) {
    ?? ??? ??? ?return "";
    ?? ??? ?}
    ?? ?}
    
    ?? ?/**
     ?? ? * 设置方法值
     ?? ? */
            ?? ?private static void setFieldValue(Field field, Object obj, Object value) throws IllegalAccessException {
    ?? ??? ?// 获取原有的访问权限
    ?? ??? ?boolean access = field.isAccessible();
    ?? ??? ?try {
    ?? ??? ??? ?// 设置可访问的权限
    ?? ??? ??? ?field.setAccessible(true);
    ?? ??? ??? ?field.set(obj, value);
    ?? ??? ?} finally {
    ?? ??? ??? ?// 恢复访问权限
    ?? ??? ??? ?field.setAccessible(access);
    ?? ??? ?}
    ?? ?}
    
    ?? ?/**
     ?? ? * 根据类型设置方法值
     ?? ? */
            ?? ?private static void setFieldValueByType(Field targetField, Object target, Object value)
    ?? ??? ??? ?throws IllegalAccessException {
    ?? ??? ?Class<?> targetType = targetField.getType();
    ?? ??? ?String valueStr = String.valueOf(value);
    ?? ??? ?if (targetType == Integer.class) {
    ?? ??? ??? ?setFieldValue(targetField, target, Integer.valueOf(valueStr));
    ?? ??? ?} else if (targetType == Double.class) {
    ?? ??? ??? ?setFieldValue(targetField, target, Double.valueOf(valueStr));
    ?? ??? ?} else if (targetType == Float.class) {
    ?? ??? ??? ?setFieldValue(targetField, target, Float.valueOf(valueStr));
    ?? ??? ?} else if (targetType == Boolean.class) {
    ?? ??? ??? ?setFieldValue(targetField, target, Boolean.parseBoolean(valueStr));
    ?? ??? ?} else if (targetType == Long.class) {
    ?? ??? ??? ?setFieldValue(targetField, target, Long.parseLong(valueStr));
    ?? ??? ?} else if (targetType == Short.class) {
    ?? ??? ??? ?setFieldValue(targetField, target, Short.parseShort(valueStr));
    ?? ??? ?} else if (targetType == Date.class) {
    ?? ??? ??? ?String dateStr = StrUtil.getDigital(valueStr);
    ?? ??? ??? ?setFieldValue(targetField, target, StrUtil.stringToDate(dateStr, "yyyyMMddHHmmss"));
    ?? ??? ?} else {
    ?? ??? ??? ?setFieldValue(targetField, target, valueStr);
    ?? ??? ?}
    ?? ?}
    }

    特别推荐:杉菜要压力测试,无从下手,我随手一个JMeter测试demo,轻松搞定

    往期精彩内容:

    Java知识体系总结

    Spring框架总结

    超详细的springBoot学习笔记

    常见数据结构与算法整理总结

    Java设计模式:23种设计模式全面解析

    Java面试题总结(附答案)

    Linux知识体系总结

    Redis知识体系总结

    cs
    下一篇:没有了