我正在学习 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); }); }}所以当我阅读 wallet 时,我得到了旧的价值,但我做了Isolation.REPEATABLE_READ. 数据库中的值当然是错误的。你能解释一下有什么问题吗?谢谢!
1 回答
小怪兽爱吃肉
TA贡献1852条经验 获得超1个赞
隔离级别 REPTEABLE_READ 按预期工作。
你可以在这里得到一个很好的解释:
Spring @Transactional - 隔离、传播
但为了澄清,这是发生的事情:
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
因此,为了控制这种行为,您有两个选择:
使用阻塞操作的可序列化事务级别以便一一处理(这有性能损失)
实现乐观锁(第二个事务如果同时尝试修改同一个账户会抛出异常)
您可以从这里开始回顾乐观锁:JPA 中的乐观锁是如何工作的?
添加回答
举报
0/150
提交
取消