Browse Source

对象的扩展属性提取到外层

yucheng 3 years ago
parent
commit
af26280108

+ 11 - 4
dmp-business/dmp-rwd/src/main/java/com/persagy/dmp/rwd/digital/controller/ObjectDigitalController.java

@@ -3,7 +3,10 @@ package com.persagy.dmp.rwd.digital.controller;
 import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.basic.utils.JsonNodeUtils;
 import com.persagy.dmp.common.constant.ResponseCode;
 import com.persagy.dmp.common.exception.BusinessException;
 import com.persagy.dmp.common.model.response.CommonResult;
@@ -49,27 +52,31 @@ public class ObjectDigitalController {
     }
 
     @PostMapping("/createOne")
-    public CommonResult<ObjectDigital> create(@Valid @RequestBody ObjectDigital vo){
+    public CommonResult<ObjectDigital> create(@Valid @RequestBody ObjectNode node){
+        ObjectDigital vo = JsonNodeUtils.toEntity(node, ObjectDigital.class, "infos");
         List<ObjectDigital> voList = CollUtil.newArrayList(vo);
         service.insert(voList);
         return ResultHelper.single(vo);
     }
 
     @PostMapping("/create")
-    public CommonResult<PageList<ObjectDigital>> createBatch(@Valid @RequestBody List<ObjectDigital> voList){
+    public CommonResult<PageList<ObjectDigital>> createBatch(@Valid @RequestBody ArrayNode array){
+        List<ObjectDigital> voList = JsonNodeUtils.toEntity(array, ObjectDigital.class, "infos");
         voList = service.insert(voList);
         return ResultHelper.multi(voList);
     }
 
     @PostMapping("/updateOne")
-    public CommonResult<ObjectDigital> update(@Valid @RequestBody ObjectDigital vo){
+    public CommonResult<ObjectDigital> update(@Valid @RequestBody ObjectNode node){
+        ObjectDigital vo = JsonNodeUtils.toEntity(node, ObjectDigital.class, "infos");
         List<ObjectDigital> voList = CollUtil.newArrayList(vo);
         service.update(voList);
         return ResultHelper.single(vo);
     }
 
     @PostMapping("/update")
-    public CommonResult<PageList<ObjectDigital>> updateBatch(@Valid @RequestBody List<ObjectDigital> voList){
+    public CommonResult<PageList<ObjectDigital>> updateBatch(@Valid @RequestBody ArrayNode array){
+        List<ObjectDigital> voList = JsonNodeUtils.toEntity(array, ObjectDigital.class, "infos");
         voList = service.update(voList);
         return ResultHelper.multi(voList);
     }

+ 12 - 3
dmp-business/dmp-rwd/src/main/java/com/persagy/dmp/rwd/digital/service/impl/ObjectDigitalServiceImpl.java

@@ -22,6 +22,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -123,11 +124,19 @@ public class ObjectDigitalServiceImpl implements IObjectDigitalService {
             }
             // 信息点值对象
             ObjectNode infos = vo.getInfos();
-            // 按信息点定义循环校验
-            for(String infoCode:infoMap.keySet()) {
-                if(!infos.has(infoCode)) {
+            if(infos == null || infos.isNull()) {
+                continue;
+            }
+            // 按infos属性循环处理
+            Iterator<String> infoKeys = infos.fieldNames();
+            while(infoKeys.hasNext()) {
+                String infoCode = infoKeys.next();
+                // 如果信息点中不存在,移除
+                if(!infoMap.containsKey(infoCode)) {
+                    infos.remove(infoCode);
                     continue;
                 }
+                // 校验信息点值
                 InfoDataFactory.parse(infoMap.get(infoCode), infos.get(infoCode));
             }
         }

+ 167 - 3
dmp-comp/dmp-digital-starter/src/main/java/com/persagy/dmp/basic/utils/JsonNodeUtils.java

@@ -1,11 +1,19 @@
 package com.persagy.dmp.basic.utils;
 
+import cn.hutool.core.collection.CollUtil;
+import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.exception.BusinessException;
+import com.persagy.dmp.common.helper.SpringHelper;
+import com.persagy.dmp.common.model.entity.BaseEntity;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.lang.reflect.Field;
+import java.util.*;
 
 /**
  * JsonNode 工具
@@ -15,6 +23,162 @@ import java.util.List;
 public class JsonNodeUtils {
 
     /**
+     * 将对象转换为Json对象,自动扩充扩展列
+     * @param vo 对象
+     * @param extraColumn 扩展列名
+     * @return Json对象
+     */
+    public static ObjectNode toObjectNode(BaseEntity vo, String extraColumn) {
+        if(vo == null) {
+            return null;
+        }
+        // 将vo转换为ObjectNode
+        ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+        ObjectNode node = null;
+        try {
+            String voJson = objectMapper.writeValueAsString(vo);
+            node = objectMapper.readValue(voJson, ObjectNode.class);
+        } catch (IOException e) {
+            throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
+        }
+        ensureExtras(node, extraColumn);
+        return node;
+    }
+
+    /**
+     * 将对象转换为Json对象,自动扩充扩展列
+     * @param voList List对象
+     * @param extraColumn 扩展列名
+     * @return Json对象
+     */
+    public static ArrayNode toArrayNode(List<BaseEntity> voList, String extraColumn) {
+        if(CollUtil.isEmpty(voList)) {
+            return null;
+        }
+        // 将vo转换为ObjectNode
+        ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+        ArrayNode array = null;
+        try {
+            String voJson = objectMapper.writeValueAsString(voList);
+            array = objectMapper.readValue(voJson, ArrayNode.class);
+        } catch (IOException e) {
+            throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
+        }
+        for(int i = 0;i < array.size();i++) {
+            ObjectNode node = (ObjectNode) array.get(i);
+            ensureExtras(node, extraColumn);
+        }
+        return array;
+    }
+
+    /**
+     * 在Json对象中扩充扩展列
+     * @param node json对象
+     * @param extraColumn 扩展列名
+     */
+    private static void ensureExtras(ObjectNode node, String extraColumn) {
+        JsonNode extraNode = node.get(extraColumn);
+        // 如果扩展列的值为空或不是对象,直接返回
+        if(extraNode.isNull() || !extraNode.isObject()) {
+            return;
+        }
+        Iterator<String> extraKeys = extraNode.fieldNames();
+        while (extraKeys.hasNext()) {
+            String extraKey = extraKeys.next();
+            // 外部已有的属性,不再赋值
+            if (node.has(extraKey)) {
+                continue;
+            }
+            // 将extra移到外部
+            node.set(extraKey, extraNode.get(extraKey));
+        }
+        // 删除extra
+        node.remove(extraColumn);
+    }
+
+    /**
+     * json转换为Clazz,为扩展属性赋值
+     * @param node json对象
+     * @param clazz 类
+     * @param extraColumn 扩展属性名
+     * @param <T>
+     * @return
+     */
+    public static <T> T toEntity(ObjectNode node, Class<T> clazz, String extraColumn) {
+        // 检查clazz包含的属性
+        Field[] fields = clazz.getDeclaredFields();
+        Set<String> fieldSet = new HashSet<>();
+        for(Field field:fields) {
+            fieldSet.add(field.getName());
+        }
+        // 转换node
+        collectExtras(node, extraColumn, fieldSet, null);
+        // 转换为对象
+        ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+        try {
+            return objectMapper.readValue(node.toString(), clazz);
+        } catch (IOException e) {
+            throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
+        }
+    }
+
+    /**
+     * json转换为Clazz,为扩展属性赋值
+     * @param array json对象
+     * @param clazz 类
+     * @param extraColumn 扩展属性名
+     * @param <T>
+     * @return
+     */
+    public static <T> List<T> toEntity(ArrayNode array, Class<T> clazz, String extraColumn) {
+        // 检查clazz包含的属性
+        Field[] fields = clazz.getDeclaredFields();
+        Set<String> fieldSet = new HashSet<>();
+        for(Field field:fields) {
+            fieldSet.add(field.getName());
+        }
+        // 转换node
+        for(int i = 0;i < array.size();i++) {
+            ObjectNode node = (ObjectNode) array.get(i);
+            collectExtras(node, extraColumn, fieldSet, null);
+        }
+        // 转换为对象List
+        ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+        try {
+            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, clazz);
+            return objectMapper.readValue(array.toString(), javaType);
+        } catch (IOException e) {
+            throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
+        }
+    }
+
+    /**
+     * 收集扩展属性
+     * @param node json对象
+     * @param extraColumn 扩展列名
+     * @param classColumns 对象包含的列
+     * @param extraColumns 扩展属性中包含的列。为空表示所有非对象的列
+     */
+    private static void collectExtras(ObjectNode node, String extraColumn, Set<String> classColumns, Set<String> extraColumns) {
+        ObjectNode extraNode = node.putObject(extraColumn);
+        Iterator<String> nodeKeys = node.fieldNames();
+        while (nodeKeys.hasNext()) {
+            String nodeKey = nodeKeys.next();
+            // clazz有的属性不用处理
+            if (classColumns.contains(nodeKey)) {
+                continue;
+            }
+            // 扩展列为空,或在扩展列范围内
+            if(CollUtil.isEmpty(extraColumns) || extraColumns.contains(nodeKey)) {
+                // clazz没有的属性添加到扩展属性中
+                extraNode.set(nodeKey, node.get(nodeKey));
+            }
+            // 移除node中此属性
+            node.remove(nodeKey);
+        }
+    }
+
+    /**
      * 获取Node值
      * @param node 值节点
      * @return

+ 1 - 1
dmp-comp/dmp-mybatis/src/main/java/com/persagy/dmp/mybatis/typehandler/PsDateTimeTypeHandler.java

@@ -17,7 +17,7 @@ import java.sql.SQLException;
  * @author Charlie Yu
  * @version 1.0 2021-04-08
  */
-@MappedJdbcTypes(JdbcType.CHAR)
+@MappedJdbcTypes({JdbcType.CHAR, JdbcType.TIMESTAMP})
 @MappedTypes(PsDateTime.class)
 public class PsDateTimeTypeHandler extends BaseTypeHandler<PsDateTime> {
 

+ 1 - 1
dmp-comp/dmp-mybatis/src/main/java/com/persagy/dmp/mybatis/typehandler/PsDateTypeHandler.java

@@ -17,7 +17,7 @@ import java.sql.SQLException;
  * @author Charlie Yu
  * @version 1.0 2021-04-08
  */
-@MappedJdbcTypes(JdbcType.CHAR)
+@MappedJdbcTypes({JdbcType.CHAR, JdbcType.TIMESTAMP})
 @MappedTypes(PsDate.class)
 public class PsDateTypeHandler extends BaseTypeHandler<PsDate> {
 

+ 1 - 1
dmp-comp/dmp-mybatis/src/main/java/com/persagy/dmp/mybatis/typehandler/PsTimeTypeHandler.java

@@ -17,7 +17,7 @@ import java.sql.SQLException;
  * @author Charlie Yu
  * @version 1.0 2021-04-08
  */
-@MappedJdbcTypes(JdbcType.CHAR)
+@MappedJdbcTypes({JdbcType.CHAR, JdbcType.TIMESTAMP})
 @MappedTypes(PsTime.class)
 public class PsTimeTypeHandler extends BaseTypeHandler<PsTime> {