ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringBoot中事务(@Transactional)与try{}catch(){}finally{}之间存在的问题

2021-11-12 19:03:44  阅读:324  来源: 互联网

标签:dto SpringBoot Transactional buyService longValue getId try finally user


前言:

本次问题发生在用户出售下单过程中,出现了并发操作,导致同一个产品出现了过量销售(本来只卖10台结果买了12台),在出售方法中已经加了事物(@Transactional)注解,并且方法内部使用了Redis分布式锁做了防并发操作

问题代码:

public TradeResult<String> add(StartSaleOrderDTO dto, TUser user) throws Exception {

  //TODO 先进行加锁操作,防止数据发生并发
  boolean lock = buyService.lockNoExpire(dto.getId().longValue());
  LogUtil.info("出售订单进行加锁操作,订单号:[{}],返回状态:[{}],投放用户:[{}]",dto.getId(),lock,user);
  if (!lock){
  LogUtil.info("当前订单有人在正在出售,请稍后再试,入参:[{}],投放用户:[{}]",dto,user);
    return TradeResult.error(TradeResultEnum.DEFAULT_EXE,"当前订单有人在正在出售,请稍后再试");
  }
  buy = buyService.getOne(queryWrapper);

  try{
    //内部逻辑

    //解锁
    buyService.unlock(dto.getId().longValue());

    return TradeResult.success("创建成功");
  }catch (Exception ex){
    LogUtil.info("当前订单出售异常,入参:[{}],投放用户:[{}],异常原因:[{}]",dto,user,ex.toString());
    buyService.unlock(dto.getId().longValue());
    throw new Exception("出售失败,请稍后再试!");
  }finally {
    //解锁操作
    buyService.unlock(dto.getId().longValue());
  }
}

问题:

为什么做了防并发和事物之后依然出现了并发操作。

发生原因:

经过对代码逻辑的梳理和测试最终发现问题出现在finally方法上,因为事务是作用于整个方法,会先执行finally后在执行提交事物操作,当finall执行完成后锁已经被释放了,然而此时事物还未提交,恰好此时有一个用户提交了订单,导致获取的数据还是事务未提交之前的数据,结果就导致了同一个订单被过量销售的问题

 

解决方案:

去掉finally

 

标签:dto,SpringBoot,Transactional,buyService,longValue,getId,try,finally,user
来源: https://www.cnblogs.com/wutongTree/p/15545966.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有