Question

Quels sont les avantages et les inconvénients de l’utilisation de Critères ou HQL ? L'API Criteria est un moyen agréable d'exprimer des requêtes orientées objet dans Hibernate, mais il est parfois plus difficile de comprendre / construire des requêtes que de construire 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?

Était-ce utile?

La solution

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 (par exemple, des restrictions) 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 jointures.

Autres conseils

Il existe une différence en termes de performances entre HQL et critèreQuery. Chaque fois que vous lancez une requête à l'aide de criterQuery, un nouvel alias pour le nom de la table n'est reflété dans le dernier cache interrogé d'aucun DB. 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 de contenu [http://www.hibernate.org/315.html]

  
      
  • Les critères respectent les paramètres de paresse dans 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", utilise 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 (join vs select vs subselect).
  •   
  • 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 "what", 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 l'extraction de jointure interne pour une non-nullable association plusieurs-à-un ou un-à-un. Les requêtes HQL ne respectent pas fetch = " join & " défini dans le document de mappage.
  •   

Critères est une API orientée objet, tandis que HQL signifie concaténation de chaînes. Cela signifie que tous les avantages de l'approche 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 Criteria. En réalité, les classes de critères sont plus contraintes.
  2. Avec l'auto-complétion, l'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ù; l'IDE peut vous aider
  3. De plus, vous n'avez pas besoin de vous souvenir des 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), ils ne doivent pas nécessairement se souvenir de " les arguments n'ont pas autant de poids. Si HQL était plus différent, alors ce serait plus important.

J'utilise habituellement les critères lorsque je ne sais pas quelles entrées utiliseront 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 génial quand je sais exactement ce que je veux.

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 comprendrais bien l’utilisation des requêtes Critères, mais globalement, je préfère HQL si je sais ce que je veux au départ.

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 second niveau. HQL n’a aucun moyen de spécifier l’indice nécessaire.

Vous pouvez trouver plus d'informations ici:

Critères Api est l’un des bons concepts d’Hibernate. à mon avis, il s’agit du seul point par lequel nous pouvons faire la différence entre HQL et Critères 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, où Criteria convient à l’exécution de requêtes dynamiques
  3. HQL ne prend pas en charge le concept de pagination , mais nous pouvons réaliser la 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 la génération dynamique de sa requête. Toutefois, dans HQL, vos requêtes sont soit fixes, soit paramétrées.

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, parce que nous n’avons que trois types de FetchModes, à savoir Select, Proxy et Default, et dans tous ces cas, il en charge plusieurs (peut-être que je me trompe si je vous aide). moi sur:))

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 ça marche vraiment mal dans les rapports . Où comme HQL charge-t-il (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 qu’il protégera u de SQL Injection en raison de sa génération de requêtes 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 alors étroitement associé à votre DAL.

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

Pour utiliser le meilleur des deux mondes, l’expressivité et la concision de HQL ainsi que 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.

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 éventuelle
  • vous ne pouvez pas créer le même alias deux fois
  • certaines clauses sql n'ont pas de contrepartie de critères simple (comme une sous-sélection)
  • etc.

J'ai tendance à utiliser HQL lorsque je souhaite des requêtes similaires à SQL (supprimer des utilisateurs dont status = "bloqué"), et à des critères lorsque je ne souhaite pas utiliser l'ajout de chaînes.

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.

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, empêche SQL Attaque par injection lors de la création de requêtes dynamiques, l’API Criteria est un très bon choix.

Les requêtes de critères sont moins expressives et vous pouvez facilement vous retrouver avec un Requête générée par SQL . J'ai déjà rejoint une grande application d'entreprise dans laquelle l'API des critères était la méthode de requête par défaut et même une analyse de code complète ne pouvait pas effacer l'horreur de ne pas savoir avec quelles requêtes SQL nous nous retrouverions.

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 est intéressant 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. Consultez cet article pour plus d'informations .

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.

Nous avons utilisé principalement les critères 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 les critères 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 dans HQL, il est assez facile (nom || '' || nom de famille) , mais cela n'est pas possible dans Crteria.
Pour surmonter cela, 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();

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

  • 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
  • HQL convient à l’exécution de requêtes statiques, où Criteria convient à l’exécution de requêtes dynamiques
  • HQL ne prend pas en charge le concept de pagination, mais nous pouvons réaliser la pagination avec des critères
  • .
  • Les critères utilisés prenaient plus de temps que HQL
  • Avec Criteria, nous sommes en sécurité avec SQL Injection en raison de la génération de sa 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.

source

Requête avec critères pour la construction dynamique, 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.

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

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 vous supprimez tous les enregistrements de la table enfant pour l'identifiant parent 'xyz', cela est facilement réalisé par HQL, mais pour les critères API, nous devons d'abord lancer un nombre n de requêtes de suppression, où n est le nombre d'enfants enregistrements de table.

La plupart des réponses ici sont trompeuses et mentionnent que les requêtes de critères sont plus lentes que HQL , ce qui n'est en fait pas le cas.

Si vous approfondissez le sujet et effectuez certains tests, vous constaterez que les requêtes-critères fonctionnent beaucoup mieux que les standards HQL .

Et avec la requête de critères également, vous obtenez un contrôle orienté objet qui n’existe pas avec HQL .

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

Il existe 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!

Ce message est assez ancien. 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 ce qu’il faut extraire exactement. L'API de critères est meilleure puisque Java est OO. C'est pourquoi JPA est créé. Une fois compilé, JPQL sera traduit en arbre AST (modèle OO) avant d'être traduit en SQL.

HQL peut entraîner des problèmes de sécurité tels que l'injection de SQL.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top