1. 程式人生 > >JAVA反射列轉行儲存資料功能

JAVA反射列轉行儲存資料功能

服務類:主要提供統一的儲存物件(saveLogObject)、查詢物件的方法(getLogObject)(備註:業務資料id按照uuid獲取)

public class DataLogService extends CrudService<DataLogDao,DataLog> {

    /**
     * 儲存業務物件
     * 實體對應欄位在datalogmapping.xml中配置
     * @param object
     */
    @Transactional(readOnly = false)
    public void saveLogObject(Object object){
        Class clazz = object.getClass();
//        System.out.println(clazz.getSimpleName());
        List<DataLog> dataLogList = new ArrayList<>();
        //獲取配置項中需要記錄的欄位
        List<String> list = DataLogMap.getKeyByName(clazz.getSimpleName());
        String dataId = null;
        if(list != null){
            try {
                //獲取傳輸物件的ID
                Method method = clazz.getMethod("getId");
                dataId = (String) method.invoke(object);
                Date today = new Date();
                //欄位行轉列儲存
                for(String dataKey : list){
                    DataLog dataLog = new DataLog();
                    dataLog.setId(IdGen.uuid());
                    dataLog.setDataType(clazz.getSimpleName());
                    dataLog.setDataId(dataId);
                    dataLog.setDataKey(dataKey);
                    //獲取物件的get方法  呼叫get方法獲取值
                    Method getMethod = clazz.getMethod(getMethodName("get", dataKey));
                    Object obj = getMethod.invoke(object);
                    //設定儲存資料物件的值
                    dataLog.setDataValue(getStringValue(obj));
                    dataLog.setCreateDate(today);
                    dataLog.setNewFlag(1);
                    dataLogList.add(dataLog);
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        if(dataLogList != null){
            //先更新資料為舊版本
            dao.updateDataToOld(clazz.getSimpleName(),dataId);
            //再儲存新資料
            dao.saveList(dataLogList);
        }
    }

    /**
     * 根據物件 獲取最新日誌物件資料
     * 未查到日誌的話返回當前傳入業務物件
     * 目前僅支援4種類型資料轉換,後期可擴充套件:Integer、Double、String、Date
     * @return
     */
    public Object getLogObject(Object object){
        Object oldObj = null;
        try {
            Class clazz = object.getClass();
            oldObj = clazz.newInstance();
            //獲取配置項中需要記錄的欄位
            List<String> list = DataLogMap.getKeyByName(clazz.getSimpleName());
            //獲取傳入物件的ID
            Method method = clazz.getMethod("getId");
            String dataId = (String) method.invoke(object);

            //獲取舊資料日誌列表資料:
            List<DataLog> dataLogList = dao.findListByTypeAndId(clazz.getSimpleName(), dataId);
            Map<String,String> valueMap = new HashMap<String,String>();
            Map<String,Method> methodMap = new HashMap<String,Method>();
            if(dataLogList != null && dataLogList.size() > 0){
                //獲取欄位對應值 存放map中 目前全為字串 需要轉換
                for(DataLog dataLog : dataLogList){
                    valueMap.put(dataLog.getDataKey(),dataLog.getDataValue());
                }
                //獲取所有方法  方法名為key組成map  set方法 按照僅有一個方法處理
                Method[] methods = clazz.getMethods();
                for(Method m : methods){
                    methodMap.put(m.getName(),m);
                }
                //呼叫每個欄位的set方法
                for(String dataKey : list){
                    System.out.println(dataKey);
                    //獲取set方法
                    Method setMethod = methodMap.get(getMethodName("set", dataKey));
                    //set方法 按照僅有一個引數處理
                    Class<?>[] parameterTypes = setMethod.getParameterTypes();
                    if(parameterTypes != null && parameterTypes.length > 0){
                        if(valueMap.get(dataKey) != null){
                            //根據型別不一樣呼叫 不同型別轉換傳參
                            if(parameterTypes[0] == String.class){
                                setMethod.invoke(oldObj,valueMap.get(dataKey));
                            }
                            if(parameterTypes[0] == Date.class){
                                setMethod.invoke(oldObj,DateUtils.parseDate(valueMap.get(dataKey)));
                            }
                            if(parameterTypes[0] == Double.class){
                                setMethod.invoke(oldObj,Double.parseDouble(valueMap.get(dataKey)));
                            }
                            if(parameterTypes[0] == Integer.class){
                                setMethod.invoke(oldObj,Integer.parseInt(valueMap.get(dataKey)));
                            }
                        }else{
                            setMethod.invoke(oldObj,new Object[] { null } );
                        }

                    }
                }
            }else{
                //未查到日誌的話 返回當前業務物件
                return object;
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return oldObj;
    }

    /**
     * 獲取get set方法
     * @param fieldName
     * @return
     */
    private String getMethodName(String type,String fieldName){
        if(fieldName != null && fieldName.length() > 0){
            if(fieldName.length() > 1){
                return type + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
            }else{
                return type + fieldName.substring(0,1).toUpperCase();
            }
        }
        return "";
    }

    /**
     * 根據物件返回String型別資料
     * 目前僅支援4種類型資料轉換,後期可擴充套件:Integer、Double、String、Date
     * @param obj
     * @return
     */
    private String getStringValue(Object obj){
        if(obj == null){
            return null;
        }
        if(obj instanceof java.lang.String){
            return (String) obj;
        }
        if(obj instanceof java.lang.Double){
            return String.valueOf(obj);
        }
        if(obj instanceof java.lang.Integer){
            return String.valueOf(obj);
        }
        if(obj instanceof java.util.Date){
            return DateUtils.formatDate((Date)obj,"yyyy-MM-dd HH:mm:ss");
        }
        return obj.toString();
    }
}

datalogmapping.xml:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <Class1>
        <field>field1</field>
        <field>field2</field>
        <field>field3</field>
    </Class1>
    <Class2>
        <field>field1</field>
        <field>field2</field>
    </Class2>
</root>

解析實體列傳行配置的配置的xml檔案:

public class DataLogMap {

    /**
     * datalogmapping配置檔案中讀取內容
     * key:root節點下二級元素節點
     * value:三級節點filed下的value 列表
     */
    private final static Map<String, List<String>> map = new HashMap();

    static {
        InputStream inputStream = DataLogMap.class.getClassLoader().getResourceAsStream("datalogmapping.xml");
        try {
            //使用dom4j解析datalogmapping.xml,生成dom樹
            SAXReader reader = new SAXReader();
            Document doc = reader.read(inputStream);
            //得到根節點:
            Element root = doc.getRootElement();
            //得到的所有節點:
            List<Element> list = root.elements();
            if(list != null && list.size() > 0){
                for(Element pElement : list){
                    List<Element> sonList = pElement.elements();
                    if(sonList != null && sonList.size() > 0){
                        for(Element sElement : sonList){
                            List<String> mapList = null;
                            if(map.get(pElement.getName()) != null){
                                mapList = map.get(pElement.getName());
                            }else{
                                mapList = new ArrayList<>();
                            }
//                            System.out.println(sElement.getText());
                            mapList.add(sElement.getText());
                            map.put(pElement.getName(),mapList);
                        }
                    }
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                };
            }
        }
    }

    /**
     * 根據實體名稱返回需要比對的欄位名稱 (讀取配置檔案中資料)
     * @param entityName
     * @return
     */
    public static List<String> getKeyByName(String entityName){
        return map.get(entityName);
    }

}