Ниже приведен метод транзакции, который извлекает существующую строку из базы данных и обновляет одно из значений ее столбца, а затем сохраняет обратно в базу данных:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public A updateTotalItem(String id, int newItemNum) {
A a = aRepository.findById(id).orElseThrow(() -> new IllegalArgumentException());
a.updateValues(newItemNum);
return aRepository.save(a);
}
И я применил блокировку PESSIMISTIC_WRITE
to aRepository.findById()
:
@Repository
public interface ARepository extends JpaRepository<A, String> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<A> findById(String id);
}
Однако я обнаружил, что при наличии двух одновременных вызовов вышеуказанного метода транзакции (с одним и тем же аргументом id
), даже если первая транзакция заблокирует обновление второй транзакции, но после первой зафиксированной транзакции вторая транзакция не будет извлекать строку с обновленными данными, вместо этого она все равно получит строку с данными до первой транзакции. Если я правильно понимаю блокировку PESSIMISTIC_WRITE
, она должна заблокировать строку / сущность для чтения / записи, но в этом случае похоже, что она блокирует только запись, я правильно понимаю? Если да, есть ли какой-нибудь подход, который я могу использовать для достижения эффекта блокировки строки / объекта для чтения / записи, чтобы предотвратить одновременное получение старых данных параллельными транзакциями?
PS: я использую Hibernate в качестве ORM и Postgres в качестве базы данных