我正在学习Spring JPA和Hibernate。所以我遇到了一个问题。
我有此方法
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void sendMoney(Long from, Long to, Double amount) {
WalletEntity fromWallet = walletServiceImpl.getWallet(from);
WalletEntity toWallet = walletServiceImpl.getWallet(to);
fromWallet.setAmount(fromWallet.getAmount() - amount);
toWallet.setAmount(toWallet.getAmount() + amount);
TransactionEntity transaction = new TransactionEntity();
transaction.setAmount(amount);
transaction.setToWallet(toWallet);
transaction.setFromWallet(fromWallet);
transactionRepository.saveAndFlush(transaction);
}
我想对其进行测试并创建它:
@GetMapping("/send")
public void sendMoney() {
ExecutorService executorService = Executors.newFixedThreadPool(20);
for (int i = 0; i < 100; i++) {
executorService.execute(() -> {
accountServiceImpl.sendMoney(1L, 2L, 10D);
});
}
}
因此,当我阅读钱包时,我得到了旧值,但我赚了Isolation.REPEATABLE_READ
。数据库中的值当然是错误的。
你能解释出什么问题吗?谢谢!
答案 0 :(得分:0)
隔离级别REPTEABLE_READ按预期工作。
您可以在这里得到很好的解释:
Spring @Transactional - isolation, propagation
但是为了澄清,这是发生了什么:
Tx1 Tx2
| |
Tx1 Read Wallet 1 100 |
Tx2 Read Wallet 1 | 100
Tx1 Discounts 10 100-10 |
Tx2 Discounts 10 | 100-10
Tx1 Commits | |
Tx2 Commits | |
Tx1 Read Wallet 1 90 |
Tx2 Read Wallet 2 | 90
因此,为了控制此行为,您有两个选择:
您可以在此处开始查看乐观锁定:Optimistic locking in JPA how does it work?