Спящий режим: увеличение целого поля

Я хочу увеличить поле в таблице базы данных на 1, используя Hibernate.

Я могу сделать это, просто загружая объект, увеличивая значение и обновляя объект, однако, если появляется другой поток и обновляет поле между загрузкой и обновлением, тогда значение будет искажено.

Поэтому вместо этого я вызвал обновление непосредственно в базе данных:

Query updateHits = createQuery(
    "UPDATE Job SET hitCount = hitCount + 1 WHERE id = :jobId" );
updateHits.setInteger( "jobId", job.getId() );
updateHits.executeUpdate();

Однако я понимаю, что это исключает оптимистичную блокировку в базе данных, и я в настоящее время испытываю проблему с взаимоблокировками на SQL-сервере, и я считаю, что это преступник.

Есть ли способ увеличить поле без непосредственного вызова обновления и при сохранении целостности данных?

Ответ 1

Я могу сделать это, просто загрузив объект, увеличивая значение и обновление объекта, однако, если другое поток приходит и обновляет поле между нагрузкой и обновить, тогда значение станет поврежден.

Если второй поток также использует hibernate, и вы используете hibernate versioning (@Version) тот самый поток, который совершает первый и изменяет объект, будет устанавливать новую версию на объект.

Когда вступает вторая фиксация потока, hibernate проверяет, не блокирует ли оптимизатор блокировки и генерирует исключение - исключение StaleObjectException, если я не ошибаюсь. Будет ли блок catch вокруг вашего параллельного кода, у вас будет возможность снова загрузить объект и попробовать свое обновление, если это имеет смысл. Если вы используете JPA, будет выбрано исключение OptimisticLockException.

В разделе содержится информация о загрузке спящего режима Оптимистичная Concurrency.

Ура!