#hibernate #debugging #transactions #hibernate-session
#гибернация #отладка #транзакции #спящий режим-сессия
Вопрос:
Я уже некоторое время пользуюсь гибернацией и привык к большинству распространенных сообщений об ошибках. Большинство указывает мне прямо на проблему, но у меня возникли проблемы с этим:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
Я понимаю ошибку (в сеансе есть два разных объекта с одинаковым идентификатором), но я действительно не знаю хорошего способа отладки моего кода, чтобы найти источник проблемы. Обычно я просматриваю код, который я сейчас изменяю, и ищу места, где я загружаю один объект и вручную создаю другой, надеясь, что смогу найти простую ошибку в своей логике. Однако в настоящее время я работаю с набором кода, который я не писал, с которым я не знаком и который не имеет документации. Единственное решение, которое я могу придумать, — это просмотреть код, построчно, в надежде найти ошибку. Знаете ли вы лучший способ отладки этой ошибки?
Кроме того, точная ошибка, которую я получаю, связана с вызовом saveOrUpdate()
, что заставляет меня задуматься, вызывает ли он вызов save()
, когда он должен вызывать update()
. Есть ли какой-либо способ просмотреть объекты, которые Hibernate имеет в текущем сеансе, для целей отладки?
Ответ №1:
saveOrUpdate
вызывает update
, если у отдельного объекта уже есть идентификатор. update
затем пытается присоединить данный отдельный объект к сеансу. Поскольку у вас может быть только один экземпляр данного объекта в сеансе, если вы уже загрузили объект (используя a load
, a get
или запрос) в сеанс во время saveOrUpdate
вызова, вы получите это исключение.
saveOrUpdate
обычно это должно быть одним из первых действий после открытия сеанса. Если вам нужно загрузить объект перед его обновлением, вы должны использовать merge
. Я обычно предпочитаю использовать merge
во всех случаях, потому что он менее подвержен ошибкам.
Вы можете иметь представление о том, что используется в сеансе session.getStatistics().getEntityKeys()
.
Комментарии:
1. «И update пытается присоединить данный отдельный объект к сеансу». Разве это не должно указывать » сохранить » вместо » обновить «?
2. No. Save делает временный экземпляр постоянным и присоединяет объект к сеансу. Обновление берет отдельный, измененный экземпляр и пытается присоединить его к сеансу. Если в сеансе уже есть постоянный экземпляр с тем же идентификатором, генерируется исключение.
Ответ №2:
Вы также можете установить точку останова в сеансе.Выполните очистку и проверьте, какие объекты хранятся в постоянном хранилище. Здесь вы можете найти некоторую информацию о том, как отслеживать события открытия и закрытия сеанса — вероятно, вам нужно тщательно изучить PersistenceContext
свойство SessionImpl
объекта и OnFlush
события.
Для отладки с использованием исходного кода вам не нужно перекомпилировать все исходные коды NHibernate — вы можете связать файлы pdb с исходным файлом zip (посмотрите на http://lowleveldesign.wordpress.com/2011/10/02/debugging-nhibernate-prepare-symbol-files /).
Комментарии:
1. Спасибо за ответ, но я не использую nhibernate. Я все равно рассмотрю возможность использования вашего совета в контексте Java.