Hibernate (JPA): как обрабатывать StaleObjectStateException, когда несколько объектов были изменены и зафиксированы - PullRequest
4 голосов
/ 29 января 2011

Рассмотрим сценарий: Db-транзакция, включающая более одной строки из разных таблиц с контролем версий.

Например: A shopLists и products.Где shopList может содержать товары (с их количеством в shoplist), а товары имеют текущий запас.

Когда я вставляю или редактируешь shopList, я хочу, чтобы запас этих товаров в shopList обновлялся, чтобы сохранитьконсистент запаса.

Для этого я открываю транзакцию, вставляю / обновляю shopList, обновляю запасы для каждого продукта (применяем дельта) и затем фиксирую транзакцию.Ничего страшного до сих пор.

Тем не менее, другой пользователь мог обновить один или несколько общих продуктов.Или даже обновил сам shopList.В обоих случаях я получаю исключение StaleObjectStateException при совершении транзакции.

Вопрос: есть ли способ определить, какая таблица вызвала исключение StaleObjectStateException?

В случае, если продукт вызвал исключение,может обновить все включенные продукты из БД, а затем повторно применить дельты акций.И это нормально.В случае, если shopList вызвал исключение, было бы лучше просто сообщить о проблеме пользователю, чтобы он мог начать все сначала.

Большое спасибо за вашу помощь.

1 Ответ

4 голосов
/ 30 января 2011

Я узнал как.

Перво-наперво: JPA (или сама Hibernate) заключает в себе исключение org.hibernate.StaleObjectStateException как javax.persistence.OptimisticLockException. Так что, если вы хотите поймать правильное исключение, перейдите к OptimisticLockException.

Во-вторых: Спящий режим вызовет исключение OptimisticLockException только при вызове метода Flush EntityManager перед фиксацией. Если вы вызовете Commit напрямую, вы получите другое исключение (я забыл, какое). Учитывая, что почти все перехватывают эти исключения, выданные методом commit, и отправляются на откат транзакции, вы получите связанное с откатом исключение (не могу вспомнить, какое еще раз).

Третий и последний ответ на мой оригинальный вопрос: Вам просто нужно вызвать метод getEntity из экземпляра OptimisticLockException, чтобы получить источник ошибки управления версиями. Это даст вам все, что вам нужно, связанное с этим.

Спасибо всем, кто прошел здесь. Любые вопросы, касающиеся этого, просто задавайте, и я буду рад помочь.

...