Hibernacja openSession () vs getCurrentSession ()

130

Mam kilka pytań dotyczących używania Hibernate w aplikacji internetowej JSP.

  1. Jaka powinna być wartość hibernate.current_session_context_class?

  2. Które z poniższych stwierdzeń należy zatem użyć? I dlaczego?

     Session s = HibernateUtil.getSessionFactory().openSession();
     Session s = HibernateUtil.getSessionFactory().getCurrentSession()
    
  3. Wreszcie, która z nich jest lepsza „jedna sesja na aplikację internetową” czy „jedna sesja na żądanie”?

wannik
źródło

Odpowiedzi:

145

Jak wyjaśniono w tym poście na forum , 1 i 2 są powiązane. Jeśli ustawisz hibernate.current_session_context_classopcję wątku, a następnie zaimplementujesz coś w rodzaju filtru serwletu, który otwiera sesję - wtedy możesz uzyskać dostęp do tej sesji w dowolnym innym miejscu za pomocą SessionFactory.getCurrentSession().

SessionFactory.openSession()zawsze otwiera nową sesję, którą musisz zamknąć po zakończeniu operacji. SessionFactory.getCurrentSession()zwraca sesję powiązaną z kontekstem - nie musisz tego zamykać.

Jeśli używasz Spring lub EJB do zarządzania transakcjami, możesz je skonfigurować tak, aby otwierały / zamykały sesje wraz z transakcjami.

Nigdy nie powinieneś używać one session per web app- sesja nie jest obiektem bezpiecznym dla wątków - nie może być współużytkowana przez wiele wątków. Zawsze powinieneś używać „jednej sesji na żądanie” lub „jednej sesji na transakcję”

gkamal
źródło
Dziękuję bardzo, @gkamal. Patrzę na kod w Open Session w View document. (Twój odsyłacz wskazuje na te dokumenty.) Autor sugeruje użycie filtra. W swoim kodzie filtru nie dzwoni openSession()ani close(). On tylko dzwoni getCurrentSession(). Chyba ustawia current_session_contextsię thread. Teraz myślę, że rozumiem getCurrentSession(). Jednak nie wiem, kiedy powinienem użyć openSession().
wannik
4
Użyjesz OpenSession, jeśli nie chcesz, aby sesja była związana z jakimkolwiek kontekstem. Są sytuacje, w których potrzebujesz innej sesji - innej niż ta związana z kontekstem (Hibernate Interceptors mają ograniczenie polegające na tym, że nie możesz użyć oryginalnej sesji) - w takich przypadkach użyjesz OpenSession zamiast currentSession. OpenSession tworzy nową sesję, którą musisz jawnie zamknąć, np. W metodzie DAO wywołasz OpenSession - skorzystaj z sesji i zamknij ją.
gkamal
używam getCurrentSession (); ponieważ zainicjowałem go w listener not filter, z twojego punktu widzenia jest to ok; używam serwletu mvc2 jsp
shareef
@gkamal - mam pytanie związane z Sessions. Czy możesz mi w tym pomóc pod adresem - stackoverflow.com/questions/23351083/… . Dziękuję i chenqui.
Erran Morad
IMO, dobrą praktyką jest, aby każdy wątek miał własną sesję i tylko jedną sesję, prawda?
coderz
31

Jeśli mówimy o SessionFactory.openSession ()

  • Zawsze tworzy nowy obiekt sesji.
  • Musisz jawnie opróżnić i zamknąć obiekty sesji.
  • W środowisku jednowątkowym jest wolniejsze niż getCurrentSession ().
  • Nie ma potrzeby konfigurowania żadnej właściwości, aby wywołać tę metodę.

A jeśli mówimy o SessionFactory.getCurrentSession ()

  • Tworzy nową sesję, jeśli nie istnieje, w przeciwnym razie używa tej samej sesji, która jest w bieżącym kontekście hibernacji.
  • Nie musisz opróżniać i zamykać obiektów sesji, zostanie to automatycznie objęte wewnętrzną obsługą Hibernate.
  • W środowisku jednowątkowym jest szybszy niż openSession ().
  • Musisz skonfigurować dodatkową właściwość. „hibernate.current_session_context_class”, aby wywołać metodę getCurrentSession (), w przeciwnym razie zgłosi wyjątek.
Ramu Agrawal
źródło
Powyższa odpowiedź mówi, aby nie używać jednej sesji na aplikację internetową. Tak więc, gdybym miał użyć getCurrentSession, wykorzystałby ponownie tę samą sesję, prawda?
parsecer
9

openSession: Kiedy dzwonisz SessionFactory.openSession, zawsze tworzy nowy Sessionobiekt i daje ci go.

Musisz jawnie opróżnić i zamknąć te obiekty sesji.

Ponieważ obiekty sesji nie są bezpieczne dla wątków, musisz utworzyć jeden obiekt sesji na żądanie w środowisku wielowątkowym i jedną sesję na żądanie również w aplikacjach internetowych.

getCurrentSession: Kiedy zadzwonisz SessionFactory.getCurrentSession, dostarczy ci obiekt sesji, który jest w kontekście hibernacji i wewnętrznie zarządzany przez hibernację. Jest to związane z zakresem transakcji.

Kiedy dzwonisz SessionFactory.getCurrentSession, tworzy nową, Sessionjeśli nie istnieje, w przeciwnym razie użyj tej samej sesji, która jest w bieżącym kontekście hibernacji. Automatycznie opróżnia i zamyka sesję po zakończeniu transakcji, więc nie musisz robić tego zewnętrznie.

Jeśli używasz hibernacji w środowisku jednowątkowym, możesz użyć getCurrentSession, ponieważ jest szybszy w porównaniu do tworzenia nowej sesji za każdym razem.

Aby użyć metody, musisz dodać następującą właściwość do hibernate.cfg.xmlgetCurrentSession :

<session-factory>
    <!--  Put other elements here -->
    <property name="hibernate.current_session_context_class">
          thread
    </property>
</session-factory>
Neeraj Gahlawat
źródło
Czy serwlet nie otwiera nowego wątku dla każdego żądania? Zatem jeśli jest to aplikacja internetowa Java, czy nie jest to już środowisko jednowątkowe?
parsecer
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>                       |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
Joby Wilson Mathews
źródło
-6

SessionFactory: „Jedna SessionFactory na aplikację na DataBase” (np. Jeśli używasz 3 DataBase w naszej aplikacji, musisz utworzyć obiekt sessionFactory na każdą bazę danych, całkowicie musisz utworzyć 3 sessionFactory lub jeśli masz tylko jedną sesję DataBase One wystarczy ).

Sesja: „Jedna sesja na jeden cykl żądanie-odpowiedź”. możesz otworzyć sesję po nadejściu żądania i zamknąć sesję po zakończeniu procesu składania wniosku. Uwaga: -Nie używaj jednej sesji dla aplikacji internetowej.

swamy
źródło