„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Was kann passieren, wenn Sie die DTOs überspringen?

Was kann passieren, wenn Sie die DTOs überspringen?

Veröffentlicht am 02.08.2024
Durchsuche:802

What can happen if you skip the DTOs

Es ist schön, dass ein Framework wie SpringBoot so viele Dinge für Sie erledigen 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 Sie haben eine REST-API am Laufen, 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:

  • Schichtstruktur (z. B. hexagonale Architektur oder Ports und Adapter): Aus Gründen der Wartbarkeit ist es eine gute Idee, den externen Kommunikationscode vom Kern (Geschäftslogik) zu entkoppeln.
  • Sicherheit und Leistung: Wenn Sie die Datenbankstruktur in Ihrer API so offenlegen, wie sie ist, werden Sie bald an einen Punkt gelangen, an dem Sie mehr als nötig offenlegen; die von böswilligen Akteuren missbraucht werden oder Ressourcen (CPU, Speicher und Netzwerkbandbreite) verschwenden können
  • DTOs können im Gegensatz zu JPA-Entitäten unveränderlich sein (Sie können Java-Datensätze verwenden) und das ist gut für datengesteuerte (funktionale) Programmierstile, nette Unit-Tests, sicherere Parallelität usw.

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 Ausnahmen beim Datenbankzugriff 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 //!!
gekennzeichnet 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 konnte nicht geschrieben werden:

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. Können Sie 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 Ebenen 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.

Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/marianvarga/what-can-happen-if-you-skip-the-dtos-aaj?1 Bei Verstößen wenden Sie sich zum Löschen bitte an [email protected] Es
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3