Maison > Java > javaDidacticiel > le corps du texte

Que peut-il arriver si vous ignorez les DTO

WBOY
Libérer: 2024-07-30 09:46:01
original
559 Les gens l'ont consulté

What can happen if you skip the DTOs

C'est bien qu'un framework comme SpringBoot puisse faire autant de choses pour vous.

Vous avez juste besoin d'une classe d'entité JPA et d'une interface de référentiel simple et SpringData vous offre tout ce dont vous avez besoin pour les opérations de base de données CRUD typiques.

Vous écrivez une simple classe de contrôleur REST et vous avez une API REST en cours d'exécution, n'est-ce pas ?

Hé, mais tu as oublié d'écrire un DTO ! Mais pourquoi en avez-vous réellement besoin alors que votre application pourrait fonctionner sans lui ?

Il y a certainement quelques raisons générales :

  • structure en couches (par exemple, architecture hexagonale ou ports et adaptateurs) : pour des raisons de maintenabilité, il est judicieux de découpler le code de communication externe du noyau (logique métier)
  • sécurité et performances : si vous exposez la structure de la base de données dans votre API telle quelle, vous arriverez bientôt à un point où vous en exposerez plus que nécessaire ; qui peuvent être utilisés à mauvais escient par des acteurs malveillants ou gaspiller des ressources (CPU, mémoire et bande passante réseau)
  • Les DTO, contrairement aux entités JPA, peuvent être immuables (vous pouvez utiliser des enregistrements Java) et c'est bon pour le style de programmation (fonctionnel) basé sur les données, les tests unitaires agréables, la concurrence plus sûre, etc.

Mais d’autres choses étranges peuvent aussi arriver. Je vais vous montrer un exemple étrange basé sur mon expérience.

Ce dépôt GitHub contient une application simple qui fonctionne sans les DTO. Il existe une entité utilisateur, chaque utilisateur peut avoir plusieurs transactions. Nous avons même un bean Service entre le référentiel et le RestController, interceptant d'éventuelles exceptions d'accès à la base de données.

Comme nous voulons créer une application prête pour la production, nous ne voulons pas qu'Hibernate génère le DDL. Au lieu de cela, nous avons un schema.sql qui crée les tables (plus tard, nous pourrons passer à Flyway ou Liquibase). Pour notre exemple simple, nous avons également un data.sql pour que nos tables ne soient pas vides.

Lorsque nous exécutons l'application et appelons le point de terminaison de l'API à l'adresse http://localhost:8080/users, nous obtenons le JSON attendu contenant les utilisateurs et leurs transactions.

Faisons maintenant attention aux deux lignes de code de la classe Transaction, marquées //!!

@JsonIgnore //!!

La première odeur est que dans la classe Transaction, nous avons dû ajouter l'annotation @JsonIgnore à la référence User. Sans cette annotation, la sérialisation JSON plante en raison d'une récursivité infinie.

Imaginons maintenant que quelqu'un fasse une erreur en ajoutant un autre champ (description) à l'entité Transaction, mais oublie d'ajuster les instructions SQL (ou exécute l'application dans un environnement où le changement de schéma n'a pas été appliqué).

description de la chaîne privée ;//!!

Bien sûr, l'appel API échoue désormais. Mais regardez la gestion des erreurs ! La clause catch à l'intérieur du UserService ne fonctionne pas comme prévu. Au lieu de cela, nous pouvons voir une étrange trace de pile dans le journal :
GlobalExceptionHandler : erreur inattendue org.springframework.http.converter.HttpMessageNotWritableException : impossible d'écrire JSON :

J'ai vu une fois cette situation (clairement, avec une application beaucoup plus grande que cet exemple) et il m'a fallu un certain temps pour comprendre pourquoi l'exception SQL échappait au service et pourquoi j'obtenais une HttpMessageNotWritableException. Pouvez-vous le voir ?

Ce qui se passe, c'est que la classe UserService (via le UserRepository) interroge uniquement la table de la base de données USERS. Les entités Transaction ne font pas partie du résultat en raison du chargement différé par défaut d'Hibernate. Ce n'est que lorsque le désérialiseur Jackson tente de créer du JSON à partir de l'instance User qu'il invoque sa méthode getTransactions qui permet à Hibernate de récupérer les entités Transaction.

C'est pourquoi nous obtenons une étrange trace de pile combinant des éléments JSON et SQL. L'exception est interceptée par le GlobalExceptionHandler qui ne sait pas quoi en faire, c'est pourquoi le message du journal est "Erreur inattendue".

J'espère que ce petit exercice vous fera comprendre plus profondément à quel point il est dangereux de permettre aux différentes couches de votre application de se mélanger. Voir uniquement les scénarios de « journée ensoleillée » de votre application alors qu'elle est encore petite peut amener certains développeurs à continuer de faire la mauvaise chose jusqu'à ce qu'il soit trop tard.

Vous n'êtes pas obligé d'écrire le code passe-partout mappant les champs entre votre DTO et les autres couches de votre application. MapStruct peut le faire pour vous.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!