Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

В принципе, у вас есть несколько вариантов.

-Вы можете использовать шаблон "open session in view", в котором вы используете логику типа filter/interceptor/AOP, чтобы открыть сеанс, когда начинается логика на стороне сервера, и закройте его, когда он пройдет.

-Вы можете реализовать цепочки цепочек запросов-ответов.

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

Ответ 2

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

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

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

Ответ 3

Как говорили другие, вы должны прочитать шаблон "open session in view", основная идея которого состоит в том, чтобы открыть сеанс hibernate для полной длительности обработки HTTP-запроса. Существуют hibernate specific и spring решения - Я использовал spring раньше, и он отлично работает.

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

Ответ 4

Используете ли вы Spring HibernateTemplate? Думаю, для вас это будет управлять. Альтернативно, если вы находитесь в Hibernate 3.0.1 или выше, Spring все равно сможет управлять сеансом для вас.

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

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

Ниже приведен XML, который мы будем использовать для сборки приложения. Как вы можете видеть, мы, конечно, все еще используем способ для настройки 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…
}

Ответ 5

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

Ответ 6

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