Es ist schön, dass ein Framework wie SpringBoot so viele Dinge für Sie tun kann.
Sie benötigen lediglich eine JPA-Entitätsklasse sowie eine einfache Repository-Schnittstelle und SpringData bietet Ihnen alles, was Sie für typische CRUD-Datenbankoperationen benötigen.
Sie schreiben eine einfache REST-Controller-Klasse und eine REST-API läuft, oder?
Hey, aber du hast vergessen, ein DTO zu schreiben! Aber warum brauchen Sie es eigentlich, wenn Ihre App auch ohne funktionieren könnte?
Es gibt sicherlich einige allgemeine Gründe:
Aber auch andere seltsame Dinge können passieren. Ich werde Ihnen ein seltsames Beispiel zeigen, das auf meiner Erfahrung basiert.
Dieses GitHub-Repo enthält eine einfache Anwendung, die ohne die DTOs funktioniert. Es gibt eine Benutzerentität. Jeder Benutzer kann mehrere Transaktionen durchführen. Wir haben sogar eine Service-Bean zwischen dem Repository und dem RestController, die mögliche Datenbankzugriffsausnahmen abfängt.
Da wir eine produktionsreife Anwendung erstellen möchten, möchten wir nicht, dass Hibernate die DDL generiert. Stattdessen haben wir eine schema.sql, die die Tabellen erstellt (später wechseln wir möglicherweise zu Flyway oder Liquibase). Für unser einfaches Beispiel haben wir auch eine data.sql, damit unsere Tabellen nicht leer sind.
Wenn wir die Anwendung ausführen und den API-Endpunkt unter http://localhost:8080/users aufrufen, erhalten wir den erwarteten JSON, der die Benutzer und ihre Transaktionen enthält.
Lassen Sie uns nun auf die beiden Codezeilen in der Transaction-Klasse achten, die mit //!! markiert sind
@JsonIgnore //!!
Der erste Geruch ist, dass wir in der Transaction-Klasse die Annotation @JsonIgnore zur Benutzerreferenz hinzufügen mussten. Ohne diese Anmerkung stürzt die JSON-Serialisierung aufgrund der unendlichen Rekursion ab.
Stellen wir uns nun vor, dass jemand einen Fehler macht, indem er ein weiteres Feld (Beschreibung) zur Transaktionsentität hinzufügt, aber vergisst, die SQL-Anweisungen anzupassen (oder die Anwendung in einer Umgebung ausführt, in der die Schemaänderung nicht angewendet wurde).
private String-Beschreibung;//!!
Natürlich schlägt der API-Aufruf jetzt fehl. Aber schauen Sie sich die Fehlerbehandlung an! Die Catch-Klausel im UserService funktioniert nicht wie erwartet. Stattdessen können wir im Protokoll einen seltsamen Stack-Trace sehen:
GlobalExceptionHandler: Unerwarteter Fehler org.springframework.http.converter.HttpMessageNotWritableException: JSON:
Ich habe diese Situation einmal gesehen (offensichtlich bei einer Anwendung, die viel größer als dieses Beispiel ist) und es hat eine ganze Weile gedauert, bis ich verstanden habe, warum die SQL-Ausnahme dem Dienst entgangen ist und warum ich eine HttpMessageNotWritableException erhalten habe. Kannst du es sehen?
Was passiert, ist, dass die UserService-Klasse (über das UserRepository) nur die USERS-Datenbanktabelle abfragt. Die Transaktionsentitäten sind aufgrund des standardmäßigen verzögerten Ladens im Ruhezustand nicht Teil des Ergebnisses. Nur wenn der Jackson-Deserialisierer versucht, JSON aus der Benutzerinstanz zu erstellen, ruft er seine getTransactions-Methode auf, die Hibernate veranlasst, die Transaktionsentitäten abzurufen.
Aus diesem Grund erhalten wir einen seltsamen Stacktrace, der JSON- und SQL-Inhalte kombiniert. Die Ausnahme wird vom GlobalExceptionHandler abgefangen, der nicht weiß, was er damit machen soll. Aus diesem Grund lautet die Protokollmeldung „Unerwarteter Fehler“.
Ich hoffe, dass Sie mit dieser kleinen Übung besser verstehen, wie gefährlich es ist, die Vermischung verschiedener Schichten Ihrer Anwendung zuzulassen. Wenn Sie nur die „Sonnentag“-Szenarien Ihrer Anwendung sehen, solange diese noch klein ist, kann dies dazu führen, dass einige Entwickler weiterhin das Falsche tun, bis es zu spät ist.
Sie müssen nicht den Boilerplate-Code schreiben, der die Felder zwischen Ihrem DTO und den anderen Ebenen Ihrer Anwendung zuordnet. MapStruct kann das für Sie erledigen.
Das obige ist der detaillierte Inhalt vonWas kann passieren, wenn Sie die DTOs überspringen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!