Ich habe spring.jpa.open-in-view=true
in der Spring Boot-Dokumentation eine Eigenschaft für die JPA-Konfiguration gesehen.
- Ist der
true
Standardwert für diese Eigenschaft, wenn er überhaupt nicht angegeben ist?; - Was macht das wirklich? Ich fand keine gute Erklärung dafür;
- Verwendet es Sie
SessionFactory
anstelle vonEntityManagerFactory
? Wenn ja, wie kann ich festlegen, dass ichEntityManagerFactory
stattdessen verwenden darf ?
Vielen Dank!
java
spring
jpa
spring-boot
spring-data
Carlos Alberto
quelle
quelle
Das OSIV-Anti-Pattern
Anstatt die Business-Schicht entscheiden zu lassen, wie alle Zuordnungen, die von der View-Schicht benötigt werden, am besten abgerufen werden, erzwingt OSIV (Open Session in View), dass der Persistenzkontext geöffnet bleibt, damit die View-Schicht die Proxy-Initialisierung auslösen kann, wie dargestellt durch das folgende Diagramm.
OpenSessionInViewFilter
ruft dieopenSession
Methode des Basiswerts aufSessionFactory
und erhält eine neueSession
.Session
ist an das gebundenTransactionSynchronizationManager
.OpenSessionInViewFilter
ruft diedoFilter
diejavax.servlet.FilterChain
Objektreferenz und die Anforderung wird weiter verarbeitetDispatcherServlet
wird aufgerufen und leitet die HTTP-Anforderung an den Basiswert weiterPostController
.PostController
ruft dasPostService
auf, um eine Liste derPost
Entitäten zu erhalten.PostService
öffnet eine neue Transaktion und dasHibernateTransactionManager
wiederverwendet das gleicheSession
, das von der geöffnet wurdeOpenSessionInViewFilter
.PostDAO
ruft die Liste derPost
Entitäten ab, ohne eine verzögerte Zuordnung zu initialisieren.PostService
schreibt die zugrunde liegende Transaktion fest, wird jedochSession
nicht geschlossen, da sie extern geöffnet wurde.DispatcherServlet
beginnt mit dem Rendern der Benutzeroberfläche, die wiederum durch die verzögerten Zuordnungen navigiert und deren Initialisierung auslöst.OpenSessionInViewFilter
kann die schließenSession
, und die zugrunde liegende Datenbankverbindung wird ebenfalls freigegeben.Auf den ersten Blick mag dies nicht schrecklich aussehen, aber sobald Sie es aus einer Datenbankperspektive betrachten, werden eine Reihe von Fehlern offensichtlicher.
Die Serviceschicht öffnet und schließt eine Datenbanktransaktion, danach findet jedoch keine explizite Transaktion statt. Aus diesem Grund wird jede zusätzliche Anweisung aus der UI-Rendering-Phase im Auto-Commit-Modus ausgeführt. Das automatische Festschreiben übt Druck auf den Datenbankserver aus, da jede Anweisung das Transaktionsprotokoll auf die Festplatte leeren muss, wodurch auf der Datenbankseite viel E / A-Verkehr verursacht wird. Eine Optimierung wäre, das
Connection
als schreibgeschützt zu markieren, wodurch der Datenbankserver das Schreiben in das Transaktionsprotokoll vermeiden kann.Es gibt keine Trennung von Bedenken mehr, da Anweisungen sowohl von der Service-Schicht als auch vom UI-Rendering-Prozess generiert werden. Das Schreiben von Integrationstests, die die Anzahl der generierten Anweisungen bestätigen, erfordert das Durchlaufen aller Ebenen (Web, Service, DAO), während die Anwendung auf einem Webcontainer bereitgestellt wird. Selbst wenn eine In-Memory-Datenbank (z. B. HSQLDB) und ein leichtgewichtiger Webserver (z. B. Jetty) verwendet werden, werden diese Integrationstests langsamer ausgeführt als wenn Schichten getrennt würden und die Back-End-Integrationstests die Datenbank verwenden würden, während die Front-End-Integrationstests verspotteten die Service-Schicht insgesamt.
Die UI-Ebene ist auf das Navigieren in Assoziationen beschränkt, was wiederum N + 1-Abfrageprobleme auslösen kann . Obwohl Hibernate Angebote
@BatchSize
zum Abrufen von Zuordnungen in Stapeln undFetchMode.SUBSELECT
zur Bewältigung dieses Szenarios anbietet , wirken sich die Anmerkungen auf den Standardabrufplan aus, sodass sie auf jeden Geschäftsanwendungsfall angewendet werden. Aus diesem Grund ist eine Datenzugriffsschichtabfrage viel besser geeignet, da sie auf die aktuellen Anforderungen für das Abrufen von Anwendungsfalldaten zugeschnitten werden kann.Last but not least wird die Datenbankverbindung während der gesamten UI-Rendering-Phase gehalten, wodurch die Verbindungslease-Zeit verlängert und der gesamte Transaktionsdurchsatz aufgrund einer Überlastung des Datenbankverbindungspools begrenzt wird. Je länger die Verbindung gehalten wird, desto mehr andere gleichzeitige Anforderungen warten darauf, eine Verbindung aus dem Pool zu erhalten.
Spring Boot und OSIV
Leider ist OSIV (Open Session in View) in Spring Boot standardmäßig aktiviert , und OSIV ist aus Sicht der Leistung und Skalierbarkeit eine wirklich schlechte Idee .
Stellen Sie also sicher, dass Sie in der
application.properties
Konfigurationsdatei den folgenden Eintrag haben:Dies wird deaktivieren OSIV , so dass Sie den Griff ,
LazyInitializationException
den richtigen Weg .Ab Version 2.0 gibt Spring Boot eine Warnung aus, wenn OSIV standardmäßig aktiviert ist, sodass Sie dieses Problem erkennen können, lange bevor es ein Produktionssystem betrifft.
Weitere Informationen zu OSIV finden Sie in diesem Artikel .
quelle