我需要一些关于悲观实体锁定的帮助。我在我的应用程序中使用PostgreSQL和Spring数据JPA(引擎盖下的hibernate 5)。所以,我想展示一个我面临的任务。
我有一些有钱的用户帐户:
@lombok.Data //Used to generate getters and setters
@Entity
class AccountEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Long balance;
}
付款,允许将资金从一个帐户转移到另一个帐户
@lombok.Data
@Entity
class PaymentEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Long amount;
@OneToOne
@JoinColumn(name="account_from_id")
private AccountEntity accountFrom;
@OneToOne
@JoinColumn(name="account_to_id")
private AccountEntity accountTo;
}
两者的存储库:
interface AccountRepository extends JpaRepository<AccountEntity, Integer> {}
interface PaymentRepository extends JpaRepository<PaymentEntity, Integer> {}
进行汇款的服务:
interface PaymentService {
PaymentEntity create(PaymentEntity paymentEntity);
}
@Service
class PaymentServiceImpl implements PaymentService {
@Autowired
private AccountRepository accountRepository;
@Autowired
private PaymentRepository paymentRepository;
@Transactional
@Override
public PaymentEntity create(PaymentEntity payment) {
AccountEntity from = accountRepository.getOne(payment.getAccountFrom().getId()); //want to lock account here
AccountEntity to = accountRepository.getOne(payment.getAccountTo().getId()); //want to lock account here
Long newFromBalance = from.getBalance() - payment.getAmount();
Long newToBalance = to.getBalance() + payment.getAmount();
if (newFromBalance < 0)
throw new RuntimeException("Not enough money for payment");
from.setBalance(newFromBalance);
to.setBalance(newToBalance);
PaymentEntity result = paymentRepository.save(payment); //create payment
accountRepository.save(from); //update account
accountRepository.save(to); //update account
return result; //want to unlock both accounts here
}
}
所以,正如你从代码中看到的那样,我想锁定两个账户,这些账户涉及交易开始时的汇款(这将保证在交易提交之前它们都无法更改,每个新的付款将获得帐户的更新余额)。在交易结束时,我想解锁它们。
我已经阅读了documentation,正如我和我所理解的那样,为此我需要更新我的AccountRepository
:
interface AccountRepository extends JpaRepository<AccountEntity, Integer> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
AccountEntity save(AccountEntity account);
}
上述代码必须在交易开始时锁定from
和to
帐户,并在结束时自动解锁。但我还有一些问题:
@Lock(LockModeType.PESSIMISTIC_WRITE)
只能应用于存储库方法(不适用于服务方法)。不是吗?@Lock
将锁定事务中的所有实体,已执行select(在我的情况下为from
和to
个帐户)。不是吗?如果您提供官方文档或某些网站的链接,我将非常感谢,我可以自己发现这个主题。