Hibernate – SQL natif, HQL ou API Criteria ?
Sommaire
Introduction
Hibernate propose plusieurs solutions pour réaliser des requêtes en base de données. Lorsque que le développeur doit écrire une requête avec Hibernate, il a trois possibilités :
- le SQL natif
- le HQL
- l’API
Criteria
(etExample
)
Quelle est la meilleure solution pour écrire une requête avec Hibernate ?
Solutions
SQL natif
L’un des objectifs d’Hibernate est de s’éloigner de la base de données[1]. Or, l’utilisation du SQL natif va à l’encontre de cet objectif. De ce point de vue, le SQL natif est à éviter. Néanmoins, l’équipe du projet le conseille seulement de façon exceptionnelle pour des points qui ont besoin d’utiliser une optimisation liée spécifique à la base de données.
HQL
C’est un langage propre à Hibernate qui s’inspire du SQL mais orienté objet. Il est très souple et donne accès à toutes les possibilités d’Hibernate.
API Criteria
C’est une API en Java qui permet de faire la même chose qu’avec le langage HQL. Le code source à écrire est très simple.
Conclusion
Si l’on élimine le SQL natif, il reste le HQL et l’API Criteria qui font la même chose. La différence concerne le développeur :
- l’écriture de requête sous forme de chaîne de caractères
- l’appel à une API de requête
Laquelle choisir ?
- pour obtenir une meilleure souplesse en terme de développement et de maintenance
- pour atteindre les meilleures performances
Jusqu’à présent j’avais utilisé naïvement simplement Hibernate avec l’API Criteria.
Pourquoi ce choix ? Cette API est très bien faite et la syntaxe des requêtes est validée à la compilation Java. De plus, je suppose que c’est plus rapide puisque qu’il n’y a pas besoin d’analyser de chaîne de caractères pour exécuter la requête. L’analyse du choix de l’implémentation des requêtes mérite d’être poursuivie.
Valère Viandier conseille de mélanger l’utilisation du HQL et de l’API Criteria. Selon lui, toute requête statique doit être implémentée avec le HQL[2]. Et toute requête dynamique doit être codée avec l’API Criteria. Cette dernière permet d’éviter la concaténation de String
lors de la construction de la requête.
John Ferguson Smart rejoint le point de vue de V. Viandier dans son article sur l’utilisation de l’API Criteria vis-à-vis de HQL. Puisque selon ce dernier, l’API doit être utilisée pour des requêtes dynamiques. Et inversement HQL doit être utilisé pour des requêtes statiques. Cela permet d’externaliser les requêtes qui pourront être mises en cache, analysées par un administrateur de base de données, etc…
L’utilisation de deux langages de requête peut troubler[3] beaucoup de personnes[4]. Pourtant, pour tirer parti des points forts de chaque langage, il est tout à fait raisonnable d’utiliser à la fois le HQL et l’API Criteria.
Quelqu’un a-t-il un avis sur le sujet ? Ou des retours d’expériences ?
Notes
[1] En terme d’implémentation.
[2] Idéalement dans les fichiers de configuration de mapping hbm.xml
.
[3] La maintenance applicative semble moins évidente.
[4] Moi le premier dans un premier temps.
https://blog.lecacheur.com/2006/07/17/hibernate-sql-natif-hql-ou-api-criteria/HibernatehibernateIntroduction Hibernate propose plusieurs solutions pour réaliser des requêtes en base de données. Lorsque que le développeur doit écrire une requête avec Hibernate, il a trois possibilités : le SQL natif le HQL l'API Criteria (et Example) Quelle est la meilleure solution pour écrire une requête avec Hibernate ? Solutions SQL natif L'un des objectifs d'Hibernate est...SeBSébastien LECACHEUR23r0@laposte.netAdministratorLe weblogue de SeB
Tout à fait d’accord avec tes conclusions.
L’avantage de la compilation avec criteria est d’ailleurs tout à fait relatif. La syntaxe est contrôlée, mais pas les noms. Pour les requêtes statiques, il est possible de les contrôler intégralement en les externalisant sous forme de ressources puis en ajoutant une tâche spécifique qui les parse lors du build. Dans ce cas, elles deviennent plus fiables que les requêtes criteria.
Ca me fait d’ailleurs penser que j’ai sous le coude un socle technique dans lequel on exprime tout en HQL (principe également valable pour SQL, EJBQL, JDOQL). Les requêtes dynamiques se traitent sans avoir à écrire une seule instruction d’assemblage (sans "if" ou assimilé). Le tout est contrôlable intégralement lors du build (même les requêtes totalement dynamiques). Ca adresse la problématique que tu évoque en ramenant tout au même niveau de simplicité tout en optimisant les performances. Il faudrait peut être que je songe à extraire cette partie pour en faire un framework opensource…
L’avantage de la compilation des appels à l’API Criteria est également désuet depuis que des outils tel que Hibernate Tools ajoutent le support de l’autocomplétion du HQL et permettent de valider/tester le HQL directement sur la base de données.
La tâche qui validerai les requêtes externalisées existe-t-elle déja ou faut-il l’implémenter soi-même ? 😉
Ton socle technique me semble très intéressant. Si jamais tu trouves le temps et que tu le publies sous forme de projet Open Source, je serai intéressé pour le tester.
A ma connaissance cette tâche n’existe pas toute faite. Dans mon cas elle fait partie d’un socle technique très vaste, mais ça fait assez longtemps que je l’ai écrit. D’autres ont peut être publié des choses semblables depuis. Dans tous les cas, ça ne casse pas trois pattes à un canard. Quelques lignes de codes suffisent pour écrire une tâche ANT qui fait ça et l’écriture de la classe qui charge les requêtes externes à l’exécution est du même acabit.
J’espère trouver le temps d’extraire cette partie du socle sous forme de framework indépendant. Jèy avais pensé initialement en lèécrivant et cèest ton billet qui me le rappelle. Mais le temps, le temps, cèest toujours ce qui me fait défaut…
Effectivement pour la tâche, son implémentation ne nous emmène pas loin. Je me renseignais au cas où, pour ne pas réinventer la roue. 😉
Malheureusement, le temps est une denrée rare qui nous fait tous défaut. Si seulement nous pouvions faire un this.clone()…
ou un fork !
en tout cas tres bon article et tu arrives au meme conclusion
que moi sur l’api hibernate 🙂
personnelement je prefere les critérias puisqu’on construit l’ast nous même à la différence du hql, donc meilleurs performances
++
Merci Chappy ! 🙂
Au niveau des performances, je ne suis pas sûr que l’API Criteria soit plus rapide. En effet, il me semble que dernière cette API c’est du HQL qui est généré.
Par contre, il est vrai que le code écrit avec l’API Criteria sera plus rapide (et surtout plus lisible) que s’il devait construire lui-même la requête HQL avec des concaténations, etc…
Bonjour,
j’ai beaucoupé aimé cet article, c’est vrai que également fais ce choix d’utiliser criteria pour les requetes dynamique, et des requetes SQL native pour les requetes necessitant des jointures plus controlée que ce qu’offre criteria.
A ce propos, je n’utilise pas les associations du type many-to-many ou one-to-many entre les tables, mais je met moi même les champs en tant que clé étrangère et indexée si besoin.
Je trouve que c’est moins lourd au niveau des fichiers de config et du code que d’accéder à une autre collection par une autre methode, de toute facon il faudrait être en lazy=false dans les cas des associations toute faite si l’on gère un site web par exemple, et que l’utilisateur passe de pages en pages avec des temps de latence.
J’aimerai savoir si d’autres ont fait ce choix, ou si vous utilisez ce type d’association pour faire les jointures entre vos objets?
Merci pour cette article, tout particulièrement à notre architecte Valère Viandier, dont ses connaissances et ses conseils sont aussi étendues dans la rénovation d’habitat (architecte transverse).
Indication de sa part (sauf erreur), toujours laisser par défaut le lazy à true.
merci pour cet article et surtout pour vos réaction car sa permet au debuttant comme nous de voir plus claire.
Content de voir que cet article sert encore ! 😉