wake-up-neo.com

JPA und Hibernate - Kriterien vs. JPQL oder HQL

Was sind die Vor- und Nachteile der Verwendung von Kriterien oder HQL ? Die Kriterien-API ist eine nette objektorientierte Methode zum Ausdrücken von Abfragen in Hibernate. Manchmal sind Kriterienabfragen jedoch schwieriger zu verstehen/zu erstellen als HQL. 

Wann verwenden Sie Kriterien und wann HQL? Was bevorzugen Sie in welchen Anwendungsfällen? Oder ist es nur eine Frage des Geschmacks?

283
cretzel

Bei dynamischen Abfragen ziehe ich meistens Kriterienabfragen vor. Beispielsweise ist es viel einfacher, eine Reihenfolge dynamisch hinzuzufügen oder einige Teile (z. B. Einschränkungen) abhängig von einigen Parametern auszulassen. 

Andererseits verwende ich HQL für statische und komplexe Abfragen, da es viel einfacher ist, HQL zu verstehen/lesen. HQL ist auch etwas leistungsfähiger, denke ich, z. für verschiedene Verbindungstypen.

203
cretzel

Bei der Leistung gibt es Unterschiede zwischen HQL und KriterienQuery. Bei jeder Abfrage einer Abfrage mithilfe von KriterienQuery wird ein neuer Aliasname für den Tabellennamen erstellt, der im letzten abgefragten Cache einer DB nicht berücksichtigt wird. Dies führt zu einem Mehraufwand für das Kompilieren der generierten SQL, was die Ausführung länger erfordert.

Bezüglich Abrufstrategien [http://www.hibernate.org/315.html]

  • Die Kriterien berücksichtigen die Faulheitseinstellungen in Ihren Mappings und gewährleisten, dass das, was Sie laden möchten, geladen wird. Dies bedeutet, dass eine Kriterienabfrage möglicherweise zu mehreren SQL-Direktanweisungen SELECT führt, um das Untergraph mit allen nicht als Lazy zugeordneten Zuordnungen und Sammlungen abzurufen. Wenn Sie das "Wie" und sogar das "Was" ändern möchten, verwenden Sie setFetchMode (), um das Abrufen der äußeren Verknüpfung für eine bestimmte Auflistung oder Zuordnung zu aktivieren oder zu deaktivieren. Bei Kriterienabfragen wird auch die Abrufstrategie vollständig berücksichtigt (Join vs. Select vs. Subselect).
  • HQL respektiert die Faulheitseinstellungen in Ihren Mappings und garantiert, dass das, was Sie laden möchten, geladen wird. Dies bedeutet, dass eine HQL-Abfrage möglicherweise zu mehreren SQL-Direktbefehlen SELECT führt, um das Untergraph mit allen nicht als Lazy zugeordneten Zuordnungen und Sammlungen abzurufen. Wenn Sie das "Wie" und sogar das "Was" ändern möchten, aktivieren Sie mit LEFT JOIN FETCH das Abrufen von Outer-Joins für eine bestimmte Auflistung oder eine null-fähige Many-to-One- oder Eins-zu-Eins-Zuordnung oder JOIN FETCH zum Aktivieren Inner Join-Abruf für eine nicht-nullfähige Many-to-One- oder One-to-One-Zuordnung. HQL-Abfragen berücksichtigen keine im Mapping-Dokument definierten fetch = "join".
89
Varun Mehta

Kriterien sind eine objektorientierte API, während HQL String-Verkettung bedeutet. Das bedeutet, dass alle Vorteile der Objektorientierung gelten:

  1. Ansonsten ist die OO -Version etwas weniger fehleranfällig. Jede alte Zeichenfolge kann an die HQL-Abfrage angehängt werden, wohingegen nur gültige Kriterienobjekte in eine Kriterienstruktur aufgenommen werden können. In der Tat sind die Kriterienklassen stärker eingeschränkt.
  2. Bei der automatischen Vervollständigung ist der OO besser auffindbar (und daher für mich zumindest einfacher zu verwenden). Sie müssen sich nicht unbedingt merken, welche Teile der Abfrage wohin gehen. Die IDE kann Ihnen helfen
  3. Sie müssen sich auch nicht an die Einzelheiten der Syntax erinnern (z. B. welche Symbole wohin gehen). Sie müssen lediglich wissen, wie Sie Methoden aufrufen und Objekte erstellen.

Da HQL sehr ähnlich zu SQL ist (was die meisten Entwickler bereits sehr gut wissen), haben diese Argumente "sich nicht zu erinnern" weniger Gewicht. Wenn HQL anders wäre, wäre dies wichtiger.

38
Craig Walker

Ich verwende normalerweise Kriterien, wenn ich nicht weiß, welche Eingaben für welche Daten verwendet werden. Wie auf einem Suchformular, in das der Benutzer 1 bis 50 Elemente eingeben kann, und ich weiß nicht, wonach er suchen soll. Es ist sehr einfach, einfach mehr an die Kriterien anzuhängen, während ich durchchecke, wonach der Benutzer sucht. Ich denke, es wäre etwas schwieriger, eine HQL-Abfrage unter diesen Umständen zu stellen. HQL ist großartig, wenn ich genau weiß, was ich will.

34
Arthur Thomas

HQL ist viel einfacher zu lesen, mit Tools wie dem Eclipse Hibernate-Plugin zu debuggen und einfacher zu protokollieren. Kriterienabfragen eignen sich besser zum Erstellen dynamischer Abfragen, bei denen ein Großteil des Verhaltens zur Laufzeit bestimmt wird. Wenn Sie sich mit SQL nicht auskennen, kann ich Criteria-Abfragen verstehen, aber insgesamt bevorzuge ich HQL, wenn ich weiß, was ich von vornherein will.

31
Brian Deterling

Nur mithilfe von Kriterien können Suchschlüssel für natürliche Schlüssel angegeben werden, die die spezielle Optimierung im Abfragecache der zweiten Ebene nutzen. HQL hat keine Möglichkeit, den erforderlichen Hinweis anzugeben. 

Weitere Informationen finden Sie hier:

22
Alex Miller

Kriterien Api ist eines der guten Konzepte von Hibernate. Meiner Ansicht nach sind dies die wenigen Punkte, durch die wir unterscheiden können zwischenHQLund Criteria Api

  1. HQL führt sowohl Select- als auch Non-Select-Vorgänge für die Daten aus, aber Kriterien dienen nur zur Auswahl der Daten. Wir können keine Nicht-Select-Vorgänge mit Kriterien durchführen.
  2. HQL eignet sich zur Ausführung von statischen Abfragen, während sich Kriterien als für die Ausführung von dynamischen Abfragen eignen
  3. HQL unterstützt kein PaginierungsKonzept, aber wir können mit Kriterien eine Paginierung erreichen.
  4. Früher dauerte die Ausführung von Kriterien länger als bei HQL.
  5. Mit Criteria sind wir mit SQL Injection wegen seiner dynamischen Abfrageerzeugung sicher, aber in HQL, da Ihre Abfragen entweder fest oder parametrisiert sind, gibt es keine Sicherheit vor SQL Injection
20
Arvind

Für mich sind Kriterien sehr einfach zu verstehen und dynamische Abfragen zu machen. Aber der Fehler, den ich bisher sage, ist, dass er alle Viele-Eins-Beziehungen usw. lädt, weil wir nur drei Arten von FetchModes haben, dh Select, Proxy und Default, und in all diesen Fällen lädt er Viel-Eins (möglicherweise bin ich falsch, wenn ich helfen kann.) mich raus :))

Das zweite Problem mit Criteria ist, dass es das vollständige Objekt lädt. Wenn ich also einfach EmpName eines Mitarbeiters laden möchte, wird es nicht mit diesem Befehl kommen, sondern mit einem vollständigen Objekt "Employee", und ich kann EmpName aufgrund dessen es funktioniert wirklich schlecht in der Berichterstattung . Wo HQL gerade geladen wird (Assoziationen/Beziehungen wurden nicht geladen), was Sie möchten, um die Leistung um ein Vielfaches zu steigern.

Ein Merkmal der Kriterien ist, dass es durch seine dynamische Abfrageerzeugung vor SQL Injection geschützt wird, wobei wie in HQL ur ur Abfragen entweder fixiert oder parametrisiert sind und daher nicht vor SQL Injection sicher sind.

Auch wenn Sie HQL in ur aspx.cs-Dateien schreiben, sind Sie eng mit ur DAL gekoppelt.

Alles in allem kann ich zu dem Schluss kommen, dass es Orte gibt, an denen Sie ohne HQL-Berichte nicht leben können. Verwenden Sie sie ansonsten. Die Kriterien lassen sich einfacher verwalten.

13
Zafar

Um das Beste aus beiden Welten zu nutzen, sollten Sie die Expressivität und Prägnanz von HQL und die dynamische Natur von Kriterien in Betracht ziehen, Querydsl zu verwenden.

Querydsl unterstützt JPA/Hibernate, JDO, SQL und Collections.

Ich bin der Verwalter von Querydsl, daher ist diese Antwort voreingenommen.

12

Der größte Gewinn bei Criteria ist für mich die Beispiel-API, bei der Sie ein Objekt übergeben können und der Ruhezustand eine auf diesen Objekteigenschaften basierende Abfrage erstellt.

Abgesehen davon hat die Kriterien-API ihre Macken (ich glaube, das Winterschlaf-Team überarbeitet die API):

  • ein kriterien.createAlias ​​("obj") erzwingt einen inneren Join anstelle eines möglichen äußeren Joins
  • sie können den gleichen Alias ​​nicht zweimal erstellen
  • einige SQL-Klauseln haben kein einfaches Kriterium (wie eine Unterauswahl).
  • usw.

Ich neige dazu, HQL zu verwenden, wenn ich ähnliche Abfragen wie sql haben möchte (von Benutzern löschen, bei denen status = 'locked' ist) und ich neige dazu, Kriterien zu verwenden, wenn ich keine Zeichenfolgenanhänge verwenden möchte.

Ein weiterer Vorteil von HQL ist, dass Sie alle Ihre Abfragen vorab definieren und sogar in eine Datei oder so weiter verlegen können.

11
Miguel Ping

Kriterien-API ist besser für dynamisch generierte Abfragen geeignet, wenn die Abfragefilter zur Laufzeit dynamisch angewendet werden. Um SQL-Injection-Angriffe verhindern beim Erstellen dynamischer Abfragen zu unterbinden, ist Criteria API daher eine sehr gute Wahl.

Kriterienabfragen sind weniger ausdrucksstark und Sie können leicht mit einem sehr komplizierten und ineffizienten durch SQL generierte Abfrage enden. Einmal habe ich mich einer großen Unternehmensanwendung angeschlossen, in der Criteria API die Standardabfragemethode war und nicht einmal umfangreiche Codeüberprüfung den Horror überwinden konnte, wenn man nicht wusste, mit welchen SQL-Abfragen wir enden würden.

JPQL oder HQL ist viel ausdrucksvoller und es ist viel einfacher, die zugehörige generierte SQL-Abfrage vorherzusagen. Es ist auch viel einfacher, die eigenen HQL-Abfragen zu überprüfen als die von Criteria. 

Die meisten Anwendungsfälle, bei denen Entitäten abgefragt werden, erfordern keine dynamischen Where-Klauseln, sodass Sie die meisten Abfragen mit JPQL implementieren können, während Sie die Kriterien für dynamische Abfragen beibehalten.

Es ist erwähnenswert, dass die Auswahl von Entitäten mit der JPQL- oder Criteria-API sinnvoll ist, wenn Sie sie ändern möchten. Ansonsten ist eine DTO-Projektion besser. Check out dieser Artikel enthält weitere Informationen .

9
Vlad Mihalcea

Kriterien api bieten eine bestimmte Funktion, die weder SQL noch HQL bietet. dh. Es ermöglicht die Kompilierzeitprüfung einer Abfrage. 

9
user1165443

Anfangs haben wir in unserer Anwendung hauptsächlich Kriterien verwendet, die jedoch aufgrund von Leistungsproblemen durch HQL ersetzt wurden. 
Wir verwenden hauptsächlich sehr komplexe Abfragen mit mehreren Joins, was zu mehreren Abfragen in Kriterien führt, aber in HQL sehr optimiert ist. 
Der Fall ist, dass wir nur mehrere Eigenschaften für ein bestimmtes Objekt und keine vollständigen Objekte verwenden. Bei Criteria bestand das Problem auch in der Verkettung von Strings. 
Sagen Sie, wenn Sie den Namen und Nachnamen des Benutzers in HQL anzeigen müssen, ist dies ziemlich einfach (name || ' ' || surname), aber in Crteria ist dies nicht möglich. 
Um dies zu überwinden, haben wir ResultTransormers verwendet, bei denen es Methoden gab, bei denen eine solche Verkettung für das benötigte Ergebnis implementiert wurde. 
Heute verwenden wir hauptsächlich HQL wie folgt:

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();

in unserem Fall handelt es sich bei den zurückgegebenen Datensätzen also um Karten der benötigten Eigenschaften.

7
Bojan Kraut
  • HQL führt sowohl Select- als auch Non-Select-Vorgänge für die Daten aus, aber Kriterien dienen nur zur Auswahl der Daten. Wir können keine Nicht-Select-Vorgänge mit Kriterien durchführen
  • HQL eignet sich zur Ausführung von statischen Abfragen, während sich Kriterien als für die Ausführung von dynamischen Abfragen eignen 
  • HQL unterstützt kein Paginierungskonzept, aber wir können mit Kriterien eine Paginierung erreichen
  • Früher dauerte die Ausführung von Kriterien länger als die Ausführung von HQL
  • Mit Criteria sind wir mit SQL Injection auf Grund der Erzeugung dynamischer Abfragen sicher, aber in HQL, da Ihre Abfragen entweder fest oder parametrisiert sind, gibt es keine Sicherheit vor SQL Injection. 

Quelle

7
Premraj

Kriterienabfrage für dynamisch können wir eine Abfrage basierend auf unseren Eingaben erstellen. Im Falle der Hql-Abfrage handelt es sich um die statische Abfrage. Sobald wir erstellt haben, können wir die Struktur der Abfrage nicht ändern.

5
user1679378

Ich möchte kein totes Pferd hier treten, aber es ist wichtig zu erwähnen, dass die Kriterienabfragen jetzt veraltet sind. Verwenden Sie HQL.

4
Eskir

Ich bevorzuge Kriterienabfragen auch für dynamische Abfragen. Aber ich ziehe hql für Löschabfragen vor, zum Beispiel, wenn alle Datensätze aus der untergeordneten Tabelle für die übergeordnete ID 'xyz' gelöscht werden. Dies wird leicht von HQL erreicht, aber für die Kriterien-API müssen wir zunächst n Anzahl der Löschabfragen auslösen, wobei n die Anzahl des Kindes ist Tabellensätze.

1
Punit Patel

Es geht auch anders. Am Ende habe ich einen HQL-Parser erstellt, der auf der ursprünglichen Hibernat-Syntax basiert, so dass zuerst der HQL analysiert und dann dynamische Parameter dynamisch eingefügt oder automatisch einige allgemeine Filter für die HQL-Abfragen hinzugefügt werden. Es funktioniert super!

0
Wallace Peng

Dieser Beitrag ist ziemlich alt. Die meisten Antworten beziehen sich auf Hibernate-Kriterien, nicht auf JPA-Kriterien. JPA 2.1 fügte CriteriaDelete/CriteriaUpdate und EntityGraph hinzu, die steuern, was genau abgerufen werden soll. Kriterien-API ist besser, da Java OO ist. Deshalb wird JPA geschaffen. Wenn JPQL kompiliert wird, wird es in den AST - Baum (OO-Modell) übersetzt, bevor es in SQL übersetzt wird.

0
Sunnyday

Die meisten Antworten sind irreführend und erwähnen, dass Criteria Queries langsamer ist als HQL, was eigentlich nicht der Fall ist.

Wenn Sie tief in die Tiefe gehen und einige Tests durchführen, werden Sie feststellen, dass Kriterienabfragen viel besser sind als reguläre HQL

Und mit Criteria Query erhalten Sie Object Oriented Control, das nicht mit HQL vorhanden ist.

Für weitere Informationen lesen Sie diese Antwort hier .

0
Pritam Banerjee