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”?

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ę”


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.

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>

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>                       |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+

-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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.