Spring嵌套事务​​最佳实践

问题描述

我的情况是,我需要 orderService.createOrder() 方法和内部 walletService.reduceBalance() 方法。我希望 orderService.createOrder() 方法具有 READ_COMMITED 隔离级别,而 walletService.reduceBalance() 具有 REPEATABLE_READ 隔离级别。

但是,据我了解,因为 walletService.reduceBalance()orderService.createOrder() 内部,尽管有注释,它仍将具有 READ_COMMITED 隔离(因为这一切都发生在单个物理事务中)。

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() REPEATABLE_READ。但在这种情况下,它会减慢应用程序的速度,因为该方法读取了大量数据,而 REPEATABLE_READ 会对这些数据加锁。

public class OrderService {

  private WalletService walletService;
  
  @Transactional(isolation = Isolation.REPEATABLE_READ)
  public void createOrder(Long userId) {
    //some order creation,BigDecimal amount) {
   Wallet wallet = walletRepository.getById(userId);
   wallet.setBalance(wallet.getBalance().substract(amount);
  }

}

第二种解决方是使 walletService.reduceBalance() propogation=REQUIRES_NEW 将创建具有正确隔离级别的单独物理事务。但在这种情况下,如果 walletService.reduceBalance() 已提交事务且稍后在 orderService.createOrder() 中发生异常,则订单创建将回滚并仍会提交 reduce balance。

public class OrderService {

  private WalletService walletService;
  
  @Transactional
  public void createOrder(Long userId) {
    //some order creation,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);
  }

}

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

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)