微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Spring嵌套事务​​最佳实践

如何解决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 举报,一经查实,本站将立刻删除。