栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

@Transactional事务未提交导致的并发问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

@Transactional事务未提交导致的并发问题

1、以下代码存在并发问题,原因是@Transactional开启事务后,执行完createOrder()方法后已经释放锁了,但是事务还没提交,此时另外一个线程获取到锁开始执行createOrder方法导致的

public class ChaoMaiConcurrencyService {

    public static final int purchaseProductId = 1;

    public static final int purchaseProductNum =1;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Transactional(rollbackFor = Exception.class)
    public synchronized Integer createOrder() throws Exception {
        Product product = productMapper.selectByPrimaryKey(purchaseProductId);

        if (product == null) {
            throw new Exception("购买商品:"+purchaseProductId+"不存在");
        }

        Integer currentCount = product.getCount();
        //校验库存
        if (purchaseProductNum > currentCount) {
            throw new Exception("商品"+purchaseProductId+"仅剩"+currentCount+"件,无法购买");
        }
        //更新库存
        productMapper.updateProductCount(purchaseProductNum,product.getId());

        //新增订单
        Order order = new Order();
        order.setOrderAmount(product.getPrice().multiply(new BigDecimal(purchaseProductNum)));
        order.setOrderStatus(1);
        order.setReceiverName("xxx");
        orderMapper.insertSelective(order);

        //新增订单明细
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(order.getId());
        orderItem.setProductId(product.getId());
        orderItem.setPurchasePrice(product.getPrice());
        orderItem.setPurchaseNum(purchaseProductNum);
        orderItemMapper.insertSelective(orderItem);

        return order.getId();
    }
}

测试类代码:
@RunWith(SpringRunner.class)
@SpringBootTest
public class ChaoMaiConcurrencyTest {

    @Autowired
    private ChaoMaiConcurrencyService chaoMaiConcurrencyService;

    @Test
    public void testChaoMai() throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(5);
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5);

        ExecutorService es = Executors.newFixedThreadPool(5);
        for (int i=0;i<5;i++) {
            es.execute(()->{
               try {
                   cyclicBarrier.await();
                   Integer orderId = chaoMaiConcurrencyService.createOrder();
                   System.out.println("订单id:"+orderId);
               } catch (Exception e) {
                   e.printStackTrace();
               } finally {
                   cdl.countDown();
               }
            });
        }
    }

}

2、解决方案:不使用@Transactional注解,注入PlatformTransactionManager和TransactionDefinition来手动提交事务
代码如下:
public class ChaoMaiConcurrencyService {

    public static final int purchaseProductId = 1;

    public static final int purchaseProductNum =1;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;
    
    public synchronized Integer createOrder() throws Exception {
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        Product product = productMapper.selectByPrimaryKey(purchaseProductId);

        if (product == null) {
            //手动回滚
            platformTransactionManager.rollback(transaction);
            throw new Exception("购买商品:"+purchaseProductId+"不存在");
        }

        Integer currentCount = product.getCount();
        //校验库存
        if (purchaseProductNum > currentCount) {
            //手动回滚
            platformTransactionManager.rollback(transaction);
            throw new Exception("商品"+purchaseProductId+"仅剩"+currentCount+"件,无法购买");
        }
        //更新库存
        productMapper.updateProductCount(purchaseProductNum,product.getId());

        //新增订单
        Order order = new Order();
        order.setOrderAmount(product.getPrice().multiply(new BigDecimal(purchaseProductNum)));
        order.setOrderStatus(1);
        order.setReceiverName("xxx");
        orderMapper.insertSelective(order);

        //新增订单明细
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(order.getId());
        orderItem.setProductId(product.getId());
        orderItem.setPurchasePrice(product.getPrice());
        orderItem.setPurchaseNum(purchaseProductNum);
        orderItemMapper.insertSelective(orderItem);

        //手动提交
        platformTransactionManager.commit(transaction);
        
        return order.getId();
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/310089.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号