Hibernate openSession () против getCurrentSession ()

130

У меня есть несколько вопросов об использовании Hibernate в веб-приложении JSP.

  1. Какая должна быть ценность hibernate.current_session_context_class?

  2. Тогда какое из следующих утверждений следует использовать? И почему?

     Session s = HibernateUtil.getSessionFactory().openSession();
     Session s = HibernateUtil.getSessionFactory().getCurrentSession()
    
  3. Наконец, что лучше: «один сеанс на каждое веб-приложение» или «один сеанс на запрос»?

wannik
источник

Ответы:

145

Как поясняется в этом форуме пост , 1 и 2 связаны между собой . Если вы установите hibernate.current_session_context_classпоток, а затем реализуете что-то вроде фильтра сервлета, который открывает сеанс, вы можете получить доступ к этому сеансу в любом другом месте, используя SessionFactory.getCurrentSession().

SessionFactory.openSession()всегда открывает новый сеанс, который необходимо закрыть после завершения операций. SessionFactory.getCurrentSession()возвращает сеанс, привязанный к контексту - вам не нужно его закрывать.

Если вы используете Spring или EJB для управления транзакциями, вы можете настроить их для открытия / закрытия сеансов вместе с транзакциями.

Вы никогда не должны использовать one session per web app- сеанс не является потокобезопасным объектом - не может использоваться несколькими потоками. Вы всегда должны использовать «один сеанс на запрос» или «один сеанс на транзакцию».

gkamal
источник
Большое спасибо, @gkamal. Я смотрю на код в документе Open Session in View . (Ваша ссылка указывает на эти документы.) Автор предлагает использовать фильтр. В своем коде фильтра он не вызывает openSession()или close(). Он только звонит getCurrentSession(). Я предполагаю , что он устанавливает current_session_contextв thread. Теперь я думаю, что понимаю getCurrentSession(). Однако я не знаю, когда мне следует использовать openSession().
wannik 08
4
Вы будете использовать OpenSession, если не хотите, чтобы сеанс был привязан к какому-либо контексту. В некоторых ситуациях вам понадобится другой сеанс, отличный от привязанного к контексту (перехватчики Hibernate имеют ограничение, заключающееся в том, что вы не можете использовать исходный сеанс) - в этих случаях вы должны использовать OpenSession вместо currentSession. OpenSession создает новый сеанс, который необходимо закрыть явно. Например, в методе DAO вы вызовете OpenSession - используйте сеанс и закройте его.
gkamal 08
я использую getCurrentSession (); потому что я инициализировал его в слушателе, а не фильтре, это нормально с вашей точки зрения; Я использую сервлет mvc2 jsp
shareef
@gkamal - у меня вопрос, связанный с Sessions. Не могли бы вы помочь мне с этим на - stackoverflow.com/questions/23351083/… . Спасибо и ченки.
Эрран Морад
ИМО, это хорошая практика, чтобы каждый поток имел свой собственный сеанс, и только один сеанс, верно?
coderz
31

Если говорить о SessionFactory.openSession ()

  • Он всегда создает новый объект сеанса.
  • Вам необходимо явно очистить и закрыть объекты сеанса.
  • В однопоточной среде он медленнее, чем getCurrentSession ().
  • Вам не нужно настраивать какое-либо свойство для вызова этого метода.

А если говорить о SessionFactory.getCurrentSession ()

  • Он создает новый сеанс, если он не существует, иначе использует тот же сеанс, который находится в текущем контексте гибернации.
  • Вам не нужно сбрасывать и закрывать объекты сеанса, Hibernate автоматически позаботится об этом внутри.
  • В однопоточной среде это быстрее, чем openSession ().
  • Вам необходимо настроить дополнительное свойство. "hibernate.current_session_context_class" для вызова метода getCurrentSession (), в противном случае он выдаст исключение.
Раму Агравал
источник
В приведенном выше ответе говорится не использовать ни одного сеанса для каждого веб-приложения. Таким образом, если бы я использовал getCurrentSession, он бы использовал тот же сеанс повторно, не так ли?
парсер
9

openSession: Когда вы звоните SessionFactory.openSession, он всегда создает новый Sessionобъект и передает его вам.

Вам необходимо явно очистить и закрыть эти объекты сеанса.

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

getCurrentSession: Когда вы вызываете SessionFactory.getCurrentSession, он предоставит вам объект сеанса, который находится в контексте спящего режима и внутренне управляется спящим режимом. Он привязан к области транзакции.

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

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

Чтобы использовать метод, вам необходимо добавить следующее свойство в hibernate.cfg.xmlgetCurrentSession :

<session-factory>
    <!--  Put other elements here -->
    <property name="hibernate.current_session_context_class">
          thread
    </property>
</session-factory>
Нирадж Гахлават
источник
Разве сервлет не открывает новый поток для каждого запроса? Таким образом, если это веб-приложение Java, это уже не однопоточная среда?
парсер
0
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Parameter            |                                openSession                                 |                                          getCurrentSession                                          |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Session  creation    | Always open new session                                                    | It opens a new Session if not exists , else use same session which is in current hibernate context. |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Session close        | Need to close the session object once all the database operations are done | No need to close the session. Once the session factory is closed, this session object is closed.    |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Flush and close      | Need to explicity flush and close session objects                          | No need to flush and close sessions , since it is automatically taken by hibernate internally.      |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Performance          | In single threaded environment , it is slower than getCurrentSession       | In single threaded environment , it is faster than openSession                                      |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Configuration        | No need to configure any property to call this method                      | Need to configure additional property:                                                              |
|                      |                                                                            |  <property name=""hibernate.current_session_context_class"">thread</property>                       |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
Джоби Уилсон Мэтьюз
источник
-6

SessionFactory: «Один SessionFactory для каждого приложения для каждой базы данных» (например, если вы используете 3 DataBase в нашем приложении, вам необходимо создать объект sessionFactory для каждой БД, всего вам нужно создать 3 sessionFactorys. Или еще, если у вас есть только одна база данных One sessionfactory достаточно ).

Сессия: «Одна сессия за один цикл запрос-ответ». вы можете открыть сеанс, когда пришел запрос, и вы можете закрыть сеанс после завершения процесса запроса. Примечание: -Не используйте один сеанс для веб-приложения.

Swamy
источник