Mam metodę poniżej.
public Profile readUser(String email){
EntityManager em = EMF.get().createEntityManager();
return em.find(Profile.class, email);
}
Czy powyższe użycie menedżera podmiotu jest w porządku? Czy trzeba je zamknąć? Proszę o wszelkie sugestie.
Odpowiedzi:
Przypuszczam, że odpowiedź brzmi: to zależy .
Twój menedżer encji jest kluczem do uzyskania dostępu do kontekstu, w którym znajdują się jednostki. Jeśli Twoja aplikacja jest aplikacją JSE, musisz wziąć pod uwagę oczekiwaną długość życia w Twoim kontekście.
Rozważmy, że utworzysz menedżera encji na żądanie użytkownika. Tak więc, gdy będziesz zajmować się daną prośbą, będziesz mieć otwartego menedżera encji, a kiedy skończysz, zamknij ją.
W aplikacji JSE mogłeś pomyśleć, że chciałbyś, aby menedżer encji pozostawał otwarty przez całe życie aplikacji (zakładając, że nie masz do czynienia z dużymi ilościami danych), a następnie zamykasz ją, gdy aplikacja zostanie zamknięta.
Podsumowując, kiedy go otworzysz i kiedy zamkniesz, zależy całkowicie od Twojej strategii i projektu. Zamykasz go, gdy nie potrzebujesz już jednostek w jego kontekście.
W twoim przykładzie nie jest to oczywiste, ale ponieważ tworzysz EM w metodzie, powinieneś zamknąć go przed powrotem, w przeciwnym razie nie będziesz już mieć do niego dostępu (chyba że trzymasz go w jakimś rejestrze, czego nie widać w kodzie).
Jeśli go nie zamkniesz, twoje byty pozostaną dołączone, nawet po zakończeniu ich używania. Twój kontekst pozostanie żywy, nawet jeśli nie będziesz już mieć dostępu do swojego EM.
JPA Specyfikacja zawiera więcej szczegółów. W sekcji 7.7 Konteksty trwałości zarządzanej przez aplikację jest napisane:
Jak więc widzisz, menedżer encji jest publicznym interfejsem, za pośrednictwem którego uzyskujesz dostęp do swoich podmiotów, jednak podmioty te znajdują się w kontekście, dołączonym do menedżera encji. Zrozumienie cyklu życia różnych typów kontekstów odpowie na Twoje pytanie.
Konteksty trwałości mogą być różnych typów. W aplikacjach Java EE można mieć kontekst trwałości o zakresie transakcji lub kontekst rozszerzonej trwałości . W aplikacji JSE natura kontekstu jest kontrolowana przez programistę .
Kiedy pytasz o jednostkę do swojego menedżera encji, szuka encji w dołączonym kontekście, jeśli znajdzie jednostkę tam, a następnie zwraca ją, w przeciwnym razie pobiera jednostkę z bazy danych. Kolejne wywołania tej jednostki w kontekście zwrócą tę samą jednostkę.
Zakres transakcji
W aplikacji Java EE korzystającej z kontekstu trwałości o zasięgu transakcji, kiedy po raz pierwszy uzyskujesz dostęp do swojego menedżera encji, sprawdza, czy bieżąca transakcja JTA ma dołączony kontekst, jeśli nie ma jeszcze żadnego kontekstu, tworzony jest nowy kontekst i jest połączony z menedżerem encji. w tym kontekście. Następnie jednostka jest odczytywana z bazy danych (lub z pamięci podręcznej, jeśli istnieje) i umieszczana w kontekście. Kiedy transakcja się kończy (zatwierdzenie lub wycofanie), kontekst staje się nieważny, a wszystkie zawarte w nim encje zostają odłączone. To jest klasyczny scenariusz dla fasoli sesji bezstanowych.
@PersistenceContext(unitName="EmplService") EntityManager em;
Oznacza to również, że w zależności od tego, jak zaprojektujesz swoje transakcje, możesz otrzymać więcej niż jeden kontekst.
Kontekst rozszerzonej trwałości
W aplikacji Java EE ze stanowymi fasolami sesji możesz chcieć, aby kontekst przetrwał wiele wywołań fasoli, ponieważ nie lubisz zatwierdzać, dopóki ziarno nie zostanie oznaczone do usunięcia, prawda? W takich przypadkach musisz użyć rozszerzonego kontekstu trwałości. W takim przypadku kontekst trwałości jest tworzony, gdy jest potrzebny po raz pierwszy, ale nie stanie się nieważny, dopóki nie oznaczysz fasoli stanowej do usunięcia.
@PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)
Oznacza to, że niezależnie od instancji menedżera encji, która zostanie wstrzyknięta do tego komponentu bean w kolejnych wywołaniach metod stanowych bean sesji, możesz mieć pewność, że zawsze będziesz mieć dostęp do tego samego kontekstu, a zatem nawet kolejne wywołania zwrócą ten sam przykład, ponieważ jest to ten sam kontekst.
Ponadto zmiany nie zostaną usunięte, dopóki fasola nie zostanie oznaczona do usunięcia lub nie zostanie przepłukana ręcznie.
Zarządzane przez aplikację
Zawsze możesz ręcznie utworzyć instancję fabryki menedżerów encji i menedżera encji. To jest to, co zwykle robisz w aplikacji JSE, prawda?
W przypadku tego rodzaju aplikacji zazwyczaj nie masz kontenera do obsługi transakcji JTA, prawda? Dlatego używasz transakcji lokalnych zasobów i jesteś odpowiedzialny za ręczne zatwierdzanie lub wycofywanie zmian.
W przypadku tego rodzaju aplikacji podczas tworzenia wystąpienia menedżera encji kontekst jest do niego automatycznie dołączany.
W zależności od aplikacji możesz zdecydować o utworzeniu globalnego menedżera encji, którego cykl życia jest powiązany z życiem samej aplikacji. To jest jeden menedżer podmiotu przez cały okres istnienia aplikacji. W takich przypadkach kontekst zostanie utworzony i zniszczony wraz z menedżerem encji.
Lub możesz utworzyć menedżera encji na rozmowę (tj. Transakcję) z użytkownikiem aplikacji. W tym przypadku zakres jest określany przez Ciebie, ale nadal Twój kontekst zostanie utworzony i zniszczony wraz z menedżerem encji.
źródło
EntityManager
musi być znikomy. Z mojego punktu widzenia EntityManager to tylko abstrakcja do zajmowania się jednostką pracy bieżącej transakcji. Uważam, że tworzenie i niszczenie jednej na transakcję jest w porządku. Teraz ma to inne konsekwencje, ponieważEntityManager
serwery jako transakcyjna pamięć podręczna dla twoich jednostek, a więc posiadające dobrze zdefiniowany zakres transakcji i właściwe postępowanie z jednostkami, mogą skorzystać z tej pamięci podręcznej.