Включение @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?
Is that expected behavior?
Да.
Does versioning work only with connections managed by JPA?
Нет, это также работает при использовании любого другого способа обновления ваших данных. Но все, что обновляет данные, должно соответствовать правилам оптимистической блокировки:
Он работает так, как ожидалось. Если вы выполняете обновление вручную, вам также необходимо обновить свою версию.
Если вы используете 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 одинаковым и соответствует копии объекта, полученной ранее.
Если значение совпадает, это означает, что объект не является грязным (не обновляется какой-либо другой транзакцией), иначе генерируется исключение.