Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Apprendre `query()` et `nativeQuery()` | Fondamentaux de Hibernate
Manipulation des Données Java avec Hibernate
course content

Contenu du cours

Manipulation des Données Java avec Hibernate

Manipulation des Données Java avec Hibernate

1. Aperçu de JDBC
2. Fondamentaux de Hibernate
3. Dernières Retouches

book
`query()` et `nativeQuery()`

Comme nous l'avons appris dans les chapitres précédents, nous avons des "méthodes intégrées" pour travailler avec les entités. Ces méthodes sont situées dans la Session. Mais que faire si nous devons écrire une requête spécifique ? Par exemple, nous voulons récupérer uniquement les employés qui ont été embauchés en 2023. Pour une telle requête, nous n'avons pas de fonction intégrée dans la session. Cependant, nous pouvons le faire en utilisant une requête SQL. Cela ressemblera à ceci :

Remarque

Oui, vous pouvez utiliser l'opérateur BETWEEN ici, mais je n'aime vraiment pas utiliser cette fonction. Vous pouvez écrire la requête comme vous le souhaitez, tant qu'elle fonctionne correctement.

Super, maintenant nous devons comprendre comment implémenter cela dans le code. Si vous avez examiné les tests dans le chapitre précédent et vu comment ils fonctionnent, vous avez peut-être remarqué que j'ai utilisé une méthode de l'objet session appelée createNativeQuery().

Maintenant, nous allons parler davantage de cette méthode.

Requête Native

La méthode createNativeQuery() crée une requête SQL, qui est conservée jusqu'à ce que executeUpdate() ou executeQuery() soit appelé. Regardons un exemple où nous devons récupérer des employés qui ont été embauchés dans un délai spécifique.

Tout d'abord, nous devons ajouter cette méthode à l'interface DAO :

Comme vous pouvez le voir, nous utilisons 2 paramètres de type Date pour spécifier la période exacte qui nous intéresse. Passons maintenant à la classe d'implémentation et implémentons cette méthode.

Pour cela, nous devons :

  1. Ouvrir une session ;
  2. Écrire une requête SQL ;
  3. Utiliser la méthode createNativeQuery() où nous utilisons cette requête ;
  4. Ajouter des données des paramètres à ces requêtes pour spécifier la période ;
  5. Utiliser la méthode getResultList() pour récupérer les données de la requête ;
  6. Exécuter la requête et enregistrer le résultat dans une List ;
  7. Attraper toutes les erreurs potentielles et fermer la session.

Dans l'ensemble, la procédure est très similaire à celle que nous avons effectuée précédemment. Seulement ici, nous utilisons une requête SQL complète pour interagir avec la base de données. Nous avons juste légèrement modifié cette requête pour y définir des paramètres. Eh bien, répétons :

Si nous voulons définir certains paramètres dans la requête SQL, nous écrivons un espace réservé pour ces paramètres directement dans la requête au lieu d'insérer directement les paramètres.

Pour cela, nous utilisons la syntaxe suivante :

Après cela, nous utilisons la méthode setParameter() où nous utilisons la syntaxe suivante :

De cette manière, Hibernate remplace automatiquement les données des paramètres de la méthode (ou toute autre donnée) directement dans la requête SQL.

Ensuite, nous récupérons une liste avec le type Employee en utilisant la méthode getResultList().

Remarque

La méthode getResultList() retournera une liste avec le type que nous avons spécifié dans la méthode createNativeQuery(). Nous avons utilisé Employee.class, donc la liste retournée aura ce type. Par exemple, si nous voulons récupérer une liste de noms, nous utilisons String.class dans les paramètres.

Ensuite, tout suit l'algorithme, en capturant les erreurs et en fermant la session.

HQL

Hibernate a son propre langage de requête que nous pouvons également utiliser. Il s'appelle HQL (Hibernate Query Language).

HQL est un langage de requête plus pratique que SQL dans le contexte de son utilisation dans le code, mais vous pouvez utiliser n'importe quel langage que vous trouvez pratique.

Considérons les principaux avantages et différences par rapport au SQL :

  • Approche orientée objet : HQL travaille avec des objets et leurs propriétés, tandis que SQL travaille avec des tables et des colonnes. Cela signifie qu'en HQL, vous vous référez aux classes et champs dans le code Java, tandis qu'en SQL, vous vous référez aux noms réels des tables et colonnes dans la base de données ;
  • Indépendance de la plateforme : HQL isole l'application de la dépendance à une base de données spécifique. Vous pouvez passer d'un SGBD à un autre sans modifier les requêtes HQL, tandis que les requêtes SQL peuvent nécessiter des modifications car différents SGBD peuvent avoir des différences de syntaxe et de fonctions ;
  • Navigation par association : En HQL, il est facile de naviguer à travers les objets associés via leurs associations, alors qu'en SQL, vous devez utiliser des jointures de tables ;
  • Sécurité des types : HQL offre une sécurité des types car il utilise des classes et propriétés Java, réduisant ainsi les risques d'erreurs liées aux types de données.

Comparons les requêtes effectuées en SQL et HQL pour voir la différence entre ces deux langages de requête :

Requête SQL pour la sélection :

Requête HQL équivalente :

Requête SQL avec JOIN :

Requête HQL équivalente :

Requête SQL pour mise à jour :

Requête HQL équivalente :

Dans ces exemples, on peut voir que HQL n'utilise pas le mot-clé SELECT pour sélectionner des objets et accéder aux propriétés en utilisant des points, tandis que SQL opère avec les noms de colonnes réels et nécessite l'utilisation du mot-clé SELECT.

HQL offre une plus grande flexibilité et puissance pour le modèle orienté objet lors du travail avec des bases de données et propose une variété de fonctionnalités pour simplifier le développement, telles que la pagination, les requêtes nommées et l'intégration avec la mise en cache.

Requête

Pour utiliser HQL, nous devrions utiliser la méthode createQuery() au lieu de createNativeQuery().

Modifions la méthode écrite précédemment pour incorporer HQL :

Comme vous pouvez le voir, certains codes ont changé. Maintenant, nous utilisons l'interface Query au lieu de NativeQuery. Ces interfaces ont des méthodes presque identiques, donc nous n'avons pas eu à modifier beaucoup la requête. De cette façon, nous opérons sur des objets et voyons clairement quels objets seront récupérés des tables.

Mais comment Hibernate sait-il avec quelle table travailler ? Hibernate regarde la classe Entity et voit quelle table y est spécifiée et les colonnes correspondantes de cette table. De cette façon, il substitue automatiquement les données nécessaires et exécute la requête.

Implémentation de la couche de service

Terminons l'implémentation complète de la méthode et implémentons la méthode getEmployeesHiredInASpecificTimeframe() dans la couche de service.

Tout d'abord, nous devons créer une telle méthode dans l'interface EmployeeService :

Comme vous pouvez le voir, nous avons ajouté une méthode supplémentaire qui récupérera uniquement les noms des employee. De même que ce que nous avons fait auparavant, une telle méthode devrait être située dans la couche de service.

Maintenant, regardons l'implémentation :

Dans l'ensemble, un tel code fonctionnera, mais il y a un inconvénient majeur. Il sera très peu pratique pour nous de travailler avec une classe comme Date() car elle n'accepte aucun format pratique pour nous. Utilisons la classe LocalDate introduite dans Java 8 pour écrire un analyseur private qui analysera la date à partir d'un format String "yyyy-mm-dd" en un objet Date, le rendant plus pratique pour nous et l'utilisateur de travailler avec les méthodes :

Ce code analysera automatiquement la date de String à Date.

Décomposons comment cela fonctionne :

  1. Nous créons un objet formatter de la classe DateTimeFormatter dans lequel nous spécifions le modèle selon lequel la date sera analysée ;
  2. Ensuite, nous stockons cette date dans une variable de type LocalDate, en utilisant la méthode parse() et en passant l'objet formatter en paramètre afin que Java sache exactement quel format de temps nous avons besoin ;
  3. Ensuite, la méthode atStartOfDay(ZoneId.systemDefault()) convertit LocalDate en ZonedDateTime au début de la journée dans le fuseau horaire par défaut du système. Cela est nécessaire car LocalDate ne contient pas d'informations sur l'heure. La méthode toInstant() convertit ZonedDateTime en Instant. Date.from(Instant) est utilisé pour obtenir un objet Date à partir de Instant.

Maintenant, nous devons modifier la méthode pour qu'elle accepte un String en tant que paramètre, ce qui nous rendra plus pratique de travailler avec.

Tout d'abord, nous devons changer le type de données des paramètres dans la classe d'interface, puis nous procédons à l'édition de l'implémentation :

Voici à quoi ressemblera notre code final. Comme vous pouvez le voir, nous avons utilisé une méthode private pour convertir la date du format String au format de la classe d'objet Date.

Ainsi, pour utiliser cette méthode, nous devons maintenant seulement spécifier la date au format "yyyy-MM-dd". Vérifions la fonctionnalité de ces méthodes dans la méthode main pour nous assurer que tout fonctionne correctement :

1. Quelle méthode est utilisée pour créer une requête SQL dans Hibernate ?

2. Comment spécifiez-vous les paramètres dans une requête HQL ?

3. Quelle caractéristique distingue HQL de SQL ?

4. Comment l'utilisation de la classe LocalDate pour les paramètres de date dans les requêtes améliore-t-elle le code ?

Quelle méthode est utilisée pour créer une requête SQL dans Hibernate ?

Quelle méthode est utilisée pour créer une requête SQL dans Hibernate ?

Sélectionnez la réponse correcte

Comment spécifiez-vous les paramètres dans une requête HQL ?

Comment spécifiez-vous les paramètres dans une requête HQL ?

Sélectionnez la réponse correcte

Quelle caractéristique distingue HQL de SQL ?

Quelle caractéristique distingue HQL de SQL ?

Sélectionnez la réponse correcte

Comment l'utilisation de la classe `LocalDate` pour les paramètres de date dans les requêtes améliore-t-elle le code ?

Comment l'utilisation de la classe LocalDate pour les paramètres de date dans les requêtes améliore-t-elle le code ?

Sélectionnez la réponse correcte

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 2. Chapitre 7
We're sorry to hear that something went wrong. What happened?
some-alt