Ressource
Définition
Les projections sont des techniques qui permettent de sélectionner et de récupérer uniquement les données nécessaires d’une base de données.
Elles permettent ainsi de
- réduire la quantité de données transférées
- améliorer donc la performance du système
Ainsi au lieu de tout récupérer (SELECT *), nous sélectionnons les colonnes qui nous intéressent
em.createQuery("SELECT b.title, b.publisher, b.author.name FROM Book b");Note :
b.author.nameest autorisé car dans la classeBooknous avons une relation@ManyToOne private Author author;
Types de Projections
JPA supportent principalement trois types de projections :
- Projections d’entités : Récupération complète des entités.
- Projections de valeurs scalaires : Sélection de colonne spécifique
- Projections DTO : Utilisation d’objets personnalisés pour transporter des données spécifiques.
Projection d’entité
C’est la plus commune, on récupère toute l’entité soit via un find() soit avec JPQL
TypedQuery<Book> query = entityManager.createQuery("SELECT b FROM Book b", Book.class);
List<Book> books = query.getResultList();
Projections de Valeurs Scalaires
Les projections de valeurs scalaires permettent de sélectionner des colonnes spécifiques ou des résultats de fonctions agrégées, sans charger des entités complètes.
// Récupère un tableau d'Object
TypedQuery<Object[]> query = entityManager.createQuery("SELECT b.title, b.publisher FROM Book b", Object[].class);
List<Object[]> results = query.getResultList();
for (Object[] result : results) {
String title = (String) result[0];
String publisher = (String) result[1];
}Très pratique, mais pas très lisible, il serait intéressant d’utiliser un type précis au lieux de Object ⇒ DTO
Projections DTO (Data Transfer Object)
Les projections DTO impliquent l’utilisation de classes personnalisées pour encapsuler les données nécessaires, offrant une structure claire.
public class BookDTO {
private String title;
private String authorName;
private String publisher;
}// Pas Object[] mais typé avec le DTO
TypedQuery<BookDTO> query = entityManager.createQuery("SELECT new com.example.BookDTO(b.title, b.author.name, b.publisher) FROM Book b", BookDTO.class);
List<BookDTO> bookDTOs = query.getResultList();Note importante
Contrairement au projection d’entité, les projections scalaire et DTO ne font plus partie du contexte de persistance et ne suivent plus le cycle de vie.
- Ainsi si vous mettez à jour le DTO, la nouvelle donnée ne sera pas persister en base de donnée
- Par conséquent les projections scalaire et DTO ne peuvent être utilisé que pour de la lecture
Choisir sa projection
Le choix du type de projection dépend du cas d’utilisation :
- Opérations d’écriture : Les projections d’entités sont obligatoire en raison de la gestion automatique du cycle de vie des entités par le contexte de persistance.
- Opérations en lecture seule : Les projections de valeurs scalaires ou DTO sont préférables pour réduire le surcoût et améliorer les performances.