同一事务中增删改查以及嵌套级联更新业务

业务场景:主表下子表,子表下还有子表

 

    @Transactional(rollbackFor = Exception.class)
    public ResultDTO<String> update(DeviceServicesUpdateDTO updateDTO) {

        String identifier = updateDTO.getIdentifier().trim();
        List<String> invalidIdentifiers = new ArrayList<>(Arrays.asList("set", "get"));
        if (invalidIdentifiers.contains(identifier)) {
            return ResultDTO.failInvalidParamWithMsg("系统方法,不允许编辑");
        }
        Set<String> identifierSet = new HashSet<>();
        long productId = updateDTO.getDeviceId();
        String method = SERVICE_METHOD_PREFIX + identifier;
        DeviceServicesEntity entity = BeanUtil.copy(updateDTO, DeviceServicesEntity.class);
        log.info("=====>DeviceServicesService#update entity:" + entity + "\n" + "updateDTO:" + updateDTO);
        entity.setMethod(method).setUpdateRequired(updateDTO.getUpdateRequired());

        int updateServiceRet = -1;
        DeviceServicesEntity serviceDB = productServicesDao.selectById(updateDTO.getId());
        if (serviceDB == null || serviceDB.getOriginalRequired() == 1 || serviceDB.getCopyright() || serviceDB.getRelated() > 0) {
            log.error("服务不存在或者是模板必选服务或者已发布或者已被关联!serviceId = {}", updateDTO.getId());
            return ResultDTO.failInvalidParamWithMsg("请求参数错误!");
        }

        if (invalidIdentifiers.contains(serviceDB.getIdentifier())) {
            log.error("接口调用,更新默认服务不允许!");
            return ResultDTO.failInvalidParamWithMsg("系统方法,不允许编辑!");
        }

        if (serviceDB.getCustom() == 0) {
            entity.setUpdateRequired(updateDTO.getUpdateRequired());

            updateServiceRet = productServicesDao.updateById(entity);
            if (updateServiceRet > 0) {
                if (productsService.updateDeviceUpdateTime(productId) < 1) {
                    throw new IotBusinessException("对不起,请求参数错误!");
                }
            }

            return ResultDTO.succ();
        }
        String dbIdentifier = serviceDB.getIdentifier();
        identifierDao.updateBySrcIdentifierAndDeviceId(updateDTO.getIdentifier(), dbIdentifier, productId);
        /*return ResultDTO.failInvalidParamWithMsg("更新服务,参数错误,查不到相应的记录");*/


        // 处理数据记录服务的参数记录 数据记录服务的id
        long refId = updateDTO.getId();
        /** 查询数据记录服务参数列表<=========>输出和输入参数集合 **/
        List<DeviceServicesParamsVO> productServicesParamsVOS = productServicesParamsDao.listByRefIds(new ArrayList<>(Arrays.asList(refId)));

        /** 查询数据记录服务参数id集合 <=========> 输出和输入参数id集合 **/
        List<Long> allParamIdsDB = productServicesParamsVOS.stream().map(DeviceServicesParamsVO::getId).collect(Collectors.toList());

        List<Long> srcOutIdsDB = new ArrayList<>();
        //long start = System.currentTimeMillis();
        for (int i = 0; i < productServicesParamsVOS.size(); i++) {
            if (productServicesParamsVOS.get(i).getType().equals(ServiceParamTypeEnum.ParamType.OUT_PARAM.getCode())) {
                srcOutIdsDB.add(productServicesParamsVOS.get(i).getId());
            }
        }
        List<Long> srcInIdsDB = new ArrayList<>();

        if (allParamIdsDB.removeAll(srcOutIdsDB) || CollectionUtils.isEmpty(srcOutIdsDB)) {
            srcInIdsDB = allParamIdsDB;
        }

        List<DeviceServicesParamsEntity> paramsUpdateDTOs = new ArrayList<>();
        /** 需要删除的id集合  <=========> 输出和输入参数id集合 **/
        List<Long> delIds = new ArrayList<>();
        // 新增输出、输入参数集合声明 suffix Add 新增的参数 suffix Req 请求体中的参数
        List<DeviceServicesParamsUpdateDTO> collectOutAdd = new ArrayList<>();
        List<DeviceServicesParamsUpdateDTO> collectInAdd = new ArrayList<>();
        List<DeviceServicesParamsUpdateDTO> outParamsReq = updateDTO.getOutputParams();
        List<DeviceServicesParamsUpdateDTO> inParamsReq = updateDTO.getInputParams();
        List<Long> outUpdateIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(outParamsReq)) {
            Set<String> outIdentifiers = outParamsReq.stream().map(DeviceServicesParamsUpdateDTO::getIdentifier).collect(Collectors.toSet());

            identifierSet.addAll(outIdentifiers);
            // 请求参数信息
            // A.a、 需要新增的请求参数集合
            collectOutAdd = outParamsReq.stream().filter(out -> out.getId() == null).collect(Collectors.toList());
            log.error("=====> collectOutAdd.size() = {}", collectOutAdd.size());
            // A.b、 需要更新的请求参数集合
            List<DeviceServicesParamsUpdateDTO> requestNeedUpdateDTOs = outParamsReq.stream().filter(input -> input.getId() != null).collect(Collectors.toList());
            outUpdateIds = requestNeedUpdateDTOs.stream().map(DeviceServicesParamsUpdateDTO::getId).collect(Collectors.toList());
//            outUpdateIds = outParamsReq.stream().filter(input -> input.getId() != null).map(DeviceServicesParamsUpdateDTO::getId).collect(Collectors.toList());
//             outParams.removeAll(requestOutputVOSAdd);requestOutputVOSUpdate = outParams;
//             编辑前的记录信息
//            List<DeviceServicesParamsVO> srcOutputVOS = productServicesParamsVOS.stream().filter(input -> input.getType().equals(1)).collect(Collectors.toList());
//            List<Long> srcOutputVOSIds = srcOutputVOS.stream().filter(inId -> inId.getId() != null).map(DeviceServicesParamsVO::getId).collect(Collectors.toList());

            /** 输出参数交集(数据库和请求参数的交集) ——> 需要更新的记录的 id 集合 **/
            List<Long> outIdsIntersection = getIntersection(srcOutIdsDB, outUpdateIds);
            if (CollectionUtils.isEmpty(outIdsIntersection)) {
                // 不保留任何服务的参数记录,此时的操作是原事件只有一个参数
                log.info("编辑时仅有的一个参数删除了... outIdsIntersection = {}", outIdsIntersection);
                delIds.addAll(srcOutIdsDB);
            } else {
                // 输出参数:原记录的差集、批量删除
                if (srcOutIdsDB.removeAll(outIdsIntersection)) {
                    log.info("删除集合添加A:deleteIds = {}", srcOutIdsDB);
                    delIds.addAll(srcOutIdsDB);
                }
            }

            // 交集 ——> 批量更新 (输出参数)
            List<DeviceServicesParamsEntity> outParams = new ArrayList();
            outParams = dealDeviceServiceParam4Update(refId, requestNeedUpdateDTOs, ServiceParamTypeEnum.ParamType.OUT_PARAM.getCode());
            paramsUpdateDTOs.addAll(outParams);

        } else {
            log.info("更新服务时,输出参数为空,删除id集合添加数据库中所有的输出参数id srcOutIdsDB = {}", srcOutIdsDB);
            delIds.addAll(srcOutIdsDB);
        }


        if (CollectionUtils.isNotEmpty(inParamsReq)) {
            Set<String> inParamsSet = inParamsReq.stream().map(DeviceServicesParamsUpdateDTO::getIdentifier).collect(Collectors.toSet());

            identifierSet.addAll(inParamsSet);
            // 请求参数信息
            // A.a、 需要新增的请求参数集合
            collectInAdd = inParamsReq.stream().filter(input -> input.getId() == null).collect(Collectors.toList());

            log.error("=====> collectInAdd.size() = {}", collectInAdd.size());
            // A.b、 需要更新的请求参数集合
            List<DeviceServicesParamsUpdateDTO> requestInputVOSUpdate = inParamsReq.stream().filter(input -> input.getId() != null).collect(Collectors.toList());
            // List<Long> inUpdateIds = requestInputVOSUpdate.stream().map(DeviceServicesParamsUpdateDTO::getId).collect(Collectors.toList());
            // outParams.removeAll(requestOutputVOSAdd);requestOutputVOSUpdate = outParams;
            List<Long> inUpdateIds = new ArrayList<>(requestInputVOSUpdate.size());
            log.error("输入参数要更新的请求集合的大小:{}", inUpdateIds.size());
            requestInputVOSUpdate.forEach(requestIn -> {
                inUpdateIds.add(requestIn.getId());
            });
            // 交集 ——> 需要更新的记录的 id 集合
            List<Long> inIdsIntersection = getIntersection(srcInIdsDB, inUpdateIds);

            // 原记录的差集添加到删除集合中
            if (CollectionUtils.isEmpty(inIdsIntersection)) {
                // 不保留任何服务的参数记录,此时的操作是原事件只有一个参数
                log.info("编辑时仅有的一个参数删除了... inIdsIntersection = {}", inIdsIntersection);
                delIds.addAll(srcInIdsDB);
            } else {
                if (srcInIdsDB.removeAll(inIdsIntersection)) {
                    log.info("服务更新,输入参数需要删除的id集合, ids = {}", srcInIdsDB);
                    delIds.addAll(srcInIdsDB);
                }
            }

            // 交集 ——> 批量更新(输入参数)

            paramsUpdateDTOs.addAll(dealDeviceServiceParam4Update(refId, requestInputVOSUpdate, ServiceParamTypeEnum.ParamType.IN_PARAM.getCode()));

        } else {
            log.error("删除集合添加D:srcOutIds = {}", srcInIdsDB);
            delIds.addAll(srcInIdsDB);
        }
        if (identifierSet.size() != (inParamsReq.size() + outParamsReq.size())) {
            log.error("请求参数identifier集合不满足条件");
            return ResultDTO.failInvalidParamWithMsg("参数异常,标识符");
        }
        boolean updateParamFlag = false;
        if (CollectionUtils.isNotEmpty(paramsUpdateDTOs)) {
            int res = productServicesParamsDao.updateBatch(paramsUpdateDTOs);
            if (res > 0) {
                updateParamFlag = true;
            }
        }

        log.info("===> update DeviceService: del list : " + delIds +
                "\n" + "输入参数: " + collectInAdd + "\n" + "输出参数: " + collectOutAdd);
        // 批量删除数据记录服务的参数记录
        boolean delParamFlag = false;
        if (CollectionUtils.isNotEmpty(delIds)) {
            delParamFlag = true;
            productServicesParamsDao.deleteByIdList(delIds);
        }
        // 处理新增
        DeviceServicesParamsEntity refMaxByRefIdDesc = productServicesParamsDao.selectRefMaxByRefIdDesc(refId);
        int maxRef = refMaxByRefIdDesc == null ? 1 : refMaxByRefIdDesc.getRef() + 1;
        List<DeviceServicesParamsEntity> outputParamsEntities = dealBatchEditAddParam4DeviceService(entity, collectOutAdd, 1, maxRef);
        maxRef = maxRef + outputParamsEntities.size();
        List<DeviceServicesParamsEntity> inputParamsEntities = dealBatchEditAddParam4DeviceService(entity, collectInAdd, 0, maxRef);
        List<DeviceServicesParamsEntity> editAddEntities = new ArrayList<>();
        editAddEntities.addAll(outputParamsEntities);
        editAddEntities.addAll(inputParamsEntities);
        boolean insertParamFlag = false;
        if (CollectionUtils.isNotEmpty(editAddEntities)) {
            insertParamFlag = true;
            productServicesParamsDao.insertBatch(editAddEntities);
        }
        if (delParamFlag || updateParamFlag || insertParamFlag) {
            entity.setUpdateTime(new Date( ));
            log.info("===>产品类别关联的参数有变化,同步更新类别服务");
            updateServiceRet = productServicesDao.updateById(entity);
        } else {
            updateServiceRet = productServicesDao.updateById(entity);
            log.info("===>产品类类别服务更新结果 {}", updateServiceRet);
        }
        if (updateServiceRet > 0 || delParamFlag || insertParamFlag || updateParamFlag) {
            int result = productsService.updateDeviceUpdateTime(productId);
            if (result < 1) {
                log.error("服务更新,联动修改失败,productId = {}", productId);
                throw new BusinessException("联动更新失败,数据状态不符合或者不存在");
            }
        }

        return ResultDTO.succ();
    }

同一事务中增删改查以及嵌套级联更新业务风险:

缺点:高并发场景中,性能不佳!

优化:优化拆分将长事务划分成子事务,查询放在事务外,不相干的代码放在事务外!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值