页面编辑器跟数据模型绑定的一点处理思路

因为数据转换花了几天时间,逻辑上面比较复杂,做下记录,里面还有很大的改进空间。

参考数据格式:

{
    "designerId": "63470494272864331",
    "dataId": 1,
    "transInfo":{
        "61532381690609670": 1
    },
    "modelList": [
        "61433580262932491"
    ],
    "dataInfo": {
        "61433580262932499": "test-device",
        "61532381690609670": 1,
        "63470494272864312": "2022-03-17",
        "61433580262932491": [
            {
                "63470494272864320": "气压",
                "61532381690609666": "查看操作流程",
                "61532381690609668": 11111,
                "61532381690609667": "OK",
                "id": "Le44NzDPy6"
            },
            {
                "63470494272864320": "温度",
                "61532381690609666": "查看操作流程",
                "61532381690609668": 2222,
                "61532381690609667": "NG",
                "id": "97ISPCCqtF"
            },
            {
                "63470494272864320": "湿度",
                "61532381690609666": "查看操作流程",
                "61532381690609668": 33333,
                "61532381690609667": "OK",
                "id": "qeY8N-vRre"
            },
            {
                "63470494272864320": "重量",
                "61532381690609666": "查看操作流程",
                "61532381690609668": 44444,
                "61532381690609667": "OK",
                "id": "EFDic4byne"
            }
        ]
        
    }
}

情况与处理逻辑:
前端传过来的数据 用的是数据模型ID:值的形式。json格式。直接存储一份json,用于后续返回,这样不用查询的时候从模型抽数据还原格式。
注意存储实体表需要把数据模型转成 key:value形式。
然后按照模型存储到实体表中(模型会生成实体表)

  1. A模型,一条数据
    这种情况最简单。转换成k:v,直接存储就行
  2. A模型,多条数据list,个别字段前提的情况:
    个别字段先转换成k:v。然后循环list,把个别字段依次塞入list中。
    待处理问题:如果list在个别字段前面,就存储不到了。需要后置list处理
  3. A模型,一条数据。B模型多条list,且跟A模型关联
    同2情况。先把A模型数据转换k:v,存储数据库。生成ID记录
    循环list,塞入ID。或者传入sql语句中也行
  4. A模型,一条数据。B模型一条数据。
    同3情况,转换存储A,转换存储B
  5. A模型,一条数据,但存在多选list。B多条数据
    这里需要考虑多选list和数据list的区分。我这里采取形式是前端告知传过来的ID是多选数组,还是对象数据。校验 modelList 即可。或者可以通过instanceof过滤
    存储多选的逻辑,这里先没有处理。可以再建立kv表,或者不是特别重要的数据,仅仅展示用,可以数组转字符串。只要能区分开,具体怎么处理都不是大问题了

待验证事项: id:值 和 table@code:值的 探讨
数据量问题。code本身占用空间更大
数据处理。id需要先掉数据库缓存数据,string转long。code需要切分多次
数据维护。code存在修改问题。id存在误删除问题
隐私问题。id不可见,code可见
数组和对象区分问题。id是判断是否存在模型list中。code?
后续扩展上面id可以根据属性做很多特殊处理。判断属性是否是数组,是否是关联其他模型。
目前来看split去切分 table@code的性能损失要大于数据库数据的缓存

数据存储与更新逻辑
前面说了前端把数据传给后台的处理逻辑。这里面有个问题是每次前端保存来的数据,怎么知道是需要新增还是更新。

  1. 全删全增
    实体表里面有个业务ID,每次保存的时候,根据业务ID删除所有数据。然后再新增。这种思路适用于纯业务数据展示用。这样处理最简单
  2. LIST比对。分出来 addList,updateList,deleteList
    依次处理数据。
  3. 创建一个对照表。记录传进来的数据跟模型的关联关系。
    每次更改的是数据跟模型关联关系。不通过实体表存储了
    关于数据处理的形式。目前还在探索实验阶段,不做好坏的判断。

核心代码处理逻辑。附加的代码就不贴了。仅做个记录。

    /**
     * 页面设计器数据存储到数据模型
     */
    public void saveModel(DesignerData designerData) {

        //根据模型code 获取出来所有的
        List<Long> modelIdList = designerData.getModelList();
        List<DataModel> modelList = dataModelService.listByModelIdList(modelIdList);
        //根据属性id抽取key
        Map<Long, DataModel> modelIdMap = modelList.stream()
                .collect(Collectors.toMap(
                        DataModel::getModelId, a -> a
                ));

        //获取模型的所有属性
        List<DataModelAttribute> attributeList = attributeService.listByModelIdList(modelIdList);
        //根据属性id抽取key
        Map<Long, DataModelAttribute> attributeIdMap = attributeList.stream()
                .collect(Collectors.toMap(
                        DataModelAttribute::getAttributeId, a -> a
                ));

        //实际存储模型的map
        Map<String, Map<String, Object>> modelDataMap = new HashMap<>();
        Map<String, List<Map<String, Object>>> modelDataListMap = new HashMap<>();

        //实际存储字段的map
        Map<String, Map<String, Object>> modelColumnMap = new HashMap<>();
        //字段的数组
        Map<String, List<String>> codeListMap = new HashMap<>();

        //处理字段
        for (Map.Entry<String, Object> entry : designerData.getTransInfo().entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            Long id = Long.valueOf(key);

            DataModelAttribute attributeTemp = attributeIdMap.get(id);
            String idStr = attributeTemp.getModelId().toString();
            codeListMap.computeIfAbsent(idStr, k -> new ArrayList<>());
            codeListMap.get(idStr).add(attributeTemp.getCode());

            modelColumnMap.computeIfAbsent(idStr, k -> new HashMap<>());
            modelColumnMap.get(idStr)
                    .put(attributeTemp.getCode(), value);
        }

        //处理数据
        for (Map.Entry<String, Object> entry : designerData.getDataInfo().entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            Long id = Long.valueOf(key);

            if (modelIdList.contains(id)) {
                // 说明这个id是模型,不是字段
                //此时obj是一个list
                List<Map<String, Object>> objList = (List<Map<String, Object>>) value;
                for (Map<String, Object> item : objList) {
                    Map<String, Map<String, Object>> modelTempMap = new HashMap<>();
                    for (Map.Entry<String, Object> tempEntry : item.entrySet()) {
                        String tempIdStr = tempEntry.getKey();
                        Object tempValue = tempEntry.getValue();
                        if (tempIdStr.equals("id")) {
                            continue;
                        }
                        Long tempId = Long.valueOf(tempIdStr);

                        DataModelAttribute attributeTemp = attributeIdMap.get(tempId);
                        String idStr = attributeTemp.getModelId().toString();
                        modelTempMap.computeIfAbsent(idStr, k -> new HashMap<>());
                        modelTempMap.get(idStr)
                                .put(attributeTemp.getCode(), tempValue);
                        modelTempMap.get(idStr).putAll(modelDataMap.get(idStr));
                    }
                    modelDataListMap.computeIfAbsent(key, k -> new ArrayList<>());
                    modelDataListMap.get(key)
                            .add(modelTempMap.get(key));
                }
            } else {
                DataModelAttribute attributeTemp = attributeIdMap.get(id);
                String idStr = attributeTemp.getModelId().toString();
                modelDataMap.computeIfAbsent(idStr, k -> new HashMap<>());
                modelDataMap.get(idStr)
                        .put(attributeTemp.getCode(), value);
                modelDataMap.get(idStr)
                        .putAll(modelColumnMap.get(idStr));
            }
        }

        for (Map.Entry<String, Map<String, Object>> entry : modelDataMap.entrySet()) {
            if (modelDataListMap.get(entry.getKey()) != null) {
                //如果列表里面已经有了上面的值,那么在列表中已经合并了
                continue;
            }
            String idStr = entry.getKey();
            Long modelId = Long.parseLong(idStr);
            //存储对应的model数据
            String modelCode = modelIdMap.get(modelId).getCode();
            modelDataService.deleteByCode(modelCode, codeListMap.get(idStr), modelColumnMap.get(idStr));
            modelDataService.add(modelCode, entry.getValue());
        }
        for (Map.Entry<String, List<Map<String, Object>>> entry : modelDataListMap.entrySet()) {
            String idStr = entry.getKey();
            Long modelId = Long.parseLong(idStr);
            String modelCode = modelIdMap.get(modelId).getCode();
            modelDataService.deleteByCode(modelCode, codeListMap.get(idStr), modelColumnMap.get(idStr));
            //存储对应的model数据
            entry.getValue().forEach(item -> {
                modelDataService.add(modelCode, item);
            });
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值