Jeder hier hat Recht, jeder auf seine Weise, und deshalb liegt jeder hier falsch.
"Die Geschichte der Drei" (A. und B. Strugatsky)
Wenn Sie Spring Data JPA verwenden, wird nach dem Update auf Spring Boot 2 beim Starten der Anwendung möglicherweise eine neue Warnung im Protokoll angezeigt:
spring.jpa.open-in-view ist standardmäßig aktiviert. Daher können Datenbankabfragen während des Renderns der Ansicht ausgeführt werden. Konfigurieren Sie spring.jpa.open-in-view explizit, um diese Warnung zu deaktivieren.
In diesem Artikel werde ich versuchen zu erklären, was es bedeutet, wer schuld ist und was zu tun ist.
Um eine vollwertige Anwendung beim Spring Boot @SpringBootApplication
, ist nur eine @SpringBootApplication
Annotation @SpringBootApplication
. Um dies zu ermöglichen, verwendet das Framework eine große Anzahl von Autokonfigurationen und Standardeinstellungen. Darüber hinaus mussten Spring Boot-Entwickler einige Anwendungsentwicklungskonzepte aus mehreren alternativen Optionen auswählen, damit der Benutzer sie nicht explizit auswählen musste. Dies ist einerseits gut für einen schnellen Start und eine einfache Entwicklung, andererseits kann sich nach einer Weile herausstellen, dass ein Standardkonzept / -paradigma / -einstellung nicht für das Projekt geeignet ist, und es muss viel Arbeit geleistet werden, um es aufzugeben. Ein solches Konzept ist der OSIV-Modus (Open Session In View) , der standardmäßig in Spring Boot enthalten ist.
In diesem Modus bleibt die Sitzung im Ruhezustand während der gesamten Verarbeitung der HTTP-Anforderung geöffnet, einschließlich der Phase der Erstellung der Ansicht (JSON-Ressource oder HTML-Seite). Dies ermöglicht es, Daten nach dem Festschreiben einer Transaktion in der Geschäftslogikschicht träge in die Präsentationsschicht zu laden. Beispielsweise fordern wir die Artikelentität aus der Datenbank an. Der Artikel sollte zusammen mit Kommentaren angezeigt werden. Mit OSIV können Sie beim Rendern von HTML einfach die getComments()
aufrufen, und Kommentare werden in einer separaten Anforderung geladen. Wenn der OSIV-Modus deaktiviert ist, wird eine LazyInitializationException
, da die Sitzung bereits geschlossen ist und die LazyInitializationException
nicht mehr von Hibernate verwaltet wird. Die meisten Hibernate-Entwickler haben eine LazyInitializationException
. Mit OSIV können Sie dies vermeiden, indem Sie in jeder Phase der Verarbeitung der HTTP-Anforderung nach Bedarf Daten laden.
OSIV in Spring Boot wird mithilfe der OpenEntityManagerInViewInterceptor
- OpenEntityManagerInViewInterceptor
implementiert. Im Gegensatz zu reinem Frühling ist es hier standardmäßig aktiviert.
OSIV gilt als Antimuster. Das Beste ist, dass die schädliche Seite seines Artikels von Vlad Mihalcea, einem der Entwickler von Hibernate: The Open Session In View Anti-Pattern, erklärt wurde . Wichtige Punkte:
- Datenbankabfragen ohne Transaktion werden im Auto-Commit-Modus ausgeführt und stark geladen.
- Es gibt keine Aufgabentrennung, jede Anwendungsschicht kann SQL-Abfragen generieren, was das Testen schwierig macht.
- Es gibt ein n + 1-Problem, wenn jede Sammlung, die sich auf eine Entität bezieht, in eine separate Anforderung geladen wird.
- Lange Verbindungen zur Datenbank erhöhen erneut die Belastung und verringern den Durchsatz.
Dies sind ziemlich unangenehme Probleme des OSIV-Modus und anscheinend starke Argumente dafür, ihn nicht zu verwenden. Bei der Aufforderung, es standardmäßig zu deaktivieren , haben die Entwickler von Spring Boot jedoch auch gute Gründe angegeben, warum OSIV für neue Projekte aktiviert werden sollte:
- Abwärtskompatibilität. Bei vorhandenen Anwendungen beim Upgrade auf Spring Boot 2 können aufgrund von deaktiviertem OSIV Fehler und Bugs auftreten. Um dies zu vermeiden, müssen Sie nur den Einzelwert
spring.jpa.open-in-view
Dies macht es jedoch auch schwierig, auf die neue Version zu wechseln. - Benutzerfreundlichkeit für Anfänger und ein schneller Start sind für Spring Boot wichtig. Wenn OSIV deaktiviert ist, ist es für Anfänger möglicherweise nicht klar, warum eine so intuitiv erwartete Sache wie das Empfangen einer Sammlung verwandter Elemente beim Zugriff auf eine Entitätsmethode nicht funktioniert. Stattdessen erhält der Benutzer eine
LazyInitializationException
, die seinen Pfad zu einer laufenden Anwendung verlangsamt. - Mit OSIV können Sie die Einfachheit, Benutzerfreundlichkeit und Entwicklungsgeschwindigkeit von Code erhöhen.
- Es ist schwierig, einfache Beispiele dafür zu finden, wie eine Anwendung ohne OSIV erstellt werden sollte.
- Ohne OSIV muss die Geschäftslogikschicht wissen, wie die Daten in der Benutzeroberfläche dargestellt werden, dh welches DTO benötigt wird oder welche zugehörigen Daten zusammen mit der Stammentität geladen werden sollen. Dies ist wiederum das Fehlen einer Aufteilung der Verantwortung.
Wir können also zwei Ansichten zu diesem Problem unterscheiden. Aus Sicht des Datenbankarchitekten (DBA) ist Open Session In View sicherlich nicht akzeptabel, da die Interaktion der Anwendung mit der Datenbank nicht optimal organisiert ist und eine erhöhte Last erzeugt. Wir verwenden jedoch häufig weniger optimale Lösungen für die Geschwindigkeit, die einfache Entwicklung und die einfachen Lernwerkzeuge. Wir schreiben in verwalteten Sprachen, verwenden Textdatenformate für die Netzwerkinteraktion und so weiter. Um die Entwicklung und den schnellen Start von Anfängern zu vereinfachen, können Sie mit OSIV die kognitive Belastung und die Anzahl der Konzepte reduzieren, die für die Entwicklung der Anwendung erforderlich sind. Wenn sich der Entwickler für JPA entschied, stimmte er bereits einer Leistungsminderung im Austausch für die Bequemlichkeit der Entwicklung zu. JPA hilft dabei, Freunde zum Objekt und zu relationalen Datenmodellen zu machen. Wenn wir im Objektstil arbeiten, um verwandte Elemente zu erhalten, wenden wir uns einfach der Entitätsmethode zu (auch wenn sie sich in der Präsentationsebene befindet). Sie ist einfach, logisch und intuitiv zu erwarten, obwohl diese Einfachheit täuscht.
Es gibt viele Beispiele und Tutorials für die Arbeit in der offenen Sitzung. Im Ansichtsmodus ist die Architektur insgesamt klar: Die Serviceschicht fordert eine JPA-Entität an, die Präsentationsschicht serialisiert sie direkt in JSON über ein Zwischen-DTO oder verwendet die Daten daraus zum Rendern einer HTML-Seite.
Weniger klar ist, wie man ohne OSIV arbeitet. Einer der Spring-Entwickler in der genannten Anfrage beschwert sich darüber, sie schreien viel über das Antimuster, aber es gibt keine einfachen Beispiele dafür, wie man ohne es leben kann. In dieser Ausführungsform können Entitäten nur zum Schreiben und Lesen mehrerer DTOs verwendet werden, die für jeden Datensatz in der Benutzeroberfläche getrennt sind und direkt aus der Datenbank zugeordnet werden. Oder benutzerdefinierte SQL-Abfragen, die den Join der erforderlichen zugehörigen Sammlungen für eine bestimmte Webanfrage beschreiben. Das heißt, mehr Boilerplate und eine Beschreibung der Anforderungen der Benutzeroberfläche in der Geschäftslogikschicht. Wenn OSIV deaktiviert ist, beginnt die JPA-Abstraktion zu fließen. Die Anwendung beschreibt weitere technische Details der Interaktion mit der Datenbank.
Somit ist die Entwicklung mit OSIV einfacher. Das Problem ist jedoch, dass Sie, wenn Sie es in Zukunft aufgeben möchten, viel wiederholen müssen. Das Konzept der Arbeit mit der Datenbank im Projekt durch Festlegen einer Eigenschaft kann nicht geändert werden. Möglicherweise müssen Sie die gesamte Anwendungsarchitektur wiederholen. Das Aufgeben von OSIV kann jedoch eine vorzeitige Optimierung sein, die die Entwicklungsgeschwindigkeit verlangsamt, was beispielsweise für einen Start kritisch sein kann. Sie können OSIV verwenden und Datenbankabfragen nur an den langsamsten Stellen optimieren. Beispielsweise leidet das Abfragen von Entitätssammlungen am meisten unter dem Problem n + 1, wenn jede Entität mehrere Abfragen aus verwandten Sammlungen abruft.
Wenn Sie es also richtig machen wollen, müssen Sie ohne OSIV entwickeln. Wenn jedoch die Entwicklungsgeschwindigkeit und die Einfachheit des Codes wichtig sind, können Sie diesen Modus verwenden, der mit einem gewissen Leistungsverlust verbunden ist.
Die Hauptsache ist, dass dieses Leistungsproblem nach einigen Jahren nicht zu einer großen technischen Verschuldung wird. Es ist doppelt gefährlich, wenn die Entwickler nicht vermuten, dass sich diese Schulden in ihnen ansammeln, weil Spring Boot stillschweigend das Konzept von Open Session In View für sie gewählt hat. Daher ist es hervorragend, dass aufgrund der oben genannten Anfrage beschlossen wurde, im Protokoll eine Warnung über den verwendeten Modus anzuzeigen, die ich am Anfang des Artikels zitiert habe.
Ich hoffe, dass die Warnung und dieser Artikel über ihn Entwicklern helfen, eine fundiertere Entscheidung zu treffen - ob das Konzept von Open Session In View in einer Anwendung auf Spring Boot verwendet werden soll. Ich habe die Hauptargumente dafür und dagegen zitiert und diskutiert, und ich rate auch, die ursprüngliche Diskussion zu lesen. Dieses Problem zeigt, dass eine große Anzahl von automatischen Konfigurationen und Standardeinstellungen in Spring / Spring Boot für unaufmerksame Entwickler gefährlich sein kann.
Verwenden Sie OSIV in Spring Boot-Anwendungen? Wenn nicht, wie ist die Architektur für die Interaktion der Präsentationsschicht mit der Datenbank organisiert? Welche Techniken und / oder Bibliotheken werden dafür verwendet?