App et hibernation-critères par rapport à JPQL ou HQL
Quels sont les avantages et les inconvénients d'utiliser critères ou HQL ? L'API critères est une bonne façon d'exprimer les requêtes en hibernation, mais parfois les requêtes critères sont plus difficiles à comprendre/construire que HQL.
Quand utilisez-vous les critères et quand HQL? Que préférez-vous dans lequel cas d'utilisation? Ou est-ce juste une question de goût?
21 réponses
je préfère les requêtes de critères pour les requêtes dynamiques. Par exemple, il est beaucoup plus facile d'ajouter de l'ordre dynamiquement ou de laisser des pièces (par exemple des restrictions) en fonction de certains paramètres.
d'un autre côté, J'utilise HQL pour les requêtes statiques et complexes, car il est beaucoup plus facile de comprendre/lire HQL. En outre, HQL est un peu plus puissant, je pense, par exemple pour différents types de jointure.
il y a une différence en termes de performance entre HQL et criteriaQuery, chaque fois que vous lancez une requête en utilisant criteriaQuery, il crée un nouvel alias pour le nom de la table qui ne reflète pas dans le dernier cache interrogé pour une quelconque base de données. Cela conduit à un overhead de compilation du SQL généré, prenant plus de temps à exécuter.
Concernant les stratégies de chargement [http://www.hibernate.org/315.html]
- les critères respectent les paramètres de paresse dans vos correspondances et garantit que ce que vous voulez chargé est chargé. Cela signifie qu'une requête de critères peut donner lieu à plusieurs instructions de sélection immédiate SQL pour récupérer le sous-paragraphe avec toutes les associations et collections cartographiées non-paresseuses. Si vous voulez changer le "comment" et même le "quoi", utilisez setFetchMode() pour activer ou désactiver la fonction externe jointure fetching pour une collection ou une association particulière. Les requêtes sur les critères respectent aussi complètement les exigences stratégie (joindre vs sélectionnez vs sous-sélection).
- HQL respecte les paramètres de paresse dans vos correspondances et garantit que ce que vous voulez chargé est chargé. Cela signifie qu'une requête HQL peut entraîner plusieurs requêtes SQL SELECT immédiates pour récupérer le sous-paragraphe avec toutes les associations et collections cartographiées non-paresseuses. Si vous voulez changer le "comment" et même le "quoi", utilisez la jointure gauche FETCH pour activer la jointure externe Fetch pour une collection particulière ou nullable many-to-one ou one-to-one l'association, ou joindre FETCH pour permettre la jonction interne pour une association non-nullable plusieurs-à-un ou un-à-un. Les requêtes HQL ne respectent aucun fetch="join" défini dans le document de mappage.
critère est une API orientée objet, tandis que HQL signifie chaîne de concaténation. Cela signifie que tous les avantages de l'objet-orienté":
- toutes choses étant égales par ailleurs, la version OO est un peu moins sujette aux erreurs. N'importe quelle ancienne chaîne de caractères pourrait être ajoutée dans la requête HQL, alors que seuls les objets de critères valides peuvent la transformer en arbre de critères. En fait, les catégories de critères sont plus restreintes.
- avec auto-complete, l'OO est plus détectable (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
- vous n'avez pas non plus besoin de vous rappeler les détails de la syntaxe (comme quels symboles vont où). Tout ce que vous devez savoir est comment appeler des méthodes et créer des objets.
puisque HQL est très proche de SQL (que la plupart des développeurs connaissent déjà très bien), alors ces arguments "n'ont pas à se souvenir" n'avez pas beaucoup de poids. Si HQL était plus différent, alors ce serait plus important.
j'utilise habituellement des 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 n'importe lequel de 1 à 50 articles et je ne sais pas ce qu'ils chercheront. Il est très facile de simplement ajouter plus de critères que je passe par la vérification de ce que l'utilisateur recherche. Je pense qu'il serait un peu plus gênant de poser une question HQL dans ces circonstances. HQL est génial quand je sais exactement ce que je veux.
HQL est beaucoup plus facile à lire, plus facile à déboguer en utilisant des outils comme le plugin Eclipse Hibernate, et plus facile à enregistrer. Les requêtes de critères sont meilleures pour la construction de requêtes dynamiques où une grande partie du comportement est déterminée à l'exécution. Si vous ne connaissez pas SQL, je pourrais comprendre en utilisant des requêtes de critères, mais dans l'ensemble je préfère HQL si je sais ce que je veux d'avance.
sont le seul moyen de spécifier des recherches de clés naturelles qui tirent profit de l'optimisation spéciale dans la cache de requête de deuxième niveau. HQL n'a aucun moyen de spécifier l'indication nécessaire.
vous pouvez trouver plus d'informations ici:
critères L'Api est l'un des bons concepts D'hibernation. selon moi, ce sont les quelques points par lesquels nous pouvons faire la différence entre HQL et critères Api
- HQL est à effectuer à la fois de sélectionner et de non-sélectionnez opérations sur les données, mais des Critères n'est que pour choisir les données, nous ne pouvons pas effectuer de non-choisir les opérations à l'aide de critères.
- HQL est adapté à l'exécution Requêtes statiques, pour lesquelles as Criteria est adapté à l'exécution de requêtes dynamiques
- HQL ne supporte pas pagination concept, mais nous pouvons réaliser la pagination avec des critères.
- critères utilisés pour prendre plus de temps à exécuter que HQL.
- avec des critères nous sommes sûrs avec injection SQL en raison de sa génération de requête dynamique, mais dans HQL que vos requêtes sont soit fixes ou paramétrées, il est pas à l'abri de l'Injection SQL
pour moi critères est un assez facile à comprendre et de faire des requêtes dynamiques. Mais le défaut que je dis jusqu'ici est qu'il charge toutes les relations beaucoup-un etc parce que nous avons seulement trois types de FetchModes I. E Select, Proxy and Default and in all these cases it loads many-one (may be I am wrong if so help me out:)
le deuxième problème avec les critères est qu'il charge l'objet complet I. e si je veux simplement charger EmpName D'un employé, il ne viendra pas avec ce insted il vient vers le haut avec l'objet employé complet et je peux obtenir EmpName de lui en raison de ce cela fonctionne vraiment mal dans le rapport . où comme HQL juste charger (ne pas charger l'association/relations) ce que vous voulez donc augmenter la performance de nombreuses fois.
L'une des caractéristiques des critères est qu'il est sûr de L'Injection SQL en raison de sa génération de requête dynamique où, comme dans HQL que les requêtes ur sont soit fixe ou paramétré de sorte ne sont pas à l'abri de L'Injection SQL.
Aussi si vous écrivez HQL dans votre aspx.fichiers cs, alors vous êtes étroitement couplé avec ur DAL.
dans l'ensemble, ma conclusion est qu'il y a des endroits où l'on ne peut pas vivre sans des rapports de type HQL, alors utilisez les autres critères qui sont plus faciles à gérer.
pour utiliser le meilleur des deux mondes, l'expressivité et la concision de HQL et la nature dynamique des critères envisager d'utiliser Querydsl .
Querydsl prend en charge JPA/Hibernate, JDO, SQL et les Collections.
je suis le responsable de Querydsl, donc cette réponse est biaisée.
pour moi la plus grande victoire sur les critères est L'API exemple, où vous pouvez passer un objet et hibernate construira une requête basée sur ces propriétés d'objet.
en outre, L'API critères a ses bizarreries (je crois que l'équipe hibernate est en train de retravailler l'api), comme:
- un des critères.createAlias ("obj") force une jonction interne au lieu d'une possible jonction externe
- vous ne pouvez pas créer le même alias deux fois
- certaines clauses sql n'ont pas de simple contrepartie de critères (comme un sous-select)
- etc.
j'ai tendance à utiliser HQL quand je veux des requêtes similaires à sql (supprimer des utilisateurs où status='blocked'), et j'ai tendance à utiliser des critères quand je ne veux pas utiliser l'ajout de chaînes de caractères.
un autre avantage de HQL est que vous pouvez définir toutes vos requêtes avant la main, et même les externaliser vers un fichier ou plus.
critères api fournir une caractéristique distincte que ni SQL ni HQL ne fournit. IE. il permet de vérifier le temps de compilation d'une requête.
L'API critères est mieux adaptée aux requêtes générées dynamiquement lorsque les filtres de requête sont appliqués dynamiquement à l'exécution. Par conséquent, pour empêcher les attaques par Injection SQL lors de la construction de requêtes dynamiques, L'API de 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 par SQL très compliquée et inefficace . Une fois j'ai rejoint une application de grande entreprise où L'API de critères était la méthode de requête par défaut et même pas de révision de code extensive pourrait surmonter l'horreur de ne pas savoir quelles requêtes SQL nous allions finir avec.
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 aussi beaucoup plus facile de passer en revue ses requêtes HQL que ses requêtes critères.
la plupart des cas d'utilisation d'entity querying ne nécessitent pas de clauses dynamiques where pour que vous puissiez mettre en œuvre la plupart des cas d'utilisation d'entity querying requêtes avec JPQL tout en laissant des critères pour les dynamiques.
il est intéressant de noter que la sélection d'entités avec L'API JPQL ou Criteria est logique si vous avez besoin de les modifier. Autrement, une projection DTO donne de meilleurs résultats. Consultez cet article pour plus d'information .
nous avons utilisé principalement des critères dans notre application au début, mais après il a été remplacé par HQL en raison de problèmes de performance.
Nous utilisons principalement des requêtes très complexes avec plusieurs jointures qui conduisent à des requêtes multiples dans les critères mais qui sont très optimisées dans HQL.
Le cas est que nous utilisons seulement plusieurs propeties sur un objet spécifique et non des objets complets. Avec les critères, le problème était aussi la concaténation des chaînes.
Disons que si vous avez besoin d'afficher le nom et le prénom de l'utilisateur dans HQL il est assez facile (name || ' ' || surname)
mais dans Crteria ce n'est pas possible.
Pour surmonter cette difficulté, nous avons utilisé des indicateurs de résultats, où il existait des méthodes où une telle concaténation était appliquée pour obtenir le résultat nécessaire.
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 retournés sont des cartes des propriétés nécessaires.
- HQL est à effectuer à la fois de sélectionner et de non-sélectionnez opérations sur les données, mais des Critères n'est que pour choisir les données, nous ne pouvons pas effectuer de non-choisir les opérations à l'aide de critères
- HQL est adapté pour l'exécution de requêtes statiques, où comme critère est adapté pour 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
- Critères utilisés pour prendre plus de temps pour exécuter alors HQL
- avec des critères nous sommes sûrs avec L'Injection SQL en raison de sa génération de requête dynamique mais dans HQL que vos requêtes sont soit fixes ou paramétrées, il n'y a pas de sécurité de L'Injection SQL.
critères requête pour dynamiquement nous pouvons construire requête basée sur nos entrées..en cas de requête Hql est la requête statique Une fois que nous construisons nous ne pouvons pas changer la structure de la requête.
Je ne veux pas donner de coup de pied à un cheval mort ici, mais il est important de mentionner que les requêtes de critères sont maintenant dépréciées. Utiliser les requêtes HQL.
je préfère également les requêtes 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 l'id parent 'xyz', il est facilement atteint par HQL, mais pour L'API de critères d'abord, nous devons tirer n nombre de requête de suppression où n est le nombre d'enregistrements de table enfant.
la plupart des réponses ici sont trompeuses et mentionnent que Criteria Queries
est plus lent que HQL
, ce qui n'est pas le cas.
si vous creusez profondément et effectuez quelques tests, vous verrez les requêtes critères performent beaucoup mieux que le HQL régulier .
et aussi avec critères requête vous obtenez contrôle orienté objet qui n'est pas là avec HQL .
pour plus d'information, lisez cette réponse ici .
il y a un autre moyen. J'ai fini par créer un analyseur HQL basé sur la syntaxe originale d'hibernation pour qu'il analyse d'abord le HQL puis il puisse injecter dynamiquement des paramètres dynamiques ou ajouter automatiquement des filtres communs pour les requêtes HQL. Il fonctionne très bien!
Ce post est assez ancien. La plupart des réponses parlent de critères D'hibernation, pas de critères JPA. JPA 2.1 a ajouté CriteriaDelete / CriteriaUpdate, et EntityGraph qui contrôle exactement ce qu'il faut aller chercher. L'API critères est meilleure puisque Java est OO. C'est pourquoi JPA est créé. Lorsque JPQL est compilé, il sera traduit en AST tree(modèle OO) avant d'être traduit en SQL.
HQL peut provoquer des sécurité préoccupations comme l'injection SQL.