Gruppierungs- und Aggregationsfunktionen

Sie haben bereits herausgefunden, wie Sie einfache Anfragen an die Kriterien-API stellen. Sehen wir uns an, wie man komplexere Abfragen durchführt.

Wir möchten beispielsweise eine Abfrage schreiben, um die Anzahl der Mitarbeiter in einem Unternehmen zu ermitteln. So wird es in HQL aussehen:

select count(*) from Employee

Und so auf der Kriterien-API:

CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));

Der vollständige Java-Code sieht folgendermaßen aus:

CriteriaBuilder builder = session.getCriteriaBuilder();

CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));

Query<Long> query = session.createQuery(critQuery);
Long count = query.getSingleResult();

Und mit HQL ist es dasselbe:

String hqlQuery = "select count(*) from Employee";

Query<Long> query = session.createQuery(hqlQuery);
Long count = query.getSingleResult();

Versuchen wir nun, das durchschnittliche Gehalt im Unternehmen zu berechnen. Die HQL-Abfrage sieht folgendermaßen aus:

select avg(salary) from Employee

Und so auf der Kriterien-API:

CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));

Der vollständige Java-Code sieht folgendermaßen aus:

CriteriaBuilder builder = session.getCriteriaBuilder();

CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));

Query<Double> query = session.createQuery(critQuery);
Double avgSalary = query.getSingleResult();

KriterienUpdate

Das Ändern einer Tabelle ist genauso einfach wie das Abrufen von Daten daraus. Zu diesem Zweck verfügt CriteriaBuilder über eine spezielle Methode – createCriteriaUpdate() , die ein Objekt erstelltCriteriaUpdate<T>Das aktualisiert die Entitäten in der Datenbank.

Erhöhen wir das Gehalt der Mitarbeiter, die weniger als 10.000 erhalten. So würde diese HQL-Abfrage aussehen:

update Employee set salary = salary+20000 where salary<=10000

Und so wird es auf der Kriterien-API aussehen:

CriteriaUpdate<Employee> criteriaUpdate = builder.createCriteriaUpdate(Employee.class);
Root<Employee> root = criteriaUpdate.from(Employee.class);
criteriaUpdate.set("salary", "salary+20000");
criteriaUpdate.where(builder.lt(root.get("salary"), 10000));

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

KriterienLöschen

Und das Löschen von Datensätzen ist noch einfacher als das Ändern. Dazu gibt es eine spezielle Methode createCriteriaDelete() , die ein Objekt erstelltCriteriaDelete<T>.

Lassen Sie uns alle Mitarbeiter streichen, die keinen Wert haben: Ihr Gehalt beträgt weniger als 10.000. So würde diese HQL-Abfrage aussehen:

delete from Employee where salary<=10000

Und so wird es auf der Kriterien-API aussehen:

CriteriaDelete<Employee> criteriaDelete = builder.createCriteriaDelete(Employee.class);
Root<Employee> root = criteriaDelete.from(Employee.class);
criteriaDelete.where(builder.lt(root.get("salary"), 10000));

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

Vorteile der Kriterien-API

Was ist also der Vorteil der Criteria API? Abfragen sind umständlich, HQL wird definitiv kompakter.

Erstens sind HQL-Abfragen nicht so kurz, wenn Sie ihnen Parameter übergeben müssen. Vergleichen:

Wir berücksichtigen die Anzahl der Mitarbeiter mit einem Gehalt von weniger als 10.000
HQL
String hqlQuery = "from Employee where salary < :sal";
Query<Employee> query = session.createQuery(hqlQuery);
query.setParametr("sal", 10000);
List<Employee> results = query.getResultList();
Kriterien-API
CriteriaBuilder builder = session.getCriteriaBuilder();
critQuery.select(critQuery.from(Employee.class)).where(builder.lt(root.get("salary"), 10000));
Query<Employee> query = session.createQuery(critQuery);
List<Employee> results = query.getResultList();

Zweitens kommt es sehr oft vor, dass eine Abfrage dynamisch erstellt werden muss. Sie verfügen beispielsweise über eine Webseite, auf der Mitarbeiter, Wohnungen usw. gefiltert werden. Und wenn dem Benutzer ein Parameter nicht wichtig ist, gibt er ihn einfach nicht an. Dementsprechend wird stattdessen null an den Server übergeben.

Hier ist Ihre Aufgabe: Mitarbeiter mit einem bestimmten Beruf (Beruf), Gehalt (Gehalt) und Beschäftigungsjahr (YEAR (join_date)) auszuwählen. Wenn jedoch ein Parameterwert null ist, verwenden Sie ihn nicht im Filter.

Dann sieht die HQL-Abfrage etwa so aus:

from Employee
where (occupation = :ocp)
   	and (salary = :sal)
   	and ( YEAR(join_date) = :jny)

Aber es wird nicht richtig funktionieren, da wir möchten, dass die Anfrage so aussehen würde, wenn der Parameter „jny“ null wäre:

from Employee
where (occupation = :ocp)
   	and (salary = :sal)

Wir können versuchen, die Anfrage neu zu schreiben, indem wir den Parameter auf Null prüfen, dann erhalten wir etwa Folgendes:

from Employee
where (occupation = :ocp or :ocp is null)
   	and (salary = :sal or :sal is null)
   	and ( YEAR(join_date)= :jny or :jny is null)

Sehen Sie, wie die Realität komplizierter wird? Die Realität sieht oft so aus :)

Aber der Filter kann noch komplizierter sein. Wie wäre es mit der Suche nach Benutzern, deren Aufgaben das Wort „kaufen“ enthalten? Oder Benutzer, die überfällige Aufgaben haben?

from Employee
where (occupation = :ocp)
   	and (salary = :sal)
   	and (YEAR(join_date) = :jny)
   	and (tasks.name like '%buy%')
   	and (tasks.deadline < curdate())

Wenn Sie in einer solchen Abfrage irgendwo „ or“ schreiben , wird dadurch die Verknüpfung zwischen Tabellen nicht abgebrochen.

Wenn Sie also in der Praxis einen komplexen Filter auf die Felder mehrerer Tabellen anwenden, kann Ihnen die Kriterien-API einfach weiterhelfen. So geht es.

Weitere Details finden Sie in der offiziellen Dokumentation .