Eine längere Beschreibung finden Sie in meinem Artikel " Open Session In View Anti-Pattern ". Andernfalls finden Sie hier eine Zusammenfassung, warum Sie Open Session In View nicht verwenden sollten.
Open Session In View verfolgt einen schlechten Ansatz beim Abrufen von Daten. Anstatt die Geschäftsschicht entscheiden zu lassen, wie alle Zuordnungen, die von der Ansichtsebene benötigt werden, am besten abgerufen werden, wird der Persistenzkontext geöffnet, damit die Ansichtsebene die Proxy-Initialisierung auslösen kann.

- Der
OpenSessionInViewFilterruft die openSessionMethode des Basiswerts auf SessionFactoryund erhält eine neue Session.
- Das
Sessionist an das gebunden TransactionSynchronizationManager.
- Das
OpenSessionInViewFilterruft die doFilterdie javax.servlet.FilterChainObjektreferenz und die Anforderung wird weiter verarbeitet
- Das
DispatcherServletwird aufgerufen und leitet die HTTP-Anforderung an den Basiswert weiter PostController.
- Das
PostControllerruft das PostServiceauf, um eine Liste der PostEntitäten zu erhalten.
- Das
PostServiceöffnet eine neue Transaktion und das HibernateTransactionManagerwiederverwendet das gleiche Session, das von der geöffnet wurde OpenSessionInViewFilter.
- Der
PostDAOruft die Liste der PostEntitäten ab, ohne eine verzögerte Zuordnung zu initialisieren.
- Das
PostServiceschreibt die zugrunde liegende Transaktion fest, wird jedoch Sessionnicht geschlossen, da sie extern geöffnet wurde.
- Das
DispatcherServletRendering der Benutzeroberfläche beginnt, die wiederum durch die verzögerten Zuordnungen navigiert und deren Initialisierung auslöst.
- Das
OpenSessionInViewFilterkann die schließen Session, 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 Connectionals 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 @BatchSizezum Abrufen von Zuordnungen in Stapeln und FetchMode.SUBSELECTzur 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 kann die Datenbankverbindung während der gesamten Rendering-Phase der Benutzeroberfläche (abhängig von Ihrem Verbindungsfreigabemodus) gehalten werden, 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.
Entweder wird die Verbindung zu lange gehalten, oder Sie erwerben / geben mehrere Verbindungen für eine einzelne HTTP-Anforderung frei, wodurch der zugrunde liegende Verbindungspool unter Druck gesetzt und die Skalierbarkeit eingeschränkt wird.
Frühlingsstiefel
Leider ist Open Session in View in Spring Boot standardmäßig aktiviert .
Stellen Sie also sicher, dass Sie in der application.propertiesKonfigurationsdatei den folgenden Eintrag haben:
spring.jpa.open-in-view=false
Dies wird deaktivieren OSIV, so dass Sie den Griff , LazyInitializationExceptionden richtigen Weg .