web-dev-qa-db-fra.com

JPA et Hibernate - Critères vs. JPQL ou HQL

Quels sont les avantages et les inconvénients de l’utilisation de Critères ou HQL ? L'API Criteria est une manière agréable, orientée objet, d'exprimer des requêtes dans Hibernate, mais parfois, les requêtes Criteria sont plus difficiles à comprendre/à construire que HQL. 

Quand utilisez-vous Criteria et quand HQL? Que préférez-vous dans quels cas d'utilisation? Ou est-ce juste une question de goût?

283
cretzel

Je préfère surtout les requêtes de critères pour les requêtes dynamiques. Par exemple, il est beaucoup plus facile d’ajouter des commandes de manière dynamique ou d’omettre certaines parties (restrictions, par exemple) en fonction de certains paramètres. 

D'autre part, j'utilise HQL pour les requêtes statiques et complexes, car il est beaucoup plus facile de comprendre/lire HQL. De plus, HQL est un peu plus puissant, par exemple. pour différents types de jointure.

203
cretzel

Il existe une différence en termes de performances entre HQL et criteriaQuery. Chaque fois que vous lancez une requête à l'aide de criteriaQuery, un nouvel alias est créé pour le nom de la table. Cela entraîne une surcharge de compilation du code SQL généré, ce qui prend plus de temps à exécuter.

Concernant les stratégies de récupération [http://www.hibernate.org/315.html]

  • Les critères respectent les paramètres de paresse de vos mappages et garantissent que ce que vous voulez charger est chargé. Cela signifie qu'une requête Critères peut générer plusieurs instructions SELECT SQL immédiates pour extraire le sous-graphe avec toutes les associations et collections mappées non paresseuses. Si vous souhaitez modifier le "comment" et même le "quoi", utilisez setFetchMode () pour activer ou désactiver l'extraction de jointure externe pour une collection ou une association particulière. Les requêtes de critères respectent également complètement la stratégie de récupération (rejoindre vs sélectionner vs sous-sélectionner).
  • HQL respecte les paramètres de paresse de vos mappages et garantit que ce que vous voulez charger est chargé. Cela signifie qu'une requête HQL peut entraîner plusieurs instructions SQL immédiates SELECT pour extraire le sous-graphe avec toutes les associations et collections mappées non lazy. Si vous souhaitez modifier le "comment" et même le "quoi", utilisez LEFT JOIN FETCH pour activer l'extraction de jointure externe pour une collection particulière ou l'association nullable plusieurs-à-un ou un-un, ou JOIN FETCH pour activer extraction de jointure interne pour une association plusieurs-à-un ou un-à-un non nullable. Les requêtes HQL ne respectent pas les propriétés fetch = "join" définies dans le document de mappage.
89
Varun Mehta

Criteria est une API orientée objet, tandis que HQL signifie concaténation de chaînes. Cela signifie que tous les avantages de l'orientation orientée objet s'appliquent:

  1. Toutes choses étant égales par ailleurs, la version OO est un peu moins sujette aux erreurs. Toute ancienne chaîne peut être ajoutée à la requête HQL, alors que seuls les objets Criteria valides peuvent en faire une arborescence de critères. En effet, les classes de critères sont plus contraintes.
  2. Avec l'auto-complétion, le OO est plus facile à découvrir (et donc plus facile à utiliser, du moins pour moi). Vous n'avez pas nécessairement besoin de vous rappeler quelles parties de la requête vont où; le IDE peut vous aider
  3. De plus, vous n'avez pas besoin de vous rappeler les détails de la syntaxe (comme quels symboles vont où). Tout ce que vous devez savoir, c'est comment appeler des méthodes et créer des objets.

Etant donné que HQL ressemble beaucoup à SQL (que la plupart des développeurs connaissent déjà très bien), ces arguments "ne pas avoir à se souvenir" n'ont pas autant de poids. Si HQL était plus différent, alors ce serait plus important.

38
Craig Walker

J'utilise habituellement les critères lorsque je ne sais pas quelles entrées seront utilisées pour quels éléments de données. Comme sur un formulaire de recherche où l'utilisateur peut entrer de 1 à 50 éléments et je ne sais pas ce qu'il va rechercher. Il est très facile d'ajouter simplement plus de critères au fur et à mesure que je vérifie ce que recherche l'utilisateur. Je pense qu'il serait un peu plus gênant de poser une requête HQL dans ce cas. HQL est bien quand je sais exactement ce que je veux.

34
Arthur Thomas

HQL est beaucoup plus facile à lire, à déboguer à l’aide d’outils tels que le plug-in Eclipse Hibernate et plus facile à enregistrer. Les requêtes par critères conviennent mieux à la construction de requêtes dynamiques dans lesquelles une grande partie du comportement est déterminée lors de l'exécution. Si vous ne connaissez pas SQL, je pourrais comprendre utiliser des requêtes Critères, mais globalement, je préfère HQL si je sais ce que je veux au départ.

31
Brian Deterling

Les critères sont le seul moyen de spécifier des recherches de clé naturelle qui tirent parti de l'optimisation spéciale du cache de requêtes de deuxième niveau. HQL n’a aucun moyen de spécifier l’indice nécessaire. 

Vous pouvez trouver plus d'informations ici:

22
Alex Miller

Critères Api est l’un des bons concepts d’Hibernate. à mon avis, c’est le seul point par lequel nous pouvons faire la différence entreHQLet Criteria Api

  1. HQL doit exécuter des opérations de sélection et de non-sélection sur les données, mais les critères ne servent qu'à sélectionner les données. Nous ne pouvons pas effectuer d'opérations de non-sélection à l'aide de critères.
  2. HQL convient à l'exécution de requêtes statiques, alors que Criteria convient à l'exécution de requêtes dynamiques
  3. HQL ne prend pas en charge le concept pagination , mais nous pouvons obtenir une pagination avec des critères.
  4. Les critères prenaient plus de temps que HQL.
  5. Avec Criteria, nous sommes en sécurité avec SQL Injection en raison de sa génération de requête dynamique, mais en HQL, vos requêtes étant soit fixes, soit paramétrées, il n’existe aucun coffre-fort de SQL Injection
20
Arvind

Pour moi, Criteria est assez facile à comprendre et à faire des requêtes dynamiques. Mais la faille que je dis jusqu’à présent est qu’elle charge toutes les relations plusieurs-un, car nous n’avons que trois types de FetchModes, c’est-à-dire Select, Proxy et Default, et dans tous ces cas, il en charge plusieurs (peut-être que j’ai tort, aide moi dehors :))

Le deuxième problème avec Criteria est qu’il charge un objet complet, c’est-à-dire que si je veux juste charger EmpName d’un employé, il ne viendra pas avec cela, mais plutôt avec l’objet employé complet et que je peux obtenir EmpName grâce à cela cela fonctionne vraiment. mauvais rapport . Où comme HQL charge-t-il simplement (n’a-t-il pas chargé association/relations) ce que vous voulez, augmentez ainsi les performances plusieurs fois.

Une des caractéristiques de Criteria est la sécurité de SQL Injection en raison de sa génération de requête dynamique où, comme dans HQL, vos requêtes sont soit fixes, soit paramétrées, de sorte qu'elles ne sont pas protégées par SQL Injection.

De même, si vous écrivez HQL dans vos fichiers aspx.cs, vous êtes étroitement associé à ur DAL.

Dans l’ensemble, ma conclusion est qu’il existe des endroits où vous ne pouvez pas vivre sans HQL, comme les rapports; utilisez-les autrement. Les critères sont plus faciles à gérer.

13
Zafar

Pour utiliser le meilleur des deux mondes, l'expressivité et la concision de HQL et la nature dynamique de Criteria envisagent d'utiliser Querydsl .

Querydsl prend en charge JPA/Hibernate, JDO, SQL et Collections.

Je suis le responsable de Querydsl, cette réponse est donc biaisée.

12
Timo Westkämper

Pour moi, le plus gros gain sur les critères est l’API Example, où vous pouvez passer un objet et où hibernate va construire une requête basée sur ces propriétés d’objet.

En outre, l’API de critères a ses bizarreries (je crois que l’équipe de veille prolongée est en train de retravailler l’API), comme par exemple:

  • un critère.createAlias ​​("obj") force une jointure interne au lieu d'une jointure externe possible
  • vous ne pouvez pas créer le même alias deux fois
  • certaines clauses SQL n'ont pas de contrepartie de critères simples (comme une sous-sélection)
  • etc.

J'ai tendance à utiliser HQL lorsque je veux des requêtes similaires à SQL (supprimer des utilisateurs avec status = 'bloqué'), et j'ai tendance à utiliser des critères lorsque je ne veux pas utiliser la chaîne ajoutée.

Un autre avantage de HQL est que vous pouvez définir toutes vos requêtes à l’avance, et même les externaliser dans un fichier.

11
Miguel Ping

L'API de critères convient mieux aux requêtes générées dynamiquement lorsque les filtres de requête sont appliqués de manière dynamique au moment de l'exécution. Par conséquent, pour empêcher les attaques par injection SQL lors de la construction de requêtes dynamiques, l'API des critères est un très bon choix.

Les requêtes de critères sont moins expressives et vous pouvez facilement vous retrouver avec une requête générée très complexe et inefficace SQL . Une fois, j'ai rejoint une grande application d'entreprise où l'API de critères était la méthode de requête par défaut et même une analyse de code approfondie ne pouvait pas effacer l'horreur de ne pas savoir quelles requêtes SQL nous allions finir.

JPQL ou HQL est beaucoup plus expressif et il est beaucoup plus facile de prédire la requête SQL générée associée. Il est également beaucoup plus facile de passer en revue ses requêtes HQL que celles de Criteria. 

La plupart des cas d'utilisation de requêtes d'entités ne nécessitent pas de clause where dynamique, vous pouvez donc implémenter la plupart des requêtes avec JPQL tout en laissant Criteria pour les requêtes dynamiques.

Il convient de noter que la sélection d'entités avec JPQL ou l'API Criteria est utile si vous devez les modifier. Sinon, une projection DTO donne de meilleurs résultats. Découvrez cet article pour plus d’informations .

9
Vlad Mihalcea

Les critères api fournissent une fonctionnalité distincte que ni SQL ni HQL ne fournissent. c'est à dire. cela permet de vérifier le temps de compilation d'une requête. 

9
user1165443

Nous avons utilisé principalement Criteria dans notre application au début, mais celle-ci a été remplacée par HQL en raison de problèmes de performances. 
Nous utilisons principalement des requêtes très complexes avec plusieurs jointures, ce qui conduit à plusieurs requêtes dans Criteria mais est très optimisé en HQL. 
Le cas est que nous utilisons seulement plusieurs propriétés sur un objet spécifique et non des objets complets. Avec Criteria, le problème était également la concaténation de chaînes. 
Disons que si vous devez afficher le nom et le prénom de l’utilisateur en HQL, c’est assez simple (name || ' ' || surname) mais cela n’est pas possible dans Crteria. 
Pour résoudre ce problème, nous avons utilisé ResultTransormers, où il existait des méthodes dans lesquelles une telle concaténation était implémentée pour obtenir le résultat souhaité. 
Aujourd'hui, nous utilisons principalement HQL comme ceci:

String hql = "select " +
            "c.uuid as uuid," +
            "c.name as name," +
            "c.objective as objective," +
            "c.startDate as startDate," +
            "c.endDate as endDate," +
            "c.description as description," +
            "s.status as status," +
            "t.type as type " +
            "from " + Campaign.class.getName() + " c " +
            "left join c.type t " +
            "left join c.status s";

Query query =  hibernateTemplate.getSessionFactory().getCurrentSession().getSession(EntityMode.MAP).createQuery(hql);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();

ainsi, dans notre cas, les enregistrements renvoyés sont des cartes des propriétés nécessaires.

7
Bojan Kraut
  • HQL doit effectuer des opérations de sélection et de non-sélection sur les données, mais les critères ne servent qu'à sélectionner les données. Nous ne pouvons pas effectuer d'opérations de non-sélection à l'aide de critères.
  • HQL convient à l'exécution de requêtes statiques, alors que Criteria convient à l'exécution de requêtes dynamiques 
  • HQL ne supporte pas le concept de pagination, mais nous pouvons réaliser la pagination avec des critères
  • Les critères prenaient plus de temps à exécuter que HQL
  • Avec Criteria, nous sommes en sécurité avec SQL Injection en raison de la génération de requête dynamique, mais dans HQL, vos requêtes étant soit fixes, soit paramétrées, il n’existe aucun coffre-fort de SQL Injection. 

la source

7
Premraj

Critère de requête pour dynamiquement, nous pouvons construire une requête sur la base de nos entrées. Dans le cas d'une requête Hql, la requête statique une fois que nous construisons, nous ne pouvons pas changer la structure de la requête.

5
user1679378

Je ne veux pas frapper d'un cheval mort ici, mais il est important de mentionner que les requêtes de critères sont maintenant obsolètes. Utilisez HQL.

4
Eskir

Je préfère également les requêtes de critères pour les requêtes dynamiques. Mais je préfère hql pour les requêtes de suppression, par exemple si supprimer tous les enregistrements de la table enfant pour le parent ID 'xyz', il est facile à réaliser par HQL, mais pour les critères API, nous devons d'abord lancer un nombre n de requête de suppression, où n est le nombre d'enfant enregistrements de table.

1
Punit Patel

Il y a un autre moyen. J'ai fini par créer un analyseur syntaxique HQL basé sur la syntaxe originale hibernate afin d'analyser d'abord HQL, puis d'injecter dynamiquement des paramètres dynamiques ou d'ajouter automatiquement des filtres communs pour les requêtes HQL. Cela fonctionne très bien!

0
Wallace Peng

Ce post est assez vieux. La plupart des réponses parlent de critères Hibernate, pas de critères JPA. JPA 2.1 a ajouté CriteriaDelete/CriteriaUpdate et EntityGraph qui contrôlent le contenu à récupérer. L'API de critères est meilleure puisque Java est OO. C'est pourquoi JPA est créé. Lorsque JPQL est compilé, il sera traduit en arborescence AST (modèle OO) avant d'être traduit en SQL.

0
Sunnyday

La plupart des réponses ici sont trompeuses et mentionnent que Criteria Queries sont plus lents que HQL, ce qui n’est en fait pas le cas.

Si vous approfondissez et effectuez quelques tests, vous verrez les requêtes de critères fonctionnent beaucoup mieux que la norme HQL

Et aussi avec Criteria Query vous obtenez contrôle orienté objet qui n'est pas là avec HQL.

Pour plus d'informations, lisez cette réponse ici .

0
Pritam Banerjee