Je cherche un bon moyen de créer des objets de transfert de données (DTO) à partir d'une entité JPA et inversement. Je souhaite envoyer le DTO au format JSON à un client, puis recevoir le DTO modifié et le sauvegarder dans. la base de données. Il serait plus facile d’exécuter la méthode de fusion à partir de EntityManager sur l’objet reçu après son analyse de JSON à sa classe Java.
Par exemple, il existe l'entité suivante et la méthode Rest pour enregistrer l'objet modifié:
@Entity
@Table(name="CUSTOMER")
public class Customer {
@Id
Long id;
@Version
Long version;
String name;
String address;
String login;
String password;
String creditCardNumber;
@OneToMany(cascade = CascadeType.ALL)
List<Foo> fooList;
... Getter() and Setter()
}
private EntityManager em;
@POST
@Path("/saveCustomer")
public void saveCustomer ( Customer customer) {
em.merge(customer);
return;
}
Cela fonctionne bien tant que j'envoie la classe d'entité entière en JSON et que l'entité entière est renvoyée. Ensuite, EntityManager fusionnera l'objet modifié à la base de données. Mais lorsque je souhaite uniquement fournir un sous-ensemble de l'entité (par exemple, uniquement le nom et l'adresse du client), des problèmes se posent:
Quel serait le meilleur moyen de créer un sous-ensemble d'une entité?
-Écrire les DTO pour l'entité à la main? Cela générera un code en double pour chaque sous-ensemble de l'entité, qui doit être maintenu.
Comment fusionner un DTO qui est un sous-ensemble d'une entité dans la base de données?
-L'utilisation de la méthode merge () de EntityManager ne fonctionne pas. Au début, le DTO n'est pas une entité et ne peut donc pas être fusionné. Et créer simplement une entité à partir du DTO aura des valeurs non définies dans l'entité. Après une fusion, les valeurs seront NULL dans la base de données.
Une idée que j’ai suggérée était de spécifier des entités supplémentaires pour chaque sous-ensemble que je souhaite avoir pour une entité. (Comme une vue de base de données) Ce serait un code en double, mais cela pourrait résoudre le problème de la fusion du DTO avec la base de données. (Et peut-être que ce code peut être généré automatiquement)
Par exemple, Entity CustomerView1 est lié à la même table que la classe Customer, mais fournit uniquement le nom et l'adresse du client. C'est un DTO pour la vraie classe Customer, qui peut être envoyé au format JSON et modifié en dehors du serveur. Cette classe peut également être fusionnée à la base de données par EntityManager.
@Entity
@Table(name="CUSTOMER")
public class CustomerView1 {
@Id
Long id;
@Version
Long version;
String name;
String address;
... Getter() and Setter()
}
Mais j’ai des doutes sur cette solution, je ne sais pas si cela va gâcher la mise en cache d’entités de JPA et causer des problèmes.
Ma question est la suivante: existe-t-il un modèle permettant de résoudre les problèmes de duplication de code pour les DTO et de fusionner les DTO dans la base de données?
Ou existe-t-il une bibliothèque à cet effet? - Quelque chose, comme la génération automatique pour les DTO et la copie des DTO dans l'entité réelle, pour permettre de les fusionner avec EntityManager.
Si la différence de taille entre l'entité et le DTO n'est pas considérable, vous pouvez opter pour l'envoi de l'entité.
Lorsque vous utilisez des DTO, pour résoudre des problèmes de concurrence tels que lost update , vous devez incorporer la version de l'entité dans votre DTO.
Si vous n'utilisez pas la version de l'entité et que la ligne sous-jacente est modifiée entre les méthodes REST GET et PUT, vous annulerez les modifications que l'utilisateur final ne savait pas vraiment.
Chaque fois que je dois modifier une entité (Créer, Mettre à jour, Supprimer), je me fie aux mécanismes JPA et Hibernate Optimistic Locking .
Pour les listes d’interface utilisateur, les tables et les résultats de recherche, les DTO sont une option viable, car vous ne vous intéressez qu'à une projection de votre entité d'origine. De cette façon, vous accélérez les extractions et vous pouvez bénéficier d'autres fonctionnalités SQL (fonctions de fenêtre) non prises en charge par JPA.
On dirait que ce que vous décrivez correspond exactement à ce que Les vues d'entité Blaze-Persistence ont été faites pour. La version actuelle prend uniquement en charge la création du modèle en lecture, c'est-à-dire le modèle que vous envoyez au client, mais la partie du modèle d'écriture est presque terminée. Les vues d'entité établissent la correspondance entre une représentation DTO d'interface/classe abstraite et le modèle d'entité. La bibliothèque exploite au mieux les informations de mappage pour mettre en œuvre toutes sortes d’optimisations de performances.
Examinez le modèle de conception Objet de valeur qui règle directement votre problème.
Ce tutoriel est une bonne introduction aux objets de valeur.