Hibernate-Tipps: Skalare Werte mittels Criteria-Abfrage selektieren

Neuigkeiten von der Insel  –  1 Kommentare

Die Hibernate-Tipps-Serie bietet schnelle und einfache Lösungen zu verbreiteten Hibernate-Fragen. Dieses Mal geht es um die Verwendung einer skalaren Projektion in Criteria-Abfragen.

Frage:

Mit JPQL-Abfragen (Java Persistence Query Language) können Entwickler mehrere skalare Werte selektieren. Kann ich mit einer Criteria-Abfrage die gleiche Projektion verwenden oder muss ich immer Entitäten oder DTOs (Data Transfer Object) selektieren?

Lösung:

Auch wenn die Criteria API häufig etwas unübersichtlich erscheint, unterstützt sie dieselben Features wie JPQL. Projektionen mehrerer skalarer Werte sind daher genauso möglich wie Projektionen, die Entitäten, DTOs und skalare Werte miteinander kombinieren.

Um mehrere skalare Werte zu selektieren, lässt sich die multiselect(Selection<?>... selections)-Methode verwenden. Der nachfolgende Quellcode zeigt ein Beispiel für eine solche Abfrage:

// Abfrage erzeugen
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> q = cb.createTupleQuery();
Root<Author> author = q.from(Author.class);

// Mehrere skalare Werte selektieren
q.multiselect(author.get(Author_.firstName).alias("firstName"), author.get(Author_.lastName).alias("lastName"));

// Abfrage ausführen
List<Tuple> authorNames = em.createQuery(q).getResultList();

for (Tuple authorName : authorNames) {
log.info(authorName.get("firstName") + " " + authorName.get("lastName"));
}

Die multiselect-Methode erwartet eine List oder ein Array von Selection-Interfaces, die die zu selektierenden Entitätseigenschaften benennen. In diesem Beispiel verwende ich das JPA-Metamodell, um die Eigenschaften typsicher zu referenzieren.

Wenn das Beispiel ausgeführt wird, erzeugt Hibernate eine SQL-Abfrage, die nur die von der multiselect-Methode referenzierten Datenbankspalten selektiert:

13:57:18,403 INFO[org.thoughts.on.java.model.TestCriteriaTuples] - ... selectTuples ...
13:57:18,818 INFO[org.hibernate.hql.internal.QueryTranslatorFactoryInitiator] - HHH000397: Using ASTQueryTranslatorFactory
13:57:19,158 DEBUG [org.hibernate.SQL] -
select
author0_.firstName as col_0_0_,
author0_.lastName as col_1_0_
from
Author author0_
13:57:19,188 INFO[org.thoughts.on.java.model.TestCriteriaTuples] - Thorben Janssen
13:57:19,188 INFO[org.thoughts.on.java.model.TestCriteriaTuples] - Joshua Bloch
13:57:19,189 INFO[org.thoughts.on.java.model.TestCriteriaTuples] - Gavin King

Das Abfrageergebnis wird anschließend als List von Tuple-Interfaces zurückgegeben. Das Tuple-Interface bietet einen komfortablen Zugriff auf die selektierten Eigenschaften. Dabei können die selektierten Spalten per Index oder, wie in diesem Beispiel, auch über den als Alias vergebenen Namen referenziert werden.

Hibernate Tips – das Buch

Mehr als 70 solcher Rezepte zu Themen wie einfache und komplexe Mappingdefinitionen, Logging, Unterstützung von Java 8, Caching sowie die statische und dynamische Erzeugung von Abfragen gibt es in meinem Buch "Hibernate Tips: More than 70 solutions to common Hibernate problems". Es ist als Taschenbuch und E-Book auf Amazon und als PDF auf hibernate-tips.com erhältlich.