【问题标题】:@Transactional. What if two users make checkout from cart at the same time@事务。如果两个用户同时从购物车结帐怎么办
【发布时间】:2021-12-12 21:20:13
【问题描述】:

如何避免两个用户同时结账,但没有足够的产品供他们使用? 用户有一篮子商品,结账时,店内商品数量应减少

@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
    public boolean createOrder(User user) {
        if (!cartRecordService.checkAvailable()) {
            return false;
        }

        final Map<Long, Long> records = cartRecords.getRecords();
        Long sum = 0L;
        for (Long id : records.keySet()) {
            Goods goods = goodsRepository.findById(id).get();
            sum += goods.getPrice() * records.get(id);
        }
        Date dateNow = new Date();
        Order order = new Order(dateNow, sum, true, user);
        orderRepository.save(order);

        Order lastUsersOrder = orderRepository.findByUserOrderByIdDesc(user).get(0);
        for (Long id : records.keySet()) {
            Goods goods = goodsRepository.findById(id).get();
            goods.setAvailable(goods.getAvailable() - records.get(id));
            goodsRepository.save(goods);

            addOrderGoods(new OrderGoods(goods, lastUsersOrder, records.get(id)));
        }
        return true;
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void addOrderGoods(OrderGoods orderGoods){
        orderGoodsRepository.save(orderGoods);
    }

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
public boolean enoughQuantity(CartAdditionDTO cartAdditionDTO){
    Long available = goodsRepository.getById(cartAdditionDTO.getId()).getAvailable();
    return available >= cartAdditionDTO.getQuantity();
}
@Transactional(propagation = Propagation.MANDATORY, isolation = Isolation.READ_COMMITTED)
public boolean checkAvailable(){
    final Map<Long, Long> records = cartRecords.getRecords();
    for(Long id : records.keySet()){
        if(!goodsService.enoughQuantity(new CartAdditionDTO(id, records.get(id)))){
            return false;
        }
    }
    return true;
}

试图对事务的隔离做一些事情,但它不起作用

【问题讨论】:

  • 您需要执行 SELECT ... FOR UPDATE 的 ORM 等效项来锁定行,直到其中一个事务完成。仅使用REPEATABLE READ 事务隔离级别(InnoDB 默认)是不够的。

标签: java database multithreading spring-boot transactions


【解决方案1】:

假设 可用项目 = 1, 然后如您的问题中所述,如果两个用户同时签出 那么最后剩下的金额会转到-1,此时检查第一个用户,可用项目为0,即第一个用户(检查他们退房的时间)和将物品分配给他,并在结帐时告诉其他人所选的物品不可用,并告诉他们要么删除然后结帐,要么选择任何其他然后继续。

注意:结账时间也应包含纳秒,以获取准确的结账用户。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-09
    • 2020-04-23
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    • 2014-01-16
    • 1970-01-01
    相关资源
    最近更新 更多