spring嵌套事务最佳实践

zujrkrfu  于 2021-07-22  发布在  Java
关注(0)|答案(0)|浏览(235)

我现在的处境,我需要 orderService.createOrder() 方法和内部 walletService.reduceBalance() 方法。我想要 orderService.createOrder() 方法读取指定的隔离级别和 walletService.reduceBalance() 具有可重复读取隔离级别。
然而,据我所知,因为 walletService.reduceBalance() 在里面 orderService.createOrder() ,它将读取提交的隔离,尽管有注解(因为它都发生在单个物理事务中)。

public class OrderService {

  private WalletService walletService;

  @Transactional
  public void createOrder(Long userId) {
    //some order creation, reads a lot of data
    walletService.reduceBalance(userId, orderPrice);
    //other operations
  }
}

public class WalletService {

  private WalletRepository walletRepository;

  @Transactional(isolation = Isolation.REPEATABLE_READ)
  public void reduceBalance(Long userId, BigDecimal amount) {
   Wallet wallet = walletRepository.getById(userId);
   wallet.setBalance(wallet.getBalance().substract(amount);
  }

}

第一个解决办法是 orderService.createOrder() 可重复读取。但在这种情况下,它会减慢应用程序的速度,因为该方法会读取大量数据,而可重复读取会锁定这些数据。

public class OrderService {

  private WalletService walletService;

  @Transactional(isolation = Isolation.REPEATABLE_READ)
  public void createOrder(Long userId) {
    //some order creation, reads a lot of data
    walletService.reduceBalance(userId, orderPrice);
    //other operations
  }
}

public class WalletService {

  private WalletRepository walletRepository;

  @Transactional(isolation = Isolation.REPEATABLE_READ)
  public void reduceBalance(Long userId, BigDecimal amount) {
   Wallet wallet = walletRepository.getById(userId);
   wallet.setBalance(wallet.getBalance().substract(amount);
  }

}

第二个解决办法是 walletService.reduceBalance() propogation=需要\u new,这将创建具有正确隔离级别的单独物理事务。但在这种情况下,如果 walletService.reduceBalance() 委托交易 orderService.createOrder() 发生异常,订单创建将回滚,减少余额仍将提交。

public class OrderService {

  private WalletService walletService;

  @Transactional
  public void createOrder(Long userId) {
    //some order creation, reads a lot of data
    walletService.reduceBalance(userId, orderPrice);
    //other operations
  }
}

public class WalletService {

  private WalletRepository walletRepository;

  @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
  public void reduceBalance(Long userId, BigDecimal amount) {
   Wallet wallet = walletRepository.getById(userId);
   wallet.setBalance(wallet.getBalance().substract(amount);
  }

}

你能提出更好的方法来处理这种情况吗?

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题