I have a service method where I request an entity by ID from the database. If the entity has the attribute paid == false
, I set it to true and do something. If paid==true
it just returns.
@Override
@Transactional(rollbackFor={ServiceException.class})
public void handleIntentSucceeded(PaymentIntent intent) throws ServiceException {
LOGGER.trace("handleIntentSucceeded({})", intent);
CreditCharge charge = transactionRepository.findByPaymentIntentId(intent.getId());
if(charge.getPaid()) {
return;
// do some stuff
charge.setPaid(true);
transactionRepository.save(charge);
}
Now if there are multiple requests with the same intent
at the same time, this method would no longer be consistent because, for example, the first request receives the charge
with paid==false
, so it does "some things" and if the second request comes to this method before the first request has saved the charge with paid==true
, it would also do "some things" even if the first request already does so. Is this a correct conclusion?
To be sure that only one request can process this method at a time, to avoid "some things" being done multiple times, I could set the Transactional to @Transactional(isolation = Isolation.SERIALIZABLE)
. This way any request can process this method/transaction only if the request has committed the Transactional before.
Is this the best approach or is there a better way?