Widziałem spring.jpa.open-in-view=true
właściwość w dokumentacji Spring Boot dla konfiguracji JPA.
- Czy jest to
true
wartość domyślna tej właściwości, jeśli w ogóle jej nie podano ?; - Co to naprawdę robi? Nie znalazłem dobrego wyjaśnienia tego;
- Czy to sprawia, że używasz
SessionFactory
zamiastEntityManagerFactory
? Jeśli tak, jak mogę to powiedzieć, aby umożliwić mi użycieEntityManagerFactory
zamiast tego?
Dzięki!
java
spring
jpa
spring-boot
spring-data
Carlos Alberto
źródło
źródło
Anty-wzór OSIV
Zamiast pozwalać warstwie biznesowej decydować, w jaki sposób najlepiej pobrać wszystkie skojarzenia wymagane przez warstwę widoku, OSIV (otwarta sesja w widoku) wymusza, aby kontekst trwałości pozostał otwarty, aby warstwa widoku mogła wyzwolić inicjalizację serwera proxy, jak pokazano na ilustracji na poniższym schemacie.
OpenSessionInViewFilter
WywołujeopenSession
metodę bazowegoSessionFactory
i pozyskuje noweSession
.Session
Jest zobowiązany doTransactionSynchronizationManager
.OpenSessionInViewFilter
NazywadoFilter
sięjavax.servlet.FilterChain
odwołania do obiektu, a wniosek jest dalej przetwarzanyDispatcherServlet
Nazywa i IT kieruje żądania HTTP do instrumentu bazowegoPostController
.PostController
wywołujePostService
uzyskać listęPost
podmiotów.PostService
Otwiera nową transakcję iHibernateTransactionManager
ponownie wykorzystuje ten samSession
, który został otwarty przezOpenSessionInViewFilter
.PostDAO
Pobiera listęPost
podmiotów bez inicjowania żadnej leniwe stowarzyszenie.PostService
transakcję bazową, aleSession
nie jest zamknięta, ponieważ została otwarta na zewnątrz.DispatcherServlet
rozpoczyna renderowania interfejsu użytkownika, który z kolei nawiguje leniwe skojarzenia i wyzwala ich inicjalizacji.OpenSessionInViewFilter
Można zamknąćSession
, a pod spodem połączenie z bazą danych jest zwolniony także.Na pierwszy rzut oka może to nie wyglądać na straszne, ale gdy spojrzysz na to z perspektywy bazy danych, seria błędów staje się bardziej oczywista.
Warstwa usług otwiera i zamyka transakcję bazy danych, ale później nie ma żadnej jawnej transakcji. Z tego powodu każda dodatkowa instrukcja wydana z fazy renderowania interfejsu użytkownika jest wykonywana w trybie automatycznego zatwierdzania. Automatyczne zatwierdzanie wywiera presję na serwer bazy danych, ponieważ każda instrukcja musi opróżnić dziennik transakcji na dysk, powodując w ten sposób duży ruch we / wy po stronie bazy danych. Jedną z optymalizacji byłoby oznaczenie
Connection
jako tylko do odczytu, co pozwoliłoby serwerowi bazy danych uniknąć zapisywania w dzienniku transakcji.Nie ma już rozdzielania obaw, ponieważ instrukcje są generowane zarówno przez warstwę usług, jak i przez proces renderowania interfejsu użytkownika. Pisanie testów integracyjnych, które potwierdzają liczbę generowanych instrukcji, wymaga przejścia przez wszystkie warstwy (sieć, usługa, DAO) podczas wdrażania aplikacji w kontenerze internetowym. Nawet w przypadku korzystania z bazy danych w pamięci (np. HSQLDB) i lekkiego serwera WWW (np. Jetty), te testy integracyjne będą wykonywane wolniej, niż gdyby warstwy były rozdzielane, a testy integracji zaplecza korzystały z bazy danych, podczas gdy testy integracji front-endu w ogóle kpili z warstwy usług.
Warstwa interfejsu użytkownika jest ograniczona do nawigacji po asocjacjach, które z kolei mogą powodować problemy z zapytaniami N + 1 . Chociaż Hibernate oferuje
@BatchSize
pobieranie skojarzeń w partiach iFetchMode.SUBSELECT
poradzi sobie z tym scenariuszem, adnotacje wpływają na domyślny plan pobierania, więc są stosowane w każdym biznesowym przypadku użycia. Z tego powodu kwerenda warstwy dostępu do danych jest o wiele bardziej odpowiednia, ponieważ można ją dostosować do aktualnych wymagań dotyczących pobierania danych dla przypadków użycia.Wreszcie, połączenie z bazą danych jest utrzymywane przez całą fazę renderowania interfejsu użytkownika, co wydłuża czas dzierżawy połączenia i ogranicza ogólną przepustowość transakcji z powodu przeciążenia puli połączeń bazy danych. Im dłużej połączenie jest utrzymywane, tym więcej innych współbieżnych żądań będzie czekać na połączenie z puli.
Spring Boot i OSIV
Niestety, OSIV (Open Session in View) jest domyślnie włączony w Spring Boot , a OSIV to naprawdę zły pomysł z punktu widzenia wydajności i skalowalności .
Dlatego upewnij się, że w
application.properties
pliku konfiguracyjnym znajduje się następujący wpis:Spowoduje to wyłączenie OSIV, abyś mógł sobie poradzić
LazyInitializationException
we właściwy sposób .Począwszy od wersji 2.0, Spring Boot wyświetla ostrzeżenie, gdy OSIV jest domyślnie włączony, więc możesz wykryć ten problem na długo przed tym, zanim wpłynie on na system produkcyjny.
Więcej informacji na temat OSIV można znaleźć w tym artykule .
źródło