事务回滚函数的设计-记一次深夜写代码的经历

事务回滚函数的设计

大二某个深夜使用反射写了一个事务回滚函数解决生成预订单过程中可能失败需要回退库存、优惠券的问题。
20年写的,躺在草稿中至今才想起。。。

事务回滚类设计:

1.RollBack类

@Slf4j
public class RollBack {
    private static final String METHOD_SUFFIX="RollBack";
    private  Stack<ObjMethod> methodStack =new Stack<>();
    private  Stack<Object> objStack=new Stack<>();
    public  void pushMethod(Object obj,String method,Object... params) throws Exception {
        Class[] classes=new Class[params.length];//参数类型列表
        int i=0;
        for (Object param : params) {
            classes[i++]=param.getClass();
        }
        Method m= obj.getClass().getDeclaredMethod(method+METHOD_SUFFIX,classes);//获取该方法对应的RollBack方法
        ObjMethod objMethod=new ObjMethod(m,params);
        objStack.push(obj);
        methodStack.push(objMethod);
    }
    public  void popMethod(){
        methodStack.pop();
        objStack.pop();
    }
    public  void rollBack() throws Exception{
        if(!methodStack.isEmpty()) popMethod();//最后一次事务未成功执行,无需回滚

      while(!methodStack.isEmpty()){
         ObjMethod objMethod= methodStack.pop();
         Object obj=objStack.pop();
         objMethod.getMethod().invoke(obj,objMethod.getParams());
         log.info("Call "+objMethod.getMethod().getName());
      }
    }




}

2.ObjMethod

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ObjMethod {
    private Method method;
    private Object[] params;

}
Demo

1.确认订单业务

  public Result confirmOrder(Order order) {
            RollBack RollBack=new RollBack();//必选建立局部变量
           
            //1. 校验订单
            Result result = checkOrder.checkOrder(order);
            if(result != null)  return result;
            log.info("订单校验通过.");
            //2. 生成预订单
            result = savePreOrder.savePreOrder(order);
            if(result != null)
            log.info("成功生成预订单.。。");
            
        try {
            boolean res;
            //3.扣减库存
            res=goodsService.reduceGoodsNum(order.getGoodsId(),order.getGoodsNumber());
            RollBack.pushMethod(goodsService,"reduceGoodsNum",order.getGoodsId(),order.getGoodsNumber());
            if(!res) throw new ShopException(ShopCode.SHOP_GOODS_NO_Exist,"库存不足");
            log.info("成功扣减库存.");

            //4.扣减优惠券
           res=couponService.setUsedStatus(order.getUserId());
            RollBack.pushMethod(couponService,"setUsedStatus",order.getUserId());
           if(!res) throw new ShopException(ShopCode.SHOP_COUPON_NO_Exist,"优惠券不够");
            log.info("扣减优惠券成功");

            //5.使用余额
           res= userService.reduceMoney(order.getUserId(),order.getOrderAmount());
            RollBack.pushMethod(userService,"reduceMoney",order.getUserId(),order.getOrderAmount());
            if(!res) throw new ShopException(ShopCode.SHOP_USER_INSUFFICIENT_BALANCE,"余额不足");
            log.info("扣余额");

            //6.确认订单
            order.setOrderStatus(STATUS_COMFIRM);
            orderDao.update(order,null);


        } catch (ShopException e) {

            //1.确认订单失败,发送回滚指令
            try {
                RollBack.rollBack();
            } catch (Exception ex) {ex.printStackTrace();}

            //2.返回失败状态
            return new Result(e.getCode(),e.getMessage());
        }catch(Exception e){ return new Result(ShopCode.SHOP_ERROR,"Server Error");}

        //7.返回成功状态
        return new Result(ShopCode.SHOP_ORDER_NORMAL, "success.", order);
    }

2.IGoodsService

@Slf4j
@Component
@DubboService(interfaceClass = IGoodsService.class)
public class GoodsServiceImpl implements IGoodsService {

    @Resource
    private GoodsDao goodsDao;

    @Override
    public Goods selectGoodsById(Integer goodsId) {
        return goodsDao.selectById(goodsId);
    }

    @Override
    public boolean reduceGoodsNum(Integer goodsId,Integer num) {
        if(selectGoodsById(goodsId).getGoodsNumber()<num) return false;
        goodsDao.reduceGoodsNum(goodsId,num);
        return true;
    }
    @Override
    public void reduceGoodsNumRollBack(Integer goodsId,Integer num){
        goodsDao.reduceGoodsNum(goodsId,-num);

    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值