Поведение JPA @Version при изменении данных из неуправляемого соединения

Включение @Version на столе Customer при выполнении тестов ниже

@Test
public void actionsTest1 () throws InterruptedException {
    CustomerState t = customerStateRepository.findById(1L).get();
    Thread.sleep(20000);
    t.setInvoiceNumber("1");
    customerStateRepository.save(t);
}

Пока actionsTest1 спит, я запускаю actionsTest2, который обновляет номер счета на 2.

@Test
public void actionsTest2 () throws InterruptedException {
    CustomerState t = customerStateRepository.findById(1L).get();
    t.setInvoiceNumber("2");
    customerStateRepository.save(t);
}

Когда actionTest1 возвращается из спящего режима, он также пытается обновиться и получает ObjectOptimisticLockingFailureException

Работает как положено.

Но если я запускаю actionsTest1 и пока он спит, я открываю терминал SQL и выполняю необработанное обновление

update customer 
set invoice_number='3' where id=1

Когда actionsTest1 возвращается из спящего режима, его механизм управления версиями не улавливает случай и обновляет значение до 1.

Это ожидаемое поведение? Работает ли управление версиями только с подключениями, управляемыми JPA?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
25
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Is that expected behavior?

Да.

Does versioning work only with connections managed by JPA?

Нет, это также работает при использовании любого другого способа обновления ваших данных. Но все, что обновляет данные, должно соответствовать правилам оптимистической блокировки:

  1. увеличивать столбец версии при выполнении любого обновления
  2. (требуется только в том случае, если другой процесс также хочет обнаруживать одновременные обновления): при каждом обновлении проверяйте, что номер версии не изменился с момента загрузки данных, на которых основано обновление.
Ответ принят как подходящий

Он работает так, как ожидалось. Если вы выполняете обновление вручную, вам также необходимо обновить свою версию.

Если вы используете JPA с @Version, JPA увеличивает столбец версии.

Чтобы получить ожидаемый результат, вы должны написать такое выражение

update customer set invoice_number='3', version=XYZ (mabye version+1) where id=1

Hibernate автоматически увеличивает/изменяет значение в сопоставленном столбце @Version в вашей базе данных.

Когда вы извлекаете запись сущности, hibernate сохраняет копию записи данных вместе со значением @Version. Выполняя операцию merge или update, hibernate проверяет, остается ли текущее значение в Version одинаковым и соответствует копии объекта, полученной ранее. Если значение совпадает, это означает, что объект не является грязным (не обновляется какой-либо другой транзакцией), иначе генерируется исключение.

Другие вопросы по теме