JAVA反射列轉行儲存資料功能
阿新 • • 發佈:2018-11-26
服務類:主要提供統一的儲存物件(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); } }