代码评审总结

今天代码评审,提出了几个问题。

 

1. jdk8 stream的使用。

我有一个代码是这么写的:

 List<PtStorageDetail> details = ptStorageDetailDao.getDetails(ptStorageOrder.getId());

        List<PtStorageDetailVO> detailVOS = Lists.newArrayList();
        details.stream().forEach(o-> {
            PtStorageDetailVO storageDetailVO = new PtStorageDetailVO();
            BeanUtils.copyProperties(o, storageDetailVO);
            SkuBO skuBO = SkuUtil.get(o.getSkuId());
            if(null != skuBO){
                storageDetailVO.setSkuName(skuBO.getSkuName());
            }
            UnitBO unit = UnitUtil.get(o.getUnitId());
            if (null != unit) {
                storageDetailVO.setUnitName(unit.getName());
            }
            storageDetailVO.setSkuCode(storageDetailVO.getSkuNo());
            detailVOS.add(storageDetailVO);
        });

 

有个同学指出来,可以使用stream的map方式,简便效率又高。

List<PtStorageDetailVO> detailVOS = details.stream().map(o -> {
			PtStorageDetailVO storageDetailVO = new PtStorageDetailVO();
			BeanUtils.copyProperties(o, storageDetailVO);
			SkuBO skuBO = SkuUtil.get(o.getSkuId());
			if(null != skuBO){
				storageDetailVO.setSkuName(skuBO.getSkuName());
			}
			UnitBO unit = UnitUtil.get(o.getUnitId());
			if (null != unit) {
				storageDetailVO.setUnitName(unit.getName());
			}
			storageDetailVO.setSkuCode(storageDetailVO.getSkuNo());
			return storageDetailVO;
		}).collect(Collectors.toList());

2. 关于BigDecimal整除的判断。

业务场景,如果能整除,就换算成二级单位。假设100瓶,10瓶/箱,显示10箱。

假设99瓶,10瓶/箱,不能整除,不换算,直接显示99瓶。

我是通过抛异常的方式进行判断整除的:

  BigDecimal applyStoreRate = null;
         
            try {
                applyStoreRate = warehouseInventoryVO.getApplyStore().divide(secondUnitSku.getRelationship(), 0, BigDecimal.ROUND_UNNECESSARY);
            } catch (ArithmeticException e) {
                return;
            }
            warehouseInventoryVO.setUnitId(secondUnitSku.getUnitId());
            UnitBO unitBO = UnitUtil.get(secondUnitSku.getUnitId());
            warehouseInventoryVO.setUnitName(unitBO.getName());
           
            warehouseInventoryVO.setApplyStore(applyStoreRate);

现在改成工具类:

 if(MathUtil.isInteger(warehouseInventoryVO.getApplyStore().divide(secondUnitSku.getRelationship(), 10, BigDecimal.ROUND_HALF_DOWN))) {
                applyStoreRate = warehouseInventoryVO.getApplyStore().divide(secondUnitSku.getRelationship());

                warehouseInventoryVO.setUnitId(secondUnitSku.getUnitId());
                UnitBO unitBO = UnitUtil.get(secondUnitSku.getUnitId());
                warehouseInventoryVO.setUnitName(unitBO.getName());
            }

 

//判断是否为整数 
public static boolean isInteger(BigDecimal number) {
        if (new BigDecimal(number.intValue()).compareTo(number) == 0) {
            return true;
        }
        return false;
    }

3. 编辑/同步订单时候,分布式锁放在最前面。我之前是放在后面。

分布式锁防止高并发。

正确方式:

public BaseResultVo syncToOms(Long id) throws BaseException {
		boolean hasLock = distributedLocker.tryLock(String.valueOf(LockTypeEnum.STORAGE_SYNC_OMS.getCode()) + id, TimeUnit.SECONDS,5,6);
		//获得分布式锁
		if(!hasLock){
			return BaseResultVo.error(MessageConstants.SysExceptionMsg.SYS_BUSY);
		}
		PtStorageOrder ptStorageOrder = ptStorageOrderDao.selectById(id);
		if (Objects.isNull(ptStorageOrder)) {
			return BaseResultVo.error("无入库单信息");
		}
		if (!OrderEnum.StorageOrderStatusEnum.wait_receive.getId().equals(ptStorageOrder.getStatus())) {
			return BaseResultVo.error("非待接单订单不能下单");
		}

		//生成wms同步DTO
		ReceiveOrderPortalDTO receiveOrderPortalDTO = new ReceiveOrderPortalDTO();
		receiveOrderPortalDTO.setActionType("ADD");
		receiveOrderPortalDTO.setCustomerOrderNo(ptStorageOrder.getStorageNo());
		receiveOrderPortalDTO.setExpectReceiveDate(ptStorageOrder.getExpectReceiveDate());
		receiveOrderPortalDTO.setOwnerCode(CustomerUtil.get(LoginUserUtil.getLoginUser().getCustomerId()).getCode());
		receiveOrderPortalDTO.setCompanyId(ptStorageOrder.getCompanyId());
		receiveOrderPortalDTO.setStoreId(ptStorageOrder.getWarehouseId());
		receiveOrderPortalDTO.setOwnerId(ptStorageOrder.getCustomerId());
		receiveOrderPortalDTO.setReceiveMethod(ptStorageOrder.getReachType());
		receiveOrderPortalDTO.setRemark(ptStorageOrder.getRemark());
		receiveOrderPortalDTO.setSenderContactName(ptStorageOrder.getContactName());
		receiveOrderPortalDTO.setSenderPhone(ptStorageOrder.getContactPhone());
		receiveOrderPortalDTO.setType(ptStorageOrder.getType());
		receiveOrderPortalDTO.setOrderTime(ptStorageOrder.getOrderTime());

        List<PtStorageDetail> details = ptStorageDetailDao.getDetails(id);
		List<ReceiveOrderDetailPortalDTO> detailList = details.stream().map(detail -> {
			ReceiveOrderDetailPortalDTO detailPortalDTO = new ReceiveOrderDetailPortalDTO();
			detailPortalDTO.setNumber(detail.getGoodsAmount().intValue());
			SkuBO skuBO = SkuUtil.get(detail.getSkuId());
			if(!Objects.isNull(skuBO)){
				detailPortalDTO.setSkuName(skuBO.getSkuName());
			}

			UnitBO unitBO = UnitUtil.get(detail.getUnitId());
			if(!Objects.isNull(unitBO)){
				detailPortalDTO.setPackageUnit(unitBO.getName());
			}

            detailPortalDTO.setSkuCode(detail.getSkuNo());
            detailPortalDTO.setSkuId(detail.getSkuId());
            detailPortalDTO.setUnitId(detail.getUnitId());
            return detailPortalDTO;
		}).collect(Collectors.toList());
		receiveOrderPortalDTO.setDetailList(detailList);

        //通知oms接单
        MqDTO mqDTO = new MqDTO();
        mqDTO.setMqTypeEnum(STORAGE_PORTAL_TO_OMS);
        mqDTO.setData(JSONObject.toJSONString(receiveOrderPortalDTO));

        if (!mqProducerApi.producer(mqDTO)){
			distributedLocker.unlock(String.valueOf(LockTypeEnum.STORAGE_SYNC_OMS.getCode()) + id);
            throw new BaseException("oms入库单接单失败");
        }
        int count = ptStorageOrderDao.updateStatus(ptStorageOrder.getId(), OrderEnum.StorageOrderStatusEnum.order_pushed.getId(),
                LoginUserUtil.getLoginUser().getId());
		distributedLocker.unlock(String.valueOf(LockTypeEnum.STORAGE_SYNC_OMS.getCode()) + id);
        if (count > 0) {
            return BaseResultVo.success();
        }
        return BaseResultVo.error();
	}

4. 要加事务控制

捕获异常,处理。

打印日志,切记切记。    log.error("outbound_portal_to_oms 接单失败", e);

并且要有异常栈信息,error显示。

@Override
    public BaseResultVo senderOrderForPortal(@RequestBody SenderOrderErpDTO dto) {
        try {
            return senderOrderService.senderOrderForERP(dto, null);
        } catch (Exception e) {
            log.error("outbound_portal_to_oms 接单失败", e);
            JSONObject json = new JSONObject();
            //接单失败
            json.put("state", OrderEnum.OutBoundOrderStatusEnum.fail_received.getId());
            json.put("customerOrderNo", dto.getCustomerOrderNo());
            json.put("updateUser", 0);
            BaseResultVo resultVo =  ptOutboundOrderApi.updateStatus(json.toJSONString());
            dingDingApi.sendDingMsgForService("outbound_portal_to_oms 接单失败, CustomerOrderNo ==> 【" + dto.getCustomerOrderNo() + "】", "15967103436");
            return BaseResultVo.error("系统异常");
        }
    }

 

加上事务:    @Transactional(rollbackFor = Exception.class),并且不能只单单加 @Transactional,而不去加哪种异常回滚。因为默认有RuntimeException才会回滚。

@Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultVo senderOrderForERP(SenderOrderErpDTO senderOrderErpDTO, String sign) {
        //参数校验
        validateParam(senderOrderErpDTO, sign);
        //生成发货单
        SenderOrder senderOrder = generateSenderOrder(senderOrderErpDTO);
        //生成发货单详情
        List<SenderOrderDetail> senderOrderDetailList = generateSenderOrderDetailList(senderOrder, senderOrderErpDTO);
        SendOrderMainDTO sendOrderMainDTO = generateSendOrderMainAddDTO(senderOrder, senderOrderDetailList);
        if ("ADD".equals(senderOrderErpDTO.getActionType())) {
            int count = senderOrderDao.add(senderOrder, senderOrderDetailList);
            if (0 >= count) {
                throw new BaseException("oms新增出库单失败");
            }
            //通知wms接单
            MqDTO mqDTO = new MqDTO();
            mqDTO.setMqTypeEnum(OUTBOUND__OMS_TO_WMS);
            mqDTO.setData(JSONObject.toJSONString(sendOrderMainDTO));
            mqDTO.setTimeOut(10);
            if (!mqProducerApi.produer(mqDTO)){
                throw new BaseException("oms推送出库单到wms失败");
            }
            //修改OMS发货单状态:已下发
            int update = senderOrderDao.updateStatus(senderOrder.getOrderNo(), OmsOrderStateEnum.SEND.getCode(), 0L);
            if (update <=0 ) {
                throw new BaseException("修改OMS发货单状态:已下发失败");
            }
        } else if ("UPDATE".equals(senderOrderErpDTO.getActionType())) {
            doUpdate(senderOrder, senderOrderErpDTO, senderOrderDetailList);
            updateToWmsAndOms(sendOrderMainDTO, null);
        }
        return BaseResultVo.success("oms推送出库单到wms成功");
    }

5. 错误示例

 @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseResultVo insert(SenderOrderDTO dto) {
        SenderOrder senderOrder = new SenderOrder();
        SenderOrderDetailDTO senderOrderDetailDTO = dto.getSenderOrderDetailDTO();
        SenderOrderDetail senderOrderDetail = new SenderOrderDetail();
        BeanUtils.copyProperties(dto, senderOrder);
        BeanUtils.copyProperties(senderOrderDetailDTO, senderOrderDetail);
        senderOrder.setOrderNo(OrderNoUtil.getOmsOrderSerialNo(OrderNoTypeEnum.SENDER_ORDER));
        int count = senderOrderDao.insertSelective(senderOrder);
        if (count > 0) {
           if(senderOrderDetailDao.insertSelective(senderOrderDetail) <= 0) {
               //直接返回,不抛异常,这样是错的,事务就不会回滚。
               return BaseResultVo.error();
           }
        }
        // 默认直接返回成功,也是不对。
        return BaseResultVo.success();
    }

以上代码两个错误点:

1)//直接返回,不抛异常,这样是错的,事务就不会回滚。

2)  // 默认直接返回成功,也是不对。需要根据结果进行返回。

6. 插入数据异常

一个环境单据导入到另一个环境。redis获取单号重复了。

private static String getSerial(OrderNoTypeEnum orderNoTypeEnum) {
        String key = RedisKeyEnum.SERIAL.getKey() + "_" + orderNoTypeEnum.getCode() + "_" + DateUtil.formatTimestampSimple();
        String no = RedisUtil.incr(key, (60 * 60 * 24) + 10) + "";
        if (no.length() == NO_LENGTH) {
            return no;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < NO_LENGTH - no.length(); i++) {
            sb.append("0");
        }
        sb.append(no);
        return sb.toString();
    }

 

public static Long incr(String key,Integer seconds) {
        Long rtn = null;
        if (key == null || "".equals(key)) {
            return rtn;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            rtn = jedis.incr(key);
            if (null == seconds) {
                jedis.expire(key, seconds);
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return rtn;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值