2010-02-20 2 views
0

У меня есть объект домена, у которого есть атрибут, который представляет собой коллекцию, содержащую другой объект домена. Это выполняется с использованием сопоставления спящего режима (которое в конечном итоге выполняет соединение в другой таблице). Hibernate, по умолчанию, кажется, лениво инстанцирует эту коллекцию. Это, оказывается, замечательно, потому что, в зависимости от того, что мне нужно отображать, мне не всегда нужна коллекция, которую нужно загрузить.Использование Hibernate ленивой загрузки?

Мой вопрос заключается в следующем: при написании своих Hibernate запросов (в моих DAO,), я использую следующие для открытия/закрытия сессии:

Session session = getSessionFactory().openSession(); 
//query goes here using the session var 
session.close(); 

Проблема: когда Hibernate наконец приходит лениво загрузка моей коллекции, Session уже давно закрыта! Как я могу обойти это? Я предполагаю, что я должен закрыть сессию, как я делаю ...

Это ошибка, я получаю:

SEVERE: failed to lazily initialize a collection of ... 
+1

Мой ответ здесь может помочь. Http: // StackOverflow.com/вопросы/2290414/trouble-with-hibernate-one-way-association/2290580 # 2290580 – marklai

ответ

5

Если это происходит внутри webapp, то легко исправить это, чтобы использовать OpenSessionInViewInterceptor или OpenSessionInViewFilter. Они задерживают закрытие сеанса до завершения всего запроса, что позволяет вам перемещаться по ленивым ассоциациям при визуализации представления.

Более общее решение состоит в том, чтобы переписать свои запросы, чтобы они явно указывали, какие ассоциации должны быть загружены спереди. Это позволяет вам поддерживать ассоциации ленивыми по умолчанию, и в то же время обслуживать специальные случаи, когда вы хотите, чтобы они охотно забирались. См. Описание "fetch joins" в документах Hibernate.

А «выборка» присоединиться позволяет ассоциации или коллекции значений быть инициализируются вместе с их родителем объектов с помощью одного выбора. Это особенно полезно в случае коллекции . Он эффективно перекрывает внешнее объединение и ленивые декларации файла отображения для ассоциаций и коллекций

+0

Работает ли OpenSessionInViewXYZ с другими фреймворками MVC или просто с Spring MVC? – marklai

+0

Спасибо, у меня есть вопрос: OpenSessionInViewInterceptor/Filter может быть тем, что мне нужно, но вы упомянули, что он задерживает закрытие сеанса до завершения всего запроса. Что делать, если одно из моих представлений никогда не заставляет сбор загружаться. Однако не исключено, что сеанс никогда не будет закрыт, если пользователь не перейдет на страницу, которая заставляет инициализировать (и это не проблема ?)? – oym

+0

.. Фактически, я думаю, что я запутался в том, что подразумевается под «запросом». – oym

2

Я понимаю, что вы открыть и закрыть сеанс для каждой операции DAO. Вместо этого вы могли использовать один и тот же сеанс всеми DAO, открытыми когда-то во время инициализации и закрытыми при завершении работы. Обратите внимание, что Hibernate Reference упоминает «сессию в операцию» как антипаттерны:

«Не использовать сеанс каждой операции антипаттерн: не открывать и закрывать сессию для каждого простого вызова базы данных в одном потоке.»

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

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

+0

Спасибо. Я решил это сделать. Я просто не уверен, как это будет выглядеть (где инициализировать и где закрыть и т. Д.). Также эта стандартная практика? Я уверен, что я не первый, у кого есть эта проблема, поэтому должен быть лучший способ обработки сеанса ... – oym

Смежные вопросы