我正在将SpringBoot 2.1.10和SpringData与MongoDB 3.6.2一起使用
我有一个@Service
类,具有以下用于保留通用凭单凭证的业务逻辑:
public Voucher reserveVoucher() {
Voucher voucherToReserve = voucherRepository.findFirstByStatusEquals(VoucherStatus.ACTIVE)
.orElseThrow(() -> new BadRequestException("VOUCHER_NOT_FOUND", "Voucher with status ACTIVE not found"));
voucherToBeConsume.setStatus(VoucherStatus.RESERVED);
voucherToBeConsume.setUserId(voucherConsumer.getUserId());
return voucherRepository.save(voucherToBeConsume);
}
我知道Spring中的@Service
类默认为Singleton
。如果findFirstByStatusEquals
方法检索相同的文档并且在save
方法执行两次之后,在服务器数量更多的环境中会发生什么情况?文档已更新两次或第二次更新失败?
在MongoDB中,您不能在事务数据库中使用像SELECT ... FOR UPDATE这样的行锁。因此,根据您的情况,该文档可能会更新两次。
但是您可以通过条件更新来模拟它:
UpdateResult updateResult = mongoTemplate.updateFirst(
query(
where("_id").is(voucherToReserve.getId())
.and("status").is(VoucherStatus.ACTIVE)
),
new Update()
.set("status", VoucherStatus.RESERVED)
.set("userId", userId),
Voucher.class
);
if(updateResult.getModifiedCount() != 1){
throw ...
}
另请参阅https://www.mongodb.com/blog/post/how-to-select--for-update-inside-mongodb-transactions