Применяли ли вы оптимистичные блокировки на практике и приведите пример
Что проверяют
Понимаете ли, что оптимистическая блокировка ничего не блокирует, знаете ли её реализацию в JPA и, главное, что делаете при конфликте. Ответ «ставим @Version» без продолжения про повтор операции считается неполным.
Как отвечать
Смысл: читаем строку вместе с версией, а при записи проверяем, что версия не изменилась. В JPA это поле с @Version (число или отметка времени), Hibernate сам добавляет условие и увеличивает счётчик:
update orders set status = ?, version = version + 1
where id = ? and version = ?Ноль обновлённых строк означает, что кто-то успел раньше, и наружу летит OptimisticLockException, в Spring Data это ObjectOptimisticLockingFailureException. Без JPA пишется тем же запросом руками. Версию можно заменить отметкой времени, но она хуже: два обновления могут попасть в одно значение.
Когда выбирать: конфликты редки, а транзакцию нельзя держать открытой, например пользователь правит форму несколько минут. Когда конфликты часты и повтор дорог, берут пессимистическую: select ... for update или LockModeType.PESSIMISTIC_WRITE.
Обработка конфликта важнее самого механизма. Повторять надо всю операцию в новой транзакции: перечитать актуальные данные, применить изменения заново, ограничить число попыток. Для формы пользователя повтор вслепую опасен, там правильнее показать, что данные изменились.
Где спотыкаются
Ловят исключение внутри той же транзакции и продолжают работать. После неудачной проверки версии контекст персистентности в неопределённом состоянии, транзакция помечена на откат, и коммит всё равно упадёт. Повтор делается снаружи, отдельной транзакцией.
Ставят @Version, а строку обновляют через @Modifying или нативный запрос. Такой апдейт версию не проверяет и не увеличивает, защита существует только на бумаге.
Версия не доезжает до клиента: сервис принимает DTO без неё, перечитывает свежую сущность и сохраняет. Проверка тогда успешна всегда, а потерянное обновление возвращается. Версию нужно отдавать наружу и принимать обратно.