问题描述
我的情况是,我需要 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 (将#修改为@)