Comprendre la projection de données dans Spring Boot avec Hibernate

Cet article se penchera sur la projection de données dans le contexte de Spring Boot et Hibernate. Ce blog examinera l’importance de la projection de données, ses avantages et ses inconvénients. De plus, je fournirai une explication complète sur la façon de l’implémenter efficacement dans vos applications Spring Boot.
Qu’est-ce que la projection de données ?
La projection de données dans les requêtes de base de données implique la sélection d’attributs spécifiques à partir d’une ou plusieurs entités ou tables et la récupération uniquement de ces attributs dans l’ensemble de résultats. Cette technique est utile lorsque vous n’avez pas besoin de l’objet entité complet et vise à améliorer les performances en récupérant uniquement les données nécessaires.
Pourquoi utiliser la projection de données ?
L’utilisation de la projection de données dans Spring Boot offre plusieurs avantages :
- Optimisation des performances : La projection de données permet de récupérer des champs spécifiques à partir de requêtes de base de données, plutôt que de récupérer des objets complets. Cela entraîne une diminution notable du transfert de données entre l’application et la base de données, améliorant ainsi les temps de réponse et les performances globales.
- Efficacité de la bande passante : Opter pour les champs essentiels permet de réduire l’utilisation de la bande passante réseau de votre application, ce qui est crucial lorsque vous traitez des ensembles de données étendus. Ceci est particulièrement important pour les applications fonctionnant dans des environnements avec des ressources réseau limitées ou lorsque des dépenses de transfert de données doivent être prises en compte.
- Utilisation réduite de la mémoire : En récupérant uniquement les champs nécessaires de la base de données, cela réduit la quantité de mémoire requise pour stocker les données. Cette optimisation peut améliorer considérablement l’efficacité de l’utilisation de la mémoire, en particulier lorsqu’il s’agit de jeux de données volumineux.
- Sécurité améliorée : La projection de données peut améliorer la sécurité en limitant la divulgation de champs de données sensibles ou redondants dans les réponses de votre application.
Techniques de projection de données :
- Requêtes JPQL (Java Persistence Query Language): JPQL permet aux développeurs d’écrire des requêtes de type SQL pour récupérer des champs spécifiques à partir d’entités. En sélectionnant uniquement les champs obligatoires dans la clause SELECT, vous pouvez réaliser une projection de données.
@Query("SELECT NEW com.ttn.dataProjection.dto.UserDetailsProjectionDTO(u.name, u.email, a.city, a.pincode) FROM UserDetails u JOIN u.address a")
List<UserDetailsProjectionDTO> findAllByActiveTrueOrderByNameDesc();
- Projections JPA des données de printemps : Spring Data JPA fournit une fonctionnalité puissante appelée projections, qui permet de définir des interfaces pour représenter le sous-ensemble de données souhaité. Ces projections peuvent être utilisées directement dans les méthodes de référentiel.
@Data
public class UserDetailsProjectionDTO {
private String name;
private String email;
private String city;
private String pincode;
public UserDetailsProjectionDTO(String name, String email, String city, String pincode) {
this.name = name;
this.email = email;
this.city = city;
this.pincode = pincode;
}
}
public interface RolesProjection {
String getName();
}
public interface AddressProjection {
String getCity();
String getPincode();
}
- Projection DTO (objet de transfert de données) : Une autre approche courante consiste à utiliser des DTO pour représenter les données projetées. Les DTO sont des objets Java simples qui contiennent uniquement les champs nécessaires à un cas d’utilisation particulier.
@Data
@JsonPropertyOrder({"name","email","mobile","address","roles"})
public class UserDetailsDto {
private String name;
private String email;
private String mobile;
private List<AddressDto> address;
private List<RolesDto> roles;
}
@Data
public class AddressDto {
private String city;
private String pincode;
}
@Data
public class RolesDto {
private String name;
}
public List<UserDetailsDto> getAllByDto() {
List<UserDetails> userDetailsList= userDetailsRepository.findAll();
List<UserDetailsDto> userDetailsDtoList=new ArrayList<>();
userDetailsList.forEach(userDetails -> {
UserDetailsDto userDetailsDto=new UserDetailsDto();
BeanUtils.copyProperties(userDetails,userDetailsDto);
List<AddressDto> addressDtoList=new ArrayList<>();
userDetails.getAddress().forEach(address -> {
AddressDto addressDto=new AddressDto();
BeanUtils.copyProperties(address,addressDto);
addressDtoList.add(addressDto);
});
userDetailsDto.setAddress(addressDtoList);
List<RolesDto> rolesDtoList=new ArrayList<>();
userDetails.getRoles().forEach(roles -> {
RolesDto rolesDto=new RolesDto();
BeanUtils.copyProperties(roles,rolesDto);
rolesDtoList.add(rolesDto);
});
userDetailsDto.setRoles(rolesDtoList);
userDetailsDtoList.add(userDetailsDto);
});
return userDetailsDtoList;
}
Détails du projet :
Dans le contexte d’un système de gestion des utilisateurs, considérons trois entités : UserDetails, Roles et Address. Dans le cadre de ce projet, j’ai développé un ensemble de cinq API pour faciliter diverses fonctionnalités.
- Créez une API pour l’utilisateur.
- Récupération de tous les utilisateurs avec entité.
- La récupération des détails de l’utilisateur, y compris des champs spécifiques d’une entité, peut être réalisée en utilisant le « Projections JPA des données de printemps » technique.
- La récupération des détails de l’utilisateur, y compris des champs spécifiques d’une entité, peut être réalisée en utilisant le « Projection DTO (objet de transfert de données) » technique.
- La récupération des détails de l’utilisateur, y compris des champs spécifiques d’une entité, peut être réalisée en utilisant le « Requêtes JPQL (Java Persistence Query Language) » technique.
@RequestMapping(value = "/user")
@RestController
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping(value = "/create")
public UserDetails createUser(@RequestBody UserDetails userDetails) {
return userService.createUser(userDetails);
}
@GetMapping(value = "/getAll")
public List<UserDetails> getAllUsers(){
return userService.getAllUsers();
}
@GetMapping(value = "/getAllByProjection")
public List<UserDetailsProjection> getAllByProjection(){
return userService.getAllUsersByProjection();
}
@GetMapping(value = "/getAllByDto")
public List<UserDetailsDto> getAllByDto(){
return userService.getAllByDto();
}
@GetMapping(value = "/getAllByJPQL")
public List<UserDetailsProjectionDTO> getAllByJPQL(){
return userService.getAllByJPQL();
}
}
Vous trouverez ci-dessous quelques avantages et inconvénients des techniques de projection de données printanières grâce auxquelles vous pourrez découvrir quelle technique vous pouvez utiliser en fonction de votre situation.
Requêtes JPQL :
Avantages:
- Contrôle à grain fin : Les requêtes JPQL offrent un contrôle précis sur les champs à sélectionner, permettant aux développeurs de récupérer exactement ce dont ils ont besoin.
- La flexibilité: Les développeurs peuvent exploiter toute la puissance de JPQL, notamment les jointures, les agrégats et les conditions de filtrage complexes.
- Optimisation des performances : En sélectionnant uniquement les champs nécessaires, les requêtes JPQL peuvent optimiser les performances de la base de données en réduisant la quantité de données transférées.
Les inconvénients :
- Complexité syntaxique : L’écriture de requêtes JPQL peut être plus complexe et plus détaillée que d’autres techniques de projection, en particulier pour les développeurs moins familiers avec la syntaxe de type SQL.
- Potentiel de fautes de frappe et d’erreurs : En raison de la nature dynamique des requêtes JPQL, il existe un risque plus élevé de fautes de frappe ou d’erreurs dans la construction des requêtes, entraînant des problèmes d’exécution.
Projections JPA des données de printemps :
Avantages :
- Type de sécurité : Les projections Spring Data JPA fournissent des interfaces ou des classes de type sécurisé pour représenter les données projetées, réduisant ainsi le risque d’erreurs d’exécution.
- Simplicité: Les projections peuvent être définies comme des interfaces ou des classes avec des méthodes getter, ce qui les rend faciles à comprendre et à maintenir.
- Intégré au référentiel : Les projections peuvent être intégrées de manière transparente aux méthodes de référentiel, permettant des définitions de requêtes claires et concises.
- Code passe-partout réduit : Les projections éliminent le besoin de mapper manuellement les résultats des requêtes aux DTO ou à d’autres structures de données, réduisant ainsi le code passe-partout.
Les inconvénients:
- Expressivité limitée : Lorsqu’il s’agit de constructions de requêtes complexes, les requêtes JPQL bénéficient d’une prise en charge plus large que les projections, ce qui pourrait limiter leur utilité dans certaines situations.
- Définition statique : Pour créer des projections, il est nécessaire d’avoir des interfaces prédéfinies. Toutefois, cette approche pourrait ne pas être très flexible pour les projections dynamiques.
Projection DTO :
Avantages:
- La flexibilité: La projection DTO permet aux développeurs de définir des objets de transfert de données personnalisés adaptés à des cas d’utilisation spécifiques, offrant ainsi une flexibilité maximale.
- Contrôle de sérialisation : Les DTO permettent un contrôle précis des données à sérialiser et à transmettre sur le réseau, améliorant ainsi les performances et réduisant l’utilisation de la bande passante.
- Encapsulation : Les DTO encapsulent les données projetées, favorisant ainsi une meilleure encapsulation et une meilleure séparation des problèmes au sein de l’architecture de l’application.
- Réutilisabilité : Les DTO peuvent être réutilisés dans plusieurs requêtes ou cas d’utilisation, favorisant ainsi la réutilisation et la maintenabilité du code.
Les inconvénients:
- Frais généraux de cartographie supplémentaires : La projection DTO nécessite un code de mappage supplémentaire pour transformer les objets d’entité en DTO, ce qui peut introduire une surcharge, en particulier pour les mappages complexes.
- Synchronisation manuelle : Les développeurs doivent assurer la synchronisation entre les attributs d’entité et les champs DTO, ce qui peut s’avérer fastidieux et sujet aux erreurs, en particulier dans les grands projets.
- Code passe-partout : Les DTO nécessitent souvent d’écrire du code passe-partout supplémentaire pour définir les classes, les constructeurs, les getters et les setters, ce qui augmente l’effort de développement et la verbosité.
Code source du projet :
https://github.com/ankit25496kumar/data-projection
Référence :
VOUS TROUVEZ CECI UTILE ? PARTAGEZ-LE
Source link