Hibernate (JPA): как обрабатывать StaleObjectStateException, когда несколько объектов были изменены и зафиксированы
Рассмотрим сценарий: Db-транзакция, включающая более одной строки из разных таблиц с контролем версий.
Например: магазин списков и товаров. Где shopList может содержать товары (с указанием их количества в списке товаров), а товары имеют текущий запас.
Когда я вставляю или редактирую shopList, я хочу, чтобы запас этих продуктов в shopList обновлялся, чтобы сохранить постоянство запасов.
Для этого я открываю транзакцию, вставляю / обновляю shopList, обновляю запасы для каждого продукта (применяем дельта), а затем фиксирую транзакцию. Ничего страшного до сих пор.
Однако другой пользователь может обновить один или несколько общих продуктов. Или даже обновил сам shopList. В обоих случаях я получал бы исключение StaleObjectStateException при совершении транзакции.
Вопрос: есть ли способ определить, какая таблица вызвала исключение StaleObjectStateException?
В случае, если продукт вызвал исключение, я мог бы обновить все включенные продукты из БД, а затем повторно применить дельты акций. И это нормально. Если shopList вызвал исключение, было бы лучше просто сообщить о проблеме пользователю, чтобы он мог начать все сначала.
Большое спасибо за вашу помощь.
1 ответ
Я узнал как.
Перво-наперво: JPA (или сама гибернация) оборачивает исключение org.hibernate.StaleObjectStateException как javax.persistence.OptimisticLockException. Итак, если вы хотите поймать правильное исключение, перейдите к OptimisticLockException.
Второе: hibernate вызовет исключение OptimisticLockException только при вызове метода Flush EntityManager перед фиксацией. Если вы вызовете Commit напрямую, вы получите другое исключение (я забыл, какое). Учитывая, что почти каждый перехватывает эти исключения, выданные методом commit, и выполняет откат транзакции, вы получите связанное с откатом исключение (не могу вспомнить, какое еще раз).
В-третьих, наконец, отвечаю на мой первоначальный вопрос: вам просто нужно вызвать метод getEntity из экземпляра OptimisticLockException, чтобы получить источник ошибки управления версиями. Это даст вам все, что вам нужно, связанное с этим.
Спасибо всем, кто прошел здесь. Любые вопросы по этому поводу, просто задавайте, и я буду рад помочь.