Mappage d'une requête Hibernate à une classe personnalisée

1. Vue d'ensemble

Lorsque nous utilisons Hibernate pour récupérer des données de la base de données, par défaut, il utilise les données récupérées pour construire l'ensemble du graphe d'objets pour l'objet demandé. Mais parfois, nous pouvons vouloir récupérer seulement une partie des données, de préférence dans une structure plate.

Dans ce tutoriel rapide, nous verrons comment nous pouvons y parvenir dans Hibernate en utilisant une classe personnalisée.

2. Les entités

Tout d'abord, regardons les entités que nous utiliserons pour récupérer les données:

@Entity public class DeptEmployee { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String employeeNumber; private String designation; private String name; @ManyToOne private Department department; // constructor, getters and setters } @Entity public class Department { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String name; @OneToMany(mappedBy="department") private List employees; public Department(String name) { this.name = name; } // getters and setters  }

Ici, nous avons deux entités - DeptEmployee et Department . Par souci de simplicité, supposons qu'un DeptEmployee ne puisse appartenir qu'à un seul département.

Mais, un département peut avoir plusieurs DeptEmployees .

3. Une classe de résultat de requête personnalisée

Disons que nous voulons imprimer une liste de tous les employés avec juste leur nom et le nom de leur service.

En règle générale, nous récupérons ces données avec une requête comme celle-ci:

Query query = session.createQuery("from com.baeldung.hibernate.entities.DeptEmployee"); List deptEmployees = query.list();

Cela récupérera tous les employés, toutes leurs propriétés, le service associé et toutes ses propriétés.

Mais, dans ce cas particulier, cela peut être un peu cher car nous n'avons besoin que du nom de l'employé et du nom du département.

Une façon de ne récupérer que les informations dont nous avons besoin est de spécifier les propriétés dans la clause select.

Mais, lorsque nous faisons cela, Hibernate renvoie une liste de tableaux au lieu d'une liste d' objets:

Query query = session.createQuery("select m.name, m.department.name from com.baeldung.hibernate.entities.DeptEmployee m"); List managers = query.list(); Object[] manager = (Object[]) managers.get(0); assertEquals("John Smith", manager[0]); assertEquals("Sales", manager[1]);

Comme nous pouvons le voir, les données renvoyées sont un peu lourdes à traiter. Mais, heureusement, nous pouvons demander à Hibernate de remplir ces données dans une classe.

Regardons la classe Result que nous utiliserons pour remplir les données récupérées dans:

public class Result { private String employeeName; private String departmentName; public Result(String employeeName, String departmentName) { this.employeeName = employeeName; this.departmentName = departmentName; } public Result() { } // getters and setters }

Notez que la classe n'est pas une entité mais juste un POJO. Cependant, nous pouvons également utiliser une entité tant qu'elle a un constructeur qui prend tous les attributs que nous voulons remplir comme paramètres.

Nous verrons pourquoi le constructeur est important dans la section suivante.

4. Utilisation d'un constructeur dans HQL

Maintenant, regardons le HQL qui utilise cette classe:

Query query = session.createQuery("select new com.baeldung.hibernate.pojo.Result(m.name, m.department.name)" + " from com.baeldung.hibernate.entities.DeptEmployee m"); List results = query.list(); Result result = results.get(0); assertEquals("John Smith", result.getEmployeeName()); assertEquals("Sales", result.getDepartmentName());

Ici, nous utilisons le constructeur que nous avons défini dans la classe Result avec les propriétés que nous voulons récupérer. Cela renverra une liste d' objets Result avec les données remplies à partir des colonnes.

Comme nous pouvons le voir, la liste retournée est plus facile à traiter que l'utilisation d'une liste de tableaux d'objets.

Il est important de noter que nous devons utiliser le nom complet de la classe dans la requête.

5. Utilisation d'un ResultTransformer

Une alternative à l'utilisation d'un constructeur dans la requête HQL consiste à utiliser un ResultTransformer:

Query query = session.createQuery("select m.name as employeeName, m.department.name as departmentName" + " from com.baeldung.hibernate.entities.DeptEmployee m"); query.setResultTransformer(Transformers.aliasToBean(Result.class)); List results = query.list(); Result result = results.get(0); assertEquals("John Smith", result.getEmployeeName()); assertEquals("Sales", result.getDepartmentName());

Nous utilisons les transformateurs. aliasToBean () pour utiliser les données récupérées pour remplir les objets Result .

Par conséquent, nous devons nous assurer que les noms de colonne ou leurs alias dans l'instruction select correspondent aux propriétés de la classe Result .

Notez que Query.setResultTransformer ( ResultTransformer ) est obsolète depuis Hibernate 5.2.

6. Conclusion

Dans cet article, nous avons vu comment une classe personnalisée peut être utilisée pour récupérer des données sous une forme facile à lire.

Le code source qui accompagne cet article est disponible à l'adresse over sur GitHub.