JPA-Kriterienabfragen

JPA-Kriterienabfragen

1. Überblick

In diesem Tutorial wird eine sehr nützliche JPA-Funktion erläutert - Kriterienabfragen.

Es ermöglicht uns nicht nur das Schreiben von Abfragen ohne SQL-Rohdaten, sondern gibt uns auch eine objektorientierte Kontrolle über die Abfragen, was eine der Hauptfunktionen von Hibernate ist. Mit der Kriterien-API können wir ein Kriterien-Abfrageobjekt programmgesteuert aufbauen, wobei wir verschiedene Arten von Filterregeln und logischen Bedingungen anwenden können.

Since Hibernate 5.2, the Hibernate Criteria API is deprecated and new development is focused on the JPA Criteria API. Wir werden untersuchen, wie Sie mit Hibernate und JPA Kriterienabfragen erstellen.

2. Maven-Abhängigkeiten

Zur Veranschaulichung der API verwenden wir die Referenz-JPA-Implementierung "Ruhezustand".

Um den Ruhezustand zu verwenden, stellen Sie sicher, dass Sie die neueste Version zur Dateipom.xmlhinzufügen:


    org.hibernate
    hibernate-core
    5.3.2.Final

Die neueste Version von Hibernate finden Sie unterhere.

3. Einfaches Beispiel unter Verwendung von Kriterien

Beginnen wir mit dem Abrufen von Daten mithilfe von Kriterienabfragen. Wir werden uns ansehen, wie Sie alle Instanzen einer bestimmten Klasse aus der Datenbank abrufen können.

Wir haben eineItem-Klasse, die das Tupel“ITEM” in der Datenbank darstellt:

public class Item implements Serializable {

    private Integer itemId;
    private String itemName;
    private String itemDescription;
    private Integer itemPrice;

   // standard setters and getters
}

Schauen wir uns eine einfache Kriterienabfrage an, mit der alle Zeilen von "ITEM”" aus der Datenbank abgerufen werden:

Session session = HibernateUtil.getHibernateSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery cr = cb.createQuery(Item.class);
Root root = cr.from(Item.class);
cr.select(root);

Query query = session.createQuery(cr);
List results = query.getResultList();

Die obige Abfrage ist eine einfache Demonstration, wie alle Elemente abgerufen werden. Mal sehen, was Schritt für Schritt getan wurde:

  1. Erstellen Sie eine Instanz vonSession aus dem ObjektSessionFactory

  2. Erstellen Sie eine Instanz von CriteriaBuilder, indem Sie die MethodegetCriteriaBuilder() aufrufen

  3. Erstellen Sie eine Instanz vonCriteriaQuery, indem SieCriteriaBuildercreateQuery() method aufrufen

  4. Erstellen Sie eine Instanz vonQuery, indem Sie dieSessioncreateQuery()-Methode aufrufen

  5. Rufen Sie diegetResultList()-Methode desquery-Objekts auf, die die Ergebnisse liefert

Nachdem wir uns nun mit den Grundlagen befasst haben, gehen wir zu einigen Funktionen der Kriterienabfrage über:

3.1. Verwenden vonExpressions

The CriteriaBuilder can be used to restrict query results based on specific conditions. Verwenden Sie die MethodeCriteriaQuery where() und geben SieExpressions an, die vonCriteriaBuilder. erstellt wurden

Hier einige Beispiele für häufig verwendeteExpressions:

So erhalten Sie Artikel mit einem Preis von mehr als 1000:

cr.select(root).where(cb.gt(root.get("itemPrice"), 1000));

Als nächstes erhalten Sie Elemente mititemPrice kleiner als 1000:

cr.select(root).where(cb.lt(root.get("itemPrice"), 1000));

Elemente mititemNames enthaltenChair:

cr.select(root).where(cb.like(root.get("itemName"), "%chair%"));

Datensätze mititemPrice zwischen 100 und 200:

cr.select(root).where(cb.between(root.get("itemPrice"), 100, 200));

So überprüfen Sie, ob die angegebene Eigenschaft null ist:

cr.select(root).where(cb.isNull(root.get("itemDescription")));

So überprüfen Sie, ob die angegebene Eigenschaft nicht null ist:

cr.select(root).where(cb.isNotNull(root.get("itemDescription")));

Sie können auch die MethodenisEmpty() undisNotEmpty() verwenden, um zu testen, ob einList innerhalb einer Klasse leer ist oder nicht.

Nun kommt unweigerlich die Frage auf, ob wir zwei oder mehr der oben genannten Vergleiche kombinieren können oder nicht. Die Antwort lautet natürlich ja -the Criteria API allows us to easily chain expressions:

Predicate[] predicates = new Predicate[2];
predicates[0] = cb.isNull(root.get("itemDescription"));
predicates[1] = cb.like(root.get("itemName"), "chair%");
cr.select(root).where(predicates);

So fügen Sie zwei Ausdrücke mit logischen Operationen hinzu:

Predicate greaterThanPrice = cb.gt(root.get("itemPrice"), 1000);
Predicate chairItems = cb.like(root.get("itemName"), "Chair%");

Elemente mit den oben definierten Bedingungen, verbunden mitLogical OR:

cr.select(root).where(cb.or(greaterThanPrice, chairItems));

So erhalten Sie Elemente, die mit den oben definierten Bedingungen übereinstimmen, verbunden mitLogical AND:

cr.select(root).where(cb.and(greaterThanPrice, chairItems));

3.2. Sortierung

Nachdem wir die grundlegende Verwendung vonCriteria kennen, werfen wir einen Blick auf die Sortierfunktionen vonCriteria.

Im folgenden Beispiel ordnen wir die Liste in aufsteigender Reihenfolge des Namens und dann in absteigender Reihenfolge des Preises:

cr.orderBy(
  cb.asc(root.get("itemName")),
  cb.desc(root.get("itemPrice")));

Im nächsten Abschnitt sehen wir uns an, wie Aggregatfunktionen ausgeführt werden.

3.3. Projektionen, Aggregate und Gruppierungsfunktionen

Bisher haben wir die meisten grundlegenden Themen behandelt. Schauen wir uns nun die verschiedenen Aggregatfunktionen an:

Zeilenzahl abrufen:

CriteriaQuery cr = cb.createQuery(Long.class);
Root root = cr.from(Item.class);
cr.select(cb.count(root));
Query query = session.createQuery(cr);
List itemProjected = query.getResultList();

Das Folgende ist ein Beispiel für Aggregatfunktionen:

Aggregate Funktion fürAverage:

CriteriaQuery cr = cb.createQuery(Double.class);
Root root = cr.from(Item.class);
cr.select(cb.avg(root.get("itemPrice")));
Query query = session.createQuery(cr);
List avgItemPriceList = query.getResultList();

Andere nützliche Aggregatmethoden, die verfügbar sind, sindsum(),max(),min(),count() usw.

3.4. CriteriaUpdate

Ab JPA 2.1 wird die Durchführung von Datenbankaktualisierungen mithilfe derCriteria-API unterstützt.

CriteriaUpdate verfügt über eineset()-Methode, mit der neue Werte für Datenbankeinträge bereitgestellt werden können:

CriteriaUpdate criteriaUpdate = cb.createCriteriaUpdate(Item.class);
Root root = criteriaUpdate.from(Item.class);
criteriaUpdate.set("itemPrice", newPrice);
criteriaUpdate.where(cb.equal(root.get("itemPrice"), oldPrice));

Transaction transaction = session.beginTransaction();
session.createQuery(criteriaUpdate).executeUpdate();
transaction.commit();

Im obigen Snippet erstellen wir eine Instanz vonCriteriaUpdate<Item>  ausCriteriaBuilder und verwenden dieset()-Methode, um neue Werte füritemPrice. bereitzustellen. Um mehrere Eigenschaften zu aktualisieren, müssen wir nur Rufen Sie die Methodeset()mehrmals auf.

3.5. CriteriaDelete

CriteriaDelete, ermöglicht, wie der Name schon sagt, einen Löschvorgang mithilfe derCriteria-API. Wir müssen lediglich eine Instanz vonCriteriaDelete erstellen und die Methodewhere() verwenden, um Einschränkungen anzuwenden:

CriteriaDelete criteriaDelete = cb.createCriteriaDelete(Item.class);
Root root = criteriaDelete.from(Item.class);
criteriaDelete.where(cb.greaterThan(root.get("itemPrice"), targetPrice));

Transaction transaction = session.beginTransaction();
session.createQuery(criteriaDelete).executeUpdate();
transaction.commit();

4. Vorteil gegenüber HQL

In den vorherigen Abschnitten haben wir uns mit der Verwendung von Kriterienabfragen befasst.

Es ist klar, dassthe main and most hard-hitting advantage of Criteria queries over HQL is the nice, clean, Object Oriented API.

Wir können einfach flexiblere, dynamischere Abfragen schreiben als mit normalem HQL. Die Logik kann mit der IDE überarbeitet werden und bietet alle typenschutzbezogenen Vorteile der Java-Sprache.

Es gibt natürlich auch einige Nachteile, insbesondere bei komplexeren Verknüpfungen.

Im Allgemeinen müssen wir also das beste Tool für den Job verwenden - das kann in den meisten Fällen die Kriterien-API sein, aber es gibt definitiv Fälle, in denen wir auf eine niedrigere Ebene gehen müssen.

5. Fazit

In diesem Artikel haben wir uns auf die Grundlagen der Kriterienabfragen in Ruhezustand und JPA sowie auf einige der erweiterten Funktionen der API konzentriert.

Der hier beschriebene Code ist inGithub repository verfügbar.