Hibernate (JPA): как обрабатывать исключение StaleObjectStateException, когда несколько объектов были изменены и зафиксированы

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

Например: МагазинСписки и продукты. Где список магазинов может содержать продукты (с их количеством в списке магазинов), а продукты имеют текущий запас.

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

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

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

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

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

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


person Marcus    schedule 29.01.2011    source источник


Ответы (1)


Я узнал как.

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

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

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

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

person Marcus    schedule 30.01.2011
comment
Полные отметки для исключения, выбрасываемого только при вызове session.flush. Если он не вызывается, он возвращается как RollbackException. В этом исключении вы ничего не можете с ним сделать. Вы не можете запросить какую-либо информацию о нем, потому что он не содержит информации. Убедитесь, что вы коллируете флеш. - person sethu; 05.03.2013