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

1. Vue d’ensemble

Lorsque nous utilisons Hibernate pour extraire des données de la base de données, il utilise par défaut les données extraites pour construire le graphe d’objet entier 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 rapide tutoriel, ** nous verrons comment y parvenir grâce à Hibernate en utilisant une classe personnalisée.

2. Les entités

Voyons d’abord les entités que nous allons utiliser 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<DeptEmployee> employees;

    public Department(String name) {
        this.name = name;
    }

   //getters and setters
}

Ici, nous avons deux entités - DeptEmployee et Department . Pour simplifier, supposons qu’un DeptEmployee puisse appartenir à un seul Department.

Cependant, un department peut avoir plusieurs DeptEmployees .

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

Disons que nous souhaitons imprimer une liste de tous les employés avec uniquement leur nom et celui de leur service.

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

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

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

Mais, dans ce cas particulier, cela pourrait être un peu cher car nous avons seulement besoin du nom de l’employé et du nom du service.

Une façon de récupérer uniquement 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 de Objects:

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 constater, les données renvoyées sont un peu fastidieuses à traiter. Mais heureusement, nous pouvons faire en sorte que Hibernate insère ces données dans une classe.

Examinons la classe Result que nous utiliserons pour renseigner les données extraites 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é dans la mesure où elle possède un constructeur qui prend en tant que paramètres tous les attributs que nous voulons renseigner.

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

4. Utilisation d’un constructeur dans HQL

Voyons maintenant le HQL qui utilise cette classe:

Query<Result> query = session.createQuery("select new com.baeldung.hibernate.pojo.Result(m.name, m.department.name)"
  + " from com.baeldung.hibernate.entities.DeptEmployee m");
List<Result> 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 retournera une liste d’objets Result_ avec les données renseignées à partir des colonnes.

Comme nous pouvons le constater, la liste renvoyé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. Utiliser 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<Result> results = query.list();
Result result = results.get(0);
assertEquals("John Smith", result.getEmployeeName());
assertEquals("Sales", result.getDepartmentName());

Nous utilisons la méthode _Transformers.aliasToBean () pour utiliser les données extraites afin de renseigner 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 __Result __class.

Notez que https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/Query.html#setResultTransformer-org.hibernate.transform.ResultTransformer- [ _Query.setResultTransformer( ResultTransformer( ResultTransformer _ ) 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 dans un formulaire facile à lire.

Le code source fourni avec cet article est disponible à l’adresse over sur GitHub .