Sortieren mit Ruhezustand

1. Übersicht

Dieser Artikel beschreibt, wie mit Hibernate sortiert wird , wobei sowohl die Hibernate Query Language (HQL) als auch die Criteria-API verwendet werden.

2. Sortieren mit HQL

Das Sortieren mit Hibernates HQL ist so einfach wie das Hinzufügen der Order By- Klausel zur HQL-Abfragezeichenfolge:

String hql = "FROM Foo f ORDER BY f.name"; Query query = sess.createQuery(hql);

Nachdem dieser Code ausgeführt wurde, generiert Hibernate die folgende SQL-Abfrage:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ from FOO foo0_ order by foo0_.NAME

Die Standardrichtung für die Sortierreihenfolge ist aufsteigend. Aus diesem Grund ist die Bestellbedingung asc nicht in der generierten SQL-Abfrage enthalten.

2.1. Verwenden einer expliziten Sortierreihenfolge

Um die Sortierreihenfolge manuell anzugeben, müssen Sie die Auftragsrichtung in die HQL- Abfragezeichenfolge aufnehmen:

String hql = "FROM Foo f ORDER BY f.name ASC"; Query query = sess.createQuery(hql);

In diesem Beispiel wurde das Setzen der asc- Klausel in der HQL in die generierte SQL-Abfrage aufgenommen:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ from FOO foo0_ order by foo0_.NAME ASC

2.2. Sortieren nach mehr als einem Attribut

Der Order By- Klausel in der HQL-Abfragezeichenfolge können mehrere Attribute zusammen mit einer optionalen Sortierreihenfolge hinzugefügt werden :

String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC"; Query query = sess.createQuery(hql);

Die generierte SQL-Abfrage ändert sich entsprechend:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ from FOO foo0_ order by foo0_.NAME DESC, foo0_.ID ASC

2.3. Festlegen der Sortierrangfolge von Nullwerten

Wenn das zu sortierende Attribut Nullwerte hat , muss das RDMS standardmäßig die Priorität festlegen. Diese Standardbehandlung kann überschrieben werden, indem eine NULLS FIRST- oder NULLS LAST- Klausel in die HQL- Abfragezeichenfolge eingefügt wird .

In diesem einfachen Beispiel werden Nullen am Ende der Ergebnisliste platziert:

String hql = "FROM Foo f ORDER BY f.name NULLS LAST"; Query query = sess.createQuery(hql);

Sehen wir uns an, dass die Klausel in der generierten SQL-Abfrage null und dann 1 else 0 ist :

Hibernate: select foo0_.ID as ID1_1_, foo0_.NAME as NAME2_1_, foo0_.BAR_ID as BAR_ID3_1_, foo0_.idx as idx4_1_ from FOO foo0_ order by case when foo0_.NAME is null then 1 else 0 end, foo0_.NAME

2.4. Eins zu viele Beziehungen sortieren

Analysieren wir einen komplexen Sortierfall: Sortieren von Entitäten in einer Eins-zu-Viele-Beziehung - Leiste mit einer Sammlung von Foo- Entitäten.

Dazu kommentieren wir die Sammlung mit der Annotation Hibernate @OrderBy . Wir geben das Feld an, nach dem die Bestellung erfolgt, sowie die Richtung:

@OrderBy(clause = "NAME DESC") Set fooList = new HashSet();

Beachten Sie das Klauselargument zur Annotation. Dies gilt nur für @OrderBy von Hibernate im Vergleich zu ähnlichen JPA-Annotationen von @OrderBy . Ein weiteres Merkmal , das diesen Ansatz aus seiner JPA äquivalent unterscheidet , ist , dass die Klausel Argument gibt an, daß die Sortierung auf der Grundlage der durchgeführt wird BEZEICHNUNG Spalte der FOO - Tabelle, nicht auf dem Namensattribut von Foo .

Schauen wir uns nun die tatsächliche Sortierung von Bars und Foos an :

String hql = "FROM Bar b ORDER BY b.id"; Query query = sess.createQuery(hql);

Die resultierende SQL-Anweisung zeigt, dass die sortierten Foo's in einer fooList platziert sind:

Hibernate: select bar0_.ID as ID1_0_, bar0_.NAME as NAME2_0_ from BAR bar0_ order by bar0_.ID Hibernate: select foolist0_.BAR_ID as BAR_ID3_0_0_, foolist0_.ID as ID1_1_0_, foolist0_.ID as ID1_1_1_, foolist0_.NAME as NAME2_1_1_, foolist0_.BAR_ID as BAR_ID3_1_1_, foolist0_.idx as idx4_1_1_ from FOO foolist0_ where foolist0_.BAR_ID=? order by foolist0_.NAME desc

Beachten Sie, dass es nicht möglich ist, Listen zu sortieren, wie dies bei JPA der Fall war. In der Dokumentation zum Ruhezustand heißt es:

„Hibernate ignoriert derzeit @OrderBy auf @ElementCollection auf zB List. Die Reihenfolge der Elemente ist wie von der Datenbank zurückgegeben und undefiniert. “

Als Randnotiz wäre es möglich, diese Einschränkung zu umgehen, indem die alte XML-Konfiguration für den Ruhezustand verwendet und die ersetzt wird Element mit a Element.

3. Sortieren nach Ruhezustandskriterien

Die Kriterienobjekt-API stellt die Order- Klasse als Haupt-API zum Verwalten der Sortierung bereit .

3.1. Sortierreihenfolge einstellen

Die Order- Klasse verfügt über zwei Methoden zum Festlegen der Sortierreihenfolge:

  • asc (String-Attribut) : Sortiert die Abfrage nach Attribut in aufsteigender Reihenfolge.
  • desc (String-Attribut) : Sortiert die Abfrage nach Attribut in absteigender Reihenfolge.

Beginnen wir mit einem einfachen Beispiel - Sortieren nach einem einzelnen ID- Attribut:

Criteria criteria = sess.createCriteria(Foo.class, "FOO"); criteria.addOrder(Order.asc("id"));

Beachten Sie, dass das Argument für die ASC- Methode zwischen Groß- und Kleinschreibung unterscheidet und mit dem Namen des Attributs übereinstimmen sollte , nach dem sortiert werden soll.

Die Objekt-API von Hibernate Criteria legt explizit eine Sortierreihenfolge fest. Dies spiegelt sich in der vom Code generierten SQL-Anweisung wider:

Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_ from FOO this_ order by this_.ID sac

3.2. Sortieren nach mehr als einem Attribut

Das Sortieren nach mehreren Attributen erfordert nur das Hinzufügen eines Order- Objekts zur Criteria- Instanz, wie im folgenden Beispiel:

Criteria criteria = sess.createCriteria(Foo.class, "FOO"); criteria.addOrder(Order.asc("name")); criteria.addOrder(Order.asc("id"));

Die in SQL generierte Abfrage lautet:

Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_ from FOO this_ order by this_.NAME asc, this_.ID sac

3.3. Festlegen der Sortierrangfolge von Nullwerten

By default, when the attribute to sort by has null values, it is up to the RDMS to decide the precedence. Hibernate Criteria Object API makes it simple to change that default and place nulls at the end of an ascending ordered list:

Criteria criteria = sess.createCriteria(Foo.class, "FOO"); criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST));

Here is the underlying SQL query – with the is null then 1 else 0 clause:

Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_, this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when this_.NAME is null then 1 else 0 end, this_.NAME asc

Alternatively, we can also place the nulls at the beginning of a descending ordered list:

Criteria criteria = sess.createCriteria(Foo.class, "FOO"); criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST));

The corresponding SQL query follows – with the is null then 0 else 1 clause:

Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_, this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when this_.NAME is null then 0 else 1 end, this_.NAME desc

Note that, if the attribute to sort by is a primitive type like an int, a PresisitenceException will thrown.

Wenn der Wert von f.anIntVariable beispielsweise null ist, wird die Abfrage ausgeführt:

String jql = "Select f from Foo as f order by f.anIntVariable desc NULLS FIRST"; Query sortQuery = entityManager.createQuery(jql);

wird werfen:

javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of com.cc.jpa.example.Foo.anIntVariable

4. Fazit

In diesem Artikel wird das Sortieren im Ruhezustand erläutert. Dabei werden die verfügbaren APIs sowohl für einfache Entitäten als auch für Entitäten in einer Eins-zu-Viele-Beziehung verwendet.

Die Implementierung dieses Tutorial zum Sortieren im Ruhezustand finden Sie im Github-Projekt. Dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.