2013-05-31 13 views
5

W naszej aplikacji używamy Spring i Hibernate.Wprowadzić obiekt sesji do komponentu bean DAO zamiast do fabryki sesji?

We wszystkich klasach DAO mamy SessionFactory auto wired i każda z metod DAO wywołuje metodę getCurrentSession().

Pytanie, jakie mam, to dlaczego nie wstawiamy obiektu sesji zamiast obiektu SessionFactory w zakresie prototypowym? To pozwoli nam zaoszczędzić na wywołaniu getCurrentSession.

Myślę, że pierwsza metoda jest poprawna, ale szuka konkretnych scenariuszy, w których druga metoda spowoduje błędy lub może być zła wydajność?

+0

Jeden przypadek czytać [doc] (http://docs.jboss.org/hibernate/orm/3.5/javadoc/org/hibernate/Session.html), który mówi 'Jeśli sesja zgłasza wyjątek, transakcja musi być wycofana i sesja wyrzucić. Wewnętrzny stan Sesji może nie być zgodne z bazy danych po wyjątku powodującego powstanie –

+0

Lepiej wstrzyknąć 'javax.persistence.EntityManager' ale za to trzeba domagać się za pomocą JPA zamiast. – Lion

Odpowiedz

3

Po zdefiniowaniu fasoli jako zakresu prototypowego tworzona jest nowa instancja dla każdego miejsca, w które należy wstrzyknąć. Tak więc każdy DAO otrzyma inną instancję Session, ale wszystkie wywołania metod na DAO będą kończyły się przy użyciu tej samej sesji. Ponieważ sesja nie jest bezpieczna dla wątków, nie powinna być współużytkowana w wielu wątkach, to będzie problem.

W większości sytuacji sesja powinna być zasięgiem transakcji, tj. Nowa sesja jest otwierana po rozpoczęciu transakcji, a następnie zamykana automatycznie po zakończeniu transakcji. W niektórych przypadkach może być konieczne rozszerzenie zakresu na żądanie.

Jeśli chcesz uniknąć używania SessionFactory.currentSession - musisz to zrobić, aby zdefiniować własną implementację zakresu.

To jest coś, co zostało już zaimplementowane w JPA przy użyciu serwerów proxy. W przypadku JPA EntityManager jest wstrzykiwany zamiast EntityManagerFactory. Zamiast @Aucowired jest nowa adnotacja @PersistenceContext. Proxy jest tworzone i wstrzykiwane podczas inicjalizacji. Gdy jakakolwiek metoda zostanie wywołana, proxy zdobędzie aktualną implementację EntityManager (używając czegoś podobnego do SessionFactory.getCurrentSession) i przekazuje ją do niego.

Podobna rzecz może zostać zaimplementowana również w Hibernate, ale dodatkowa złożoność nie jest tego warta. Znacznie łatwiej jest zdefiniować metodę getSession w BaseDAO, która wewnętrznie wywołuje SessionFactory.getCurrentSession(). Dzięki temu kod przy użyciu sesji jest identyczny z sesją iniekcyjną.

3

Wstrzykiwanie sesji prototypowych oznacza, że ​​każdy z obiektów DAO z definicji otrzyma własną sesję ... Z drugiej strony SessionFactory daje moc do open i udostępnia sesje do woli.

Faktycznie getCurrentSession nie otworzy nowej sesji przy każdym wywołaniu ... Zamiast tego będzie ponownie korzystać z sesji powiązanych z current session context (np. Wątek, JTA Transacion lub kontekst zewnętrzny zarządzany).

Pomyślmy o tym; załóżmy, że w twojej warstwie biznesowej jest operacja, która musi odczytywać i aktualizować kilka tabel bazy danych (co oznacza interakcję, bezpośrednio lub pośrednio, z kilkoma DAO) ... Dość typowy scenariusz, prawda? Zwyczajowo, gdy tego rodzaju operacja się nie powiedzie, będziesz chciał przywrócić wszystko, co się stało w bieżącej operacji, prawda? A więc, w tym "szczególnym" przypadku, jaka strategia wydaje się odpowiednia?

  1. Obejmują one kilka sesji, z których każda zarządza własnym rodzajem obiektów i wiąże się z różnymi transakcjami.
  2. Mieć pojedynczą sesję zarządzającą obiektami związanymi z tą operacją ... Wyznacz transakcje zgodnie z potrzebami biznesowymi.

W skrócie, sesje udostępniania i efektywne rozgraniczanie transakcji nie tylko poprawią wydajność aplikacji, ale stanowią część funkcjonalności aplikacji.

bym głęboko polecam czytać Chapter 2 i Chapter 13 z Hibernate Core Reference Manual lepsze zrozumienie ról, które SessionFactory, Session i Transaction odtworzeń w ramach. Będzie również uczyć woli o jednostkach pracy, jak również popularnych wzorców sesji i anty-wzorców.

Powiązane problemy