Csoportosítási és aggregációs funkciók

Már rájött, hogyan lehet egyszerű kéréseket benyújtani a Criteria API-hoz. Nézzük meg, hogyan készítsünk összetettebb lekérdezéseket.

Például egy lekérdezést szeretnénk írni egy vállalat alkalmazottainak számának meghatározására. Így fog kinézni HQL-ben:

select count(*) from Employee

És így a Criteria API-n:

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

A teljes Java kód így fog kinézni:

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

És ez ugyanaz a HQL használatával:

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

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

Most próbáljuk meg kiszámítani a vállalat átlagkeresetét. A HQL lekérdezés így fog kinézni:

select avg(salary) from Employee

És így a Criteria API-n:

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

A teljes Java kód így fog kinézni:

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

CriteriaUpdate

A táblázat módosítása ugyanolyan egyszerű, mint az adatok lekérése. Ehhez a CriteriaBuilder egy speciális metódussal rendelkezik - createCriteriaUpdate() , amely létrehoz egy objektumotCriteriaUpdate<T>Ez frissíti az adatbázisban lévő entitásokat.

Emeljük a 10 ezer alatti dolgozók fizetését. Így nézne ki ez a HQL-lekérdezés:

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

És így fog kinézni a Criteria API-n:

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

CriteriaDelete

A rekordok törlése pedig még egyszerűbb, mint megváltoztatni őket. Ehhez van egy speciális metódus createCriteriaDelete() , amely létrehoz egy objektumotCriteriaDelete<T>.

Vágjunk le minden olyan alkalmazottat, akinek nincs értéke: 10 ezer alatt van a fizetése. Így nézne ki ez a HQL-lekérdezés:

delete from Employee where salary<=10000

És így fog kinézni a Criteria API-n:

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

A Criteria API előnyei

Tehát mi az előnye a Criteria API-nak? A lekérdezések nehézkesek, a HQL biztosan kompaktabb lesz.

Először is, a HQL lekérdezések nem olyan rövidek, ha paramétereket kell átadni nekik. Összehasonlítás:

A 10 ezer fő alatti fizetésű alkalmazottak számát tekintjük
HQL
String hqlQuery = "from Employee where salary < :sal";
Query<Employee> query = session.createQuery(hqlQuery);
query.setParametr("sal", 10000);
List<Employee> results = query.getResultList();
Criteria 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();

Másodszor, nagyon gyakran van olyan helyzet, amikor egy lekérdezést dinamikusan kell felépíteni. Például van egy weboldala, amely szűri az alkalmazottakat, lakásokat és bármit. És ha egy paraméter nem fontos a felhasználó számára, akkor egyszerűen nem jelzi. Ennek megfelelően nullát ad át a szervernek.

Íme az Ön feladata: válasszon ki egy bizonyos szakmával (foglalkozással), fizetéssel (bérrel) és a munkaviszony évével (YEAR (csatlakozási_dátum)) rendelkező munkavállalókat. De ha bármely paraméter értéke null, akkor ne használja a szűrőben.

Ekkor a HQL lekérdezés valahogy így fog kinézni:

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

De ez nem fog megfelelően működni, mivel azt szeretnénk, ha a "jny" paraméter nulla lenne, akkor a kérés így néz ki:

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

Megpróbálhatjuk átírni a kérést úgy, hogy a paramétert nullra ellenőrizzük, ekkor valami ilyesmit kapunk:

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)

Látod, hogyan válik bonyolultabbá a valóság? A valóság sokszor ilyen :)

De a szűrő még bonyolultabb lehet. Mit szólnál, ha olyan felhasználókat keresnél, akiknek a "vásárlás" szót tartalmazó feladataik vannak? Vagy azok a felhasználók, akiknek lejárt feladataik vannak?

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

Ha egy ilyen lekérdezésben valahova nullát ír , akkor ez nem törli a táblák összekapcsolását.

Tehát a gyakorlatban, amikor bármilyen összetett szűrést végez több tábla mezőin, a Criteria API csak segíthet. Ez így megy.

További részletek a hivatalos dokumentációban találhatók .