Как работает аннотация JPA @Version при наличии нескольких объектов

#java #sql #hibernate #jpa #transactions

#java #sql #переход в спящий режим #jpa #транзакции

Вопрос:

Предположим, мы используем базу данных с уровнем изоляции, установленным на: read_committed, и мы также используем объекты JPA, аннотированные с помощью @Version .

У нас есть две транзакции T и K, подобные этим:

T ————————————- K
начните
читать A
, читать B
, читать C
————————————— начать
————————————— обновить A
————————————— завершите
обновление C
с использованием состояний
объекта A и B
end

На данном этапе транзакции T обновление C выполнено успешно (проверка версии в порядке), поэтому мы обновляем C, используя статус, который на самом деле никогда не существовал в базе данных.

Что не так с моим пониманием?

Редактировать:

@Vlad

Рассмотрим этот пример:

T—————————————————— K

Запустите транзакцию
прочитайте
———————————————— Запустить транзакцию
———————————————— Мод A
———————————————— Мод B
———————————————— Завершение транзакции
чтение версии C = 1
чтение B

// используйте данные da A и B
// для обновления C
A, B -> C
// обновление выполнено успешно (проверьте версию в порядке)

Завершить транзакцию

Используя OPTIMISTIC_FORCE_INCREMENT, вы, по сути, говорите мне всегда использовать метод find с правильно установленным параметром?

Ответ №1:

Оптимистичная блокировка работает только для отдельных строк таблицы. В этом конкретном случае объект C может быть успешно обновлен, поскольку вторая транзакция его не изменяет.

Если вы хотите создать здесь конфликт, то вы должны использовать любой из следующих запросов оптимистичной блокировки:

Таким образом, во второй транзакции всякий раз, когда вы обновляете объект A , вы также запускаете увеличение версии в C .

Комментарии:

1. Большое вам спасибо!

2. Я думаю, что это не нужно, но я был бы рад услышать от вас об этом?

3. Сброс вызывается автоматически в конце транзакции, поэтому вам не нужно вызывать его вручную.

4. У меня есть последнее сомнение: предположим, мы загружаем объект en с hibernate findById с параметром OPTIMISTIC_FORCE_INCREMENT и сериализуем объект клиенту (здесь долгий разговор), когда клиент возвращает серверу объект, должен ли я создать присоединенный объект, вручную установить для него версию и затем вызвать merge ? извините, что беспокою вас 😉

5. Вы узнаете гораздо больше, когда попробуете все эти примеры с помощью упражнений. Для этого используйте мой репозиторий на GitHub . Удачи!