удалить объекты из спящего режима - PullRequest
1 голос
/ 27 сентября 2011

У меня есть спящий класс pojo A {B b;некоторые другие свойства} с lazy = true для класса B. Когда я получаю объект A, B не загружается и hibernate возвращает свой прокси.Когда я передаю этот объект другому модулю, этот модуль пересекает каждый объект в A, и когда он встречает B.getXXX, он вызывает исключение LazyInitialization.В этом конкретном случае я не хочу загружать класс B, поскольку это не требуется.Есть ли способ, когда я вызываю методы на B, он либо возвращает ноль, либо превращает прокси-сервер B в реальный объект B, чтобы модуль не выдавал ошибку LazyInitialization.Я не могу изменить класс B для получения, установки для общего класса и использования многими другими классами.

Ответы [ 4 ]

1 голос
/ 27 сентября 2011

Если я понимаю ваш вопрос, вы извлекаете объект A с ленивой ассоциацией к B. Однако эта ассоциация не инициализируется, и вы обнаруживаете, что другие модули выдают исключения, потому что B фактически используется. Так что требуется каким-то образом.

Вы хотите либо

  • Возврат null из вызовов на B (насколько я знаю, это невозможно, если только в этих модулях не наблюдается какое-то специфическое поведение приложения) или

  • Инициализировать B, когда такие вызовы происходят. Я постараюсь помочь вам реализовать это.

Причина, по которой вы получаете LazyInitializationExceptions, заключается в том, что сеанс, который извлек B (и не инициализировал его), уже закрыт, поэтому на данный момент экземпляр B бесполезен совсем. Один из способов обойти это здесь - использовать шаблон OSIV , чтобы у вас был один и тот же сеанс Hibernate, открытый во всей области запроса. Это сеанс, который будет извлекать A с ленивым B и инициализирует B, когда возникнет необходимость .

Другой вариант, который вы могли бы применить, - инициализация B в другом сеансе (допустимо только в том случае, если эти исключения происходят в контексте другой транзакции, то есть с другим открытым сеансом Hibernate, отличным от того, который был извлечен * 1033). *). Например:

session.update(a.getB());

Конечно, вы всегда можете принудительно инициализировать B с помощью fetchMode.EAGER или Hibernate.initialize(a.getB()). Но это будет безоговорочно загружать экземпляр, даже если он вообще не будет использоваться.

Также могут оказаться полезными ответы на этот вопрос: hibernate: LazyInitializationException: не удалось инициализировать прокси

0 голосов
/ 28 сентября 2011

Спасибо за все ваши предложения.Мое приложение имеет многоуровневую архитектуру.Сервис-> Manager-> Dao.Hibernate сессия закрывается после менеджера.Другой модуль взаимодействует только через Сервис.Открытие сеанса гибернации до завершения запроса для меня не вариант.Я также не хочу попадать в базу данных, поскольку необязательно заполнять свойства B.Я просто хочу заменить прокси hibernate на реальный объект, чтобы любой, кто использует сервис, не сталкивался с какой-либо проблемой.Я нашел утилиту на http://svn.rhq -project.org / repos / rhq / branch / HEIKO-EXP / modules / enterprise / server / safe-invoker / src / main / java / org / rhq / enterprise / server /util / HibernateDetachUtility.java , которая точно делает то, что я хочу.Он проверяет объект и заменяет спящий режим прокси реальным объектом.Мне нужно настроить следующие вещи в приведенной выше утилите 1. Измените экземпляры classname из org.rhq на мою структуру пакета.2. Они ожидают, что имя поля идентификатора в pojo будет «id».Я изменяю его, чтобы использовать то свойство, которое имеет аннотацию javax.persistence.Id.

Базовое тестирование с указанными выше изменениями выполнено и работает нормально.Мне просто нужно протестировать все приложение по разным сценариям, чтобы оно работало во всех сценариях.

0 голосов
/ 27 сентября 2011

Не отправляйте объекты в другие модули, когда сессия закрыта.

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

Если эти модули не совпадаютAppDomain, если вам нужна какая-то сериализация для отправки объектов или если она вызывается асинхронно, я бы использовал DTO.Разоблачение сущностей вне сервера (я не знаю, так ли это здесь) является плохой практикой по нескольким причинам.Ayende Rahien называет это Pattern Stripper .

0 голосов
/ 27 сентября 2011

На самом деле, у вас есть несколько вариантов.

1) Установите отношение A-> B EAGER.

2) Вы получаете LazyInitializationExceptions при попытке запустить прокси, когда сеанс гибернации уже закрыт.таким возможным решением было бы держать сеанс открытым до тех пор, пока все ваши объекты A, B, C ... и т. д. не будут завершены.

3) Если вы интересуетесь веб-средой, в поле зрения есть шаблон Open Session.который сохраняет ваш сеанс Hibernate открытым до тех пор, пока ваш HTTP-запрос не будет активен.

Вы можете узнать больше об этом здесь .Я думаю, вам будет полезно прочитать его.

...