JPA Criteria Abfragen sind der standardisierte Weg um in Java Quellcode Abfragen zu spezifizieren, die bereits zur Compilezeit geprüft werden können. In diesem Beitrag wird gezeigt, wie das Suchergebnis einer CriteriaQuery sortiert werden kann, indem man die orderBy() Methode des CriteriaQuery interface benutzt.
Das Beispiel nutzt die bekannte unidirektionale 1->n Beziehung zwischen zwei Entitätsklassen Person und Adresse.
Um eine Abfrage aller Personen und die anschließende sofortige aufsteigende Sortierung des Ergebnisses zu veranlassen, würde man folgendes JPQL Statement einsetzen:
select p from Person p order by p.lastName asc;
Das bekannte Beispiel für die Selektion durch eine CriteriaQuery wird dazu angepasst und vor dem Absetzen der Query durch den Entitymanager die Methode orderBy() aufgerufen. Als Argument für den Aufruf benötigt man Order–Objekte, die vom CriteriaBuilder durch Factory-Methoden bereitgestellt werden. Ob die Sortierung auf- bzw. absteigend erfolgen soll, spezifiziert man durch Aufruf der passenden Factory-Methode asc() oder desc() des CriteriaBuilder Interfaces.
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Person.class); Root person = criteriaQuery.from(Person.class); criteriaQuery.select(person); criteriaQuery.orderBy(criteriaBuilder.asc(person.get(Person_.lastName))); List resultList = em.createQuery(criteriaQuery).getResultList();
Die beiden Factory-Methoden bekommen als Argument eine Expresssion Instanz , welche einem sortierbaren Feld einer Entität oder “embeddable” Klasse mit folgenden Eigenschaften entspricht:
- entweder das Feld kommt in dem select oder multiselect vor
- oder das Feld ist ein Argument eines Tuple- oder Array-Konstruktors, den man dem select() als Argument übergibt.
Die orderBy() Methode akzeptiert die Übergabe von mehreren Order-Objekten als Parameter. In diesem Fall bestimmt die Reihenfolge in der Argumentenliste der orderBy() Methode den Vorrang in der späteren Sortierung der CriteriaQuery zur Ausführungszeit.
Folgendes Beispiel zeigt eine solche verkettete Sortierung anhand einer Join-Query, deren Entsprechung in JPQL folgendes Statement wäre :
select p.lastName, a.street from Person p join p.adresses a order by p.lastName asc, a.street asc;
Die Spezifikation des Joins erfolgt wie hier beschrieben. Das zweite Sortierkriterium „street“ wird als weiterer Parameter der orderBy()-Methode übergeben und ebenfalls über die asc-Factorymethode des CriteriaBuilders erzeugt.
EntityManager em = entityManagerFactory.createEntityManager(); CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery criteriaQuery = criteriaBuilder.createTupleQuery(); Root person = criteriaQuery.from(Person.class); SetJoin adresses = person.join(Person_.adresses); criteriaQuery.orderBy(criteriaBuilder.asc(person.get(Person_.lastName)), criteriaBuilder.asc(adresses.get(Address_.street))); criteriaQuery.multiselect(person.get(Person_.lastName), adresses.get(Address_.street)); List resultList = em.createQuery(criteriaQuery).getResultList();
Zusätzlich spezifizieren wir die CriteriaQuery als Tuple-Query und nicht über die Entity-Klasse und nutzen daher nicht die einfache select()-Methode des CriteriaQuery-Interfaces, sondern deren multiselect()-Methode. Die resultierende Query liefert zur Laufzeit daher auch nur eine Liste von (Person_.lastName;Address_.street) Tuple-Objekten zurück.
Einsortiert unter:Java Persistence Tagged: Criteria, Database, Hibernate, JPA, Orderby, persistence, Query
