В Spring с jpa / hibernate, как сохранить сеанс открытым, чтобы избежать отложенных исключений инициализации? - PullRequest
19 голосов
/ 17 июля 2009

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

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

Ответы [ 6 ]

9 голосов
/ 17 июля 2009

https://www.hibernate.org/43.html

По сути, у вас есть несколько вариантов.

-Вы можете использовать шаблон «открыть сеанс в представлении», где вы используете логику в стиле фильтра / перехватчика / AOP, чтобы открыть сеанс, когда начинается логика на стороне сервера, и закрыть его, когда он завершится.

-Вы могли бы осуществлять диалоги, охватывающие несколько циклов запрос-ответ.

Простой старый фильтр сервлетов - самый простой.

5 голосов
/ 24 июля 2009

Последний вариант, который, по-видимому, был пропущен, состоит в том, что вы можете построить свой граф объектов на основе своего варианта использования с помощью JOIN.

Это приведет к инициализации объекта, т.е. он не будет прокси.

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

3 голосов
/ 17 июля 2009

Как уже говорили другие, вам следует ознакомиться с шаблоном "открыть сеанс в представлении", основная идея которого заключается в том, чтобы сеанс гибернации был открыт в течение всей продолжительности обработки http-запроса. Существуют как специальные для спящего режима , так и пружины решения - раньше я использовал Spring, и он отлично работает.

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

1 голос
/ 17 июля 2009

Используете ли вы Spring HibernateTemplate? Я думаю, он будет управлять сессией. В качестве альтернативы, если вы используете Hibernate 3.0.1 или более позднюю версию, Spring все равно сможет управлять сессией за вас.

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

Начиная с Hibernate 3.0.1 (и в Java Persistence API с момента его первого выпуска) стало возможным для Spring управлять базовым ресурсом без необходимости просматривать какие-либо шаблоны, доступные для этих технологий. Это означает, что даже если вы используете Hibernate API напрямую (например, через SessionFactory.getCurrentSession ()), вы все равно будете использовать Spring Hibernate Session. То же самое относится и к EntityManager, полученному через JPA EntityManagerFactory. Это еще одна причина, по которой вам больше не нужно использовать Spring HibernateTemplate для получения интегрированного опыта. [...]

Ниже приведен XML-код, который мы будем использовать для сборки приложения. Как вы можете видеть, мы, конечно, по-прежнему используем Spring для настройки Hibernate (используя LocalSessionFactoryBean).

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <!– the works –>
</bean>
<bean id="accountRepo" class="com.mycompany.HibernateAccountRepository">
  <constructor-arg ref="sessionFactory"/>
</bean>

Теперь, как я уже говорил, из-за небольшого изменения в Hibernate 3.0.1 Spring может управлять сессией Hibernate за вас без необходимости проходить сессию Hibernate. Единственное, чего не хватало, был перевод исключения. Для этого вам также нужно аннотировать репозиторий с помощью аннотации @Repository (предоставленной Spring) и включать преобразование исключений с помощью постпроцессора.

@Repository // from org.springframework.stereotype
public class HibernateAccountRepository implements AccountRepository {
    // see above for full impl…
}
0 голосов
/ 17 июля 2009

Сейчас я не использовал Spring, но я использовал Hibernate в нескольких разных проектах. Подход, который я выбрал для самого последнего проекта, вырос из шаблона Обработка защитных сессий (в сочетании с фильтром сервлета), и мы довольны им. Вы можете найти больше шаблонов дизайна здесь .

0 голосов
/ 17 июля 2009

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

...