Что проверяет вопрос про @Version и optimistic locking в JPA

Вопрос звучит просто: как JPA предотвращает потерянное обновление без блокировки строки в БД. Но проверяют здесь не термин, а понимание механики — что происходит в SQL-запросе при обновлении версионированной сущности.

@Version добавляет столбец, который Hibernate инкрементирует при каждом UPDATE. Ключевая деталь — этот же столбец попадает в WHERE-условие запроса: UPDATE ... SET version = version + 1 WHERE id = ? AND version = ?. Если версия в БД уже другая — ни одна строка не обновится, и Hibernate бросает OptimisticLockException.

Это отличает optimistic locking от pessimistic (SELECT ... FOR UPDATE): здесь нет блокировки строки на время транзакции, конфликт обнаруживается только в момент записи изменения. Для read-heavy систем с редкими конфликтами это дешевле, чем держать лок.

@Entity public class Account {

@Id private Long id;

@Version private Long version;

private BigDecimal balance; }

Спросят следом: что делать при перехваченном OptimisticLockException. Просто залогировать и вернуть 500 — не ответ. Нужен retry: перечитать сущность заново, применить изменение к свежей версии, повторить commit. И отдельная ловушка — @Version защищает только в пределах одной UPDATE-операции конкретной сущности, а не любые check-then-act сценарии, где чтение и запись разнесены во времени за пределами одной транзакции.

OptimisticLockException — это не ошибка, а сигнал, что кто-то обновил ту же строку раньше вас. Обрабатывать его нужно повтором, а не try-catch с логом.

Тренажёр: 600 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки