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 |
|
Criteria API |
|
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 .
GO TO FULL VERSION