Открытая сессия Hibernate: транзакция на запрос?

Я использую Hibernate с Spring на Tomcat. Я читал и перечитывал часто указываемыеJBoss вики-страница по теме, и это было полезно. Но это оставляет меня с некоторыми вопросами.

The idea of starting a transaction for every request troubles me. I guess I could limit the filter to certain controllers -- maybe put all my controllers that need a transaction under a pseudo "tx" path or something. But isn't it a bad idea to use transactions if you don't know if you're going to need one? And if I'm just doing reads in some request -- reads that very likely may come from a cache -- aren't I better off without a transaction?

I've read posts mentioning how they handled the transactions at the service layer, and I'd like to do this with Spring. But then what does the filter code look like? I still want the session available in my view for some lazy loading.

If all I have to do is call sessionFactory.getCurrentSession() in my filter, how does it get "freed" back to the session factory for re-use? (I expected to see a session.close() or something, even when using transactions.) Who is telling the session factory that that session can be reused?

Perhaps it's the beginTransaction() call that binds a given database connection to a given session for the duration of a request? Otherwise, a session pulls db connections from the pool as needed, right?

Спасибо за ваше терпение со всеми моими вопросами.

(И если вашим ответом будет ссылка на документацию Spring, вы просто заставите меня плакать. Вы этого не хотите, не так ли? Я заплачу реальные деньги, если люди перестанут отвечать на вопросы, связанные со Spring, которые путь.)

Ответы на вопрос(2)

если фильтр создает сеанс для каждого запроса, потому что сеансы приходят из пула сеансов, и они будут использоваться повторно. С точки зрения ОС ничего не происходит.

Сеанс гибернации - это, по сути, соединение tcp (или сокет / канал) с сервером базы данных. Стоимость создания db conn очень зависит от типа sql (postgresql особенно плох в этом, хотя он очень хорош во всем). Но это на самом деле ничего не значит, потому что Hibernate повторно использует соединения с базой данных.

Простое решение с фильтром гибернации запускает новую транзакцию в сеансе также для каждого запроса. Это транзакция с точки зрения SQL: это «НАЧАЛО» и "COMMIT" запрос. Это всегда дорого, и это должно быть уменьшено.

ИМХО возможное решение было бы, если бы транзакции были запущены только при первом запросе текущего запроса. Может быть, у весны есть что-то полезное для этого.

 24 окт. 2014 г., 16:36
@ Марво У меня не было такого хорошего опыта. Вы не контролируете, что именно происходит и почему. В моем последнем проекте у меня было несколько соединений с базами данных (некоторые сущности соединяли первое, некоторые со вторым) с поперечно направленными пружинными слоями, и некоторые процессы были инициированы Quartz, некоторые из Интернета. Ситуация была сложной, и главная проблема заключалась в том, что при использовании аннотаций или / и основанных на AOP вы очень-очень можете проверить, что не удалось или где проблема. Это просто работает или нет, но вы не можете видеть в них. В понятной процедурной среде это тривиально.
 Marvo17 янв. 2013 г., 20:03
Мы пришли к использованию фильтра OpenSessionInView (см. Выше) в сочетании с аннотацией Spring @Transactional. Пока все отлично работает.
Решение Вопроса

решение, представленное на вики-странице, слишком упрощенное. Транзакция не должна управляться на веб-уровне - она должна обрабатываться на сервисном уровне.

Правильная реализация откроет сеанс и свяжет его с потоком в фильтре. Транзакция не запущена. Сессия никогда не переводится в режим сброса - только для чтения. Сервисный вызов установит сеанс в режим сброса auto & amp; начать / совершить транзакцию. Как только сервисный метод завершается, режим очистки сеанса возвращается к никогда.

Существует также возможность не открывать сеанс в фильтре. Каждый вызов уровня сервиса откроет отдельный сеанс & amp; транзакция - после завершения сервисного вызова сеанс не закрывается, но регистрируется для отложенного закрытия. Сессия будет закрыта после завершения обработки веб-запроса.

Весна обеспечиваетOpensessionInViewFilter который работает как описано выше. Поэтому не обращайте внимания на статью вики о jboss и просто настройте OpensessionInViewFilter - все будет хорошо.

SessionFactory.getCurrentSession () - внутренне создает и назначает сеанс локальному потоку. Каждый запрос / поток будет иметь свой собственный сеанс. После завершения обработки веб-запроса сеанс будет закрыт. Внутри вашего кода вам просто нужно использовать SessionFactory.getCurrentSession () и не нужно его закрывать. Пример кода на вики-странице jboss неверен - он должен иметь SessionFactory.getCurrentSession (). Close () в блоке finally. Или они могут использовать транзакцию JTA и настроить спящий режим на открытие / закрытие сеанса в сочетании с транзакцией JTA.

 05 авг. 2014 г., 19:10
Я всегда думал, что это будет работать как транзакция. Но на самом деле транзакция ограничена пружиной @Transactional. Спасибо за объяснение.
 Marvo19 мая 2012 г., 23:37
Я собирался отсюда туда-сюда-туда-сюда, пропуская веб-страницы по этой теме в течение недели ... и это первый раз, когда я читал, что Spring имеет фильтр OpenSessionInView. Спасибо.
 Marvo20 мая 2012 г., 04:45
Чувак, это так прекрасно работает. Спасибо!

Ваш ответ на вопрос