Hibernate.initialize (), кажется, не работает на отложенных коллекциях - PullRequest
2 голосов
/ 23 марта 2012

У меня есть слой доступа к данным Hibernate, который находится за кэшем объектов в памяти.В случае пропуска кэша на стороне клиента кэш в памяти будет вызывать слой Hibernate для загрузки графа объектов в кэш.Из-за того, как объекты сериализуются в кеш, мне нужно загрузить весь граф объектов из Hibernate за один раз (т.е. без отложенной загрузки).Подобный сценарий описан в документах Hibernate здесь .Вот выдержка:

В приложении с отдельным бизнес-уровнем бизнес-логика должна «подготовить» все коллекции, которые нужны веб-уровню, прежде чем вернуться.Это означает, что бизнес-уровень должен загрузить все данные и вернуть все уже инициализированные данные на уровень представления / веб-уровня, который требуется для конкретного варианта использования.Обычно приложение вызывает Hibernate.initialize () для каждой коллекции, которая потребуется на веб-уровне (этот вызов должен произойти до закрытия сеанса), или с нетерпением получает коллекцию, используя запрос Hibernate с предложением FETCH или FetchMode.JOIN.в критерии.Это обычно проще, если вы принимаете шаблон Command вместо Session Facade.

Так как я не могу просто включить Eager выборку непосредственно для своих сущностей (я получаю исключение MultipleBagFetchException, как описано в this вопрос StackOverflow) Я подумал, что я просто оставлю стандартное поведение загрузки Lazy и затем выполню Hibernate.initialize() для каждой коллекции в объекте, чтобы полностью насытить объект.Проблема состоит в том, что мои коллекции все еще остаются пустыми.

Чтобы еще больше запутать вещи, эта стратегия, кажется, работает нормально в моих юнит-тестах (мои объекты насыщены должным образом), но когда я запускаю этот слой Hibernate как плагин длямой кэш в памяти (я предоставляю банку, содержащую мой DAL, который кэш в памяти будет вызывать из-за ошибки кэша) Я вижу описанное поведение.

В настоящее время я обрабатываю свойсеанс с

    <property name="current_session_context_class">thread</property>

и последующий вызов

    sessionFactory.getCurrentSession();

в моем DAO, после чего я выполняю сеанс для загрузки объекта.Насколько я могу судить, моя обработка сессий одинакова как для моих рабочих юнит-тестов, так и для нерабочего DAO.Любые предложения относительно того, что здесь происходит.Если вам нужна дополнительная информация, дайте мне знать.

Ответы [ 2 ]

1 голос
/ 23 марта 2012

Я нашел ответ, но на самом деле он не связан с предполагаемой ошибочной инициализацией коллекции, как подразумевает мой OP, но я все равно опубликую его здесь в надежде, что он может кому-то помочь:

Проблема заключалась в том, что UUID (передаваемые в виде строк на уровне обслуживания по уважительным причинам, которые здесь не имеют значения), которые я использую для идентификации объектов, отправлялись на стороне клиента в нижнем регистре, в то время как мой (успешный) модуль тесты отправляли строку UUID в верхнем регистре. Очевидно, БД не заботилась об этой разнице и была в состоянии вернуть по крайней мере объект корневого уровня графа для любого случая, но последующие объединения для насыщения коллекций не дали результата, учитывая строку идентификатора UUID нижнего регистра объекта корневого уровня. Кто-нибудь знает, почему это может быть? Мне кажется, что сгенерированный SQL Hibernate вернул правильные результаты независимо от случая UUID, но Hibernate в конечном итоге отбросил некоторые результаты объединения, потому что идентификаторы UUID технически не совпадали.

1 голос
/ 23 марта 2012

Я тоже видел, как это иногда случается, и мне было бы интересно узнать ответ.В качестве обходного пути я использовал два разных метода для инициализации потомков:

  1. Если это коллекция, вызовите parent.getChildCollection().size()
  2. Используйте запрос Criteria с FetchMode.JOINв ассоциации

Кажется, они всегда работают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...