Автор оригинала: Vlad Mihalcea.
При переходе с JPA на MongoDB вы начинаете понимать, сколько функций JPA вы ранее принимали как должное. JPA предотвращает “потерянные обновления” как с помощью пессимистической, так и оптимистической блокировки. Оптимистичная блокировка ничего не блокирует, и ее лучше было бы назвать оптимистичной без блокировки или оптимистичным управлением параллелизмом, потому что это то, что она делает в любом случае.
Итак, что значит “потерять обновления”?
Примером из реальной жизни может быть случай, когда несколько фоновых задач обновляют различные атрибуты какой-либо общей сущности.
В нашем примере у нас есть объект продукта с количеством и скидкой, которые решаются двумя отдельными процессорами пакетной обработки.
- партия товара загружает Товар с {количество:1, скидка: 0}
- запас меняет количество, поэтому у нас есть {количество:5, скидка: 0}
- партия со скидкой загружает продукт с {количество:1, скидка: 0}
- скидка изменяет скидку, поэтому у нас есть {количество:1, скидка: 15}
- Запас сохраняет товар {количество:5, скидка: 0}
- Скидка сохраняет товар {количество:1, скидка: 15}
- сохраненное количество равно 1, и обновление запасов будет потеряно
В JPA вы можете указать поле @Version (обычно автоматически увеличиваемое число), а Hibernate позаботится об остальном. За кулисами существует механизм безопасности, который проверяет номер обновленных строк при задании определенной версии. Если ни одна строка не была обновлена, значит, версия изменилась и возникает оптимистичное исключение блокировки.
UPDATE Product SET quantity=1, discount=15 WHERE version=1;
Но если ваше хранилище представляет собой не систему реляционных баз данных, а базу данных NoSQL, вы все равно хотите предотвратить потерю обновлений. К счастью, Spring Data приходит на помощь, поскольку он предоставляет набор аннотаций, ориентированных на документы, среди которых вы можете найти аннотацию @Version с той же семантикой, что и ее аналог JPA.
Также следует использовать механизм автоматической повторной попытки, поскольку оптимистичное исключение блокировки может быть восстановлено. Ему нужно только перезагрузить последний снимок сущности, объединить определенные атрибуты и обновить.
Таким образом, Spring Data предлагает больше, чем поддержку базового репозитория и простую автоматизацию запросов. Надстройка с оптимистичной блокировкой обеспечивает надлежащий уровень согласованности записи, требуемый требованиями вашего приложения.
Код доступен на GitHub