Grupperings- och aggregeringsfunktioner

Du har redan kommit på hur du gör enkla förfrågningar till Criteria API. Låt oss se hur man gör mer komplexa frågor.

Vi vill till exempel skriva en fråga för att fastställa antalet anställda i ett företag. Så här kommer det att se ut i HQL:

select count(*) from Employee

Och så här på Criteria API:

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

Hela Java-koden kommer att se ut så här:

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();

Och det är samma sak med HQL:

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

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

Låt oss nu försöka beräkna medellönen i företaget. HQL-frågan kommer att se ut så här:

select avg(salary) from Employee

Och så här på Criteria API:

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

Hela Java-koden kommer att se ut så här:

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();

Uppdatering av kriterier

Att ändra en tabell är lika enkelt som att hämta data från den. För att göra detta har CriteriaBuilder en speciell metod - createCriteriaUpdate() , som skapar ett objektCriteriaUpdate<T>Den som uppdaterar enheterna i databasen.

Låt oss höja lönen för anställda som får mindre än 10 tusen. Så här skulle den här HQL-frågan se ut:

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

Och så här kommer det att se ut på Criteria API:

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();

Kriterier Radera

Och att ta bort poster är ännu lättare än att ändra dem. För att göra detta finns det en speciell metod createCriteriaDelete() , som skapar ett objektKriterier Ta bort<T>.

Låt oss skära alla anställda som inte har något värde: deras lön är mindre än 10 tusen. Så här skulle den här HQL-frågan se ut:

delete from Employee where salary<=10000

Och så här kommer det att se ut på Criteria API:

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();

Fördelar med Criteria API

Så vad är fördelen med Criteria API? Frågor är besvärliga, HQL kommer definitivt att vara mer kompakt.

För det första är HQL-frågor inte så korta om du behöver skicka parametrar till dem. Jämföra:

Vi överväger antalet anställda med en lön på mindre än 10 tusen
HQL
String hqlQuery = "from Employee where salary < :sal";
Query<Employee> query = session.createQuery(hqlQuery);
query.setParametr("sal", 10000);
List<Employee> results = query.getResultList();
Kriterier 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();

För det andra, mycket ofta finns det en situation då en fråga behöver konstrueras dynamiskt. Du har till exempel en webbsida som filtrerar anställda, lägenheter och vad som helst. Och om någon parameter inte är viktig för användaren, indikerar han det helt enkelt inte. Följaktligen skickas null till servern istället.

Här är din uppgift: att välja anställda med ett visst yrke (yrke), lön (lön) och anställningsår (ÅR (join_date)). Men om något parametervärde är null, använd det inte i filtret.

Då kommer HQL-frågan att se ut ungefär så här:

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

Men det kommer inte att fungera korrekt, eftersom vi vill att om parametern "jny" var null, så skulle begäran se ut så här:

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

Vi kan försöka skriva om begäran genom att kontrollera parametern för null, då får vi något sånt här:

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)

Ser du hur verkligheten blir mer komplicerad? Verkligheten är ofta så här :)

Men filtret kan vara ännu mer komplicerat. Vad sägs om att söka efter användare som har uppgifter med ordet "köp" i dem? Eller användare som har försenade uppgifter?

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

Om du skriver eller är null någonstans i en sådan fråga kommer detta inte att avbryta kopplingen mellan tabeller.

Så i praktiken, när du gör något komplext filter på fälten i flera tabeller, kan Criteria API bara hjälpa dig. Så går det.

Mer information finns i den officiella dokumentationen .