Groeperings- en aggregatiefuncties
Je hebt al ontdekt hoe je eenvoudige verzoeken kunt doen aan de Criteria API. Laten we eens kijken hoe we complexere query's kunnen maken.
We willen bijvoorbeeld een query schrijven om het aantal werknemers in een bedrijf te bepalen. Zo ziet het eruit in HQL:
select count(*) from Employee
En zo op de Criteria API:
CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));
De volledige Java-code ziet er als volgt uit:
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();
En het is hetzelfde met HQL:
String hqlQuery = "select count(*) from Employee";
Query<Long> query = session.createQuery(hqlQuery);
Long count = query.getSingleResult();
Laten we nu proberen het gemiddelde salaris in het bedrijf te berekenen. De HQL-query ziet er als volgt uit:
select avg(salary) from Employee
En zo op de Criteria API:
CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));
De volledige Java-code ziet er als volgt uit:
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
Het wijzigen van een tabel is net zo eenvoudig als er gegevens uit halen. Hiervoor heeft CriteriaBuilder een speciale methode - createCriteriaUpdate() , waarmee een object wordt gemaaktCriteriaUpdate<T>De die de entiteiten in de database bijwerkt.
Laten we het salaris verhogen van werknemers die minder dan 10 duizend ontvangen. Dit is hoe deze HQL-query eruit zou zien:
update Employee set salary = salary+20000 where salary<=10000
En zo ziet het eruit op de 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();
CriteriaVerwijderen
En records verwijderen is nog eenvoudiger dan ze wijzigen. Om dit te doen, is er een speciale methode createCriteriaDelete() , die een object maaktCriteriaVerwijderen<T>.
Laten we alle werknemers schrappen die geen waarde hebben: hun salaris is minder dan 10 duizend. Dit is hoe deze HQL-query eruit zou zien:
delete from Employee where salary<=10000
En zo ziet het eruit op de 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();
Voordelen van de Criteria-API
Dus wat is het voordeel van de Criteria API? Query's zijn omslachtig, HQL zal beslist compacter zijn.
Ten eerste zijn HQL-query's niet zo kort als u er parameters aan moet doorgeven. Vergelijken:
We kijken naar het aantal werknemers met een salaris van minder dan 10 duizend |
---|
hoofdkwartier |
|
Criteria-API |
|
Ten tweede is er heel vaak een situatie waarin een query dynamisch moet worden opgebouwd. U hebt bijvoorbeeld een webpagina die werknemers, appartementen en wat dan ook filtert. En als een parameter niet belangrijk is voor de gebruiker, geeft hij deze eenvoudigweg niet aan. Dienovereenkomstig wordt in plaats daarvan null doorgegeven aan de server.
Dit is uw taak: werknemers selecteren met een bepaald beroep (beroep), salaris (salaris) en dienstjaar (YEAR (join_date)). Maar als een parameterwaarde null is, gebruik deze dan niet in het filter.
Dan ziet de HQL-query er ongeveer zo uit:
from Employee
where (occupation = :ocp)
and (salary = :sal)
and ( YEAR(join_date) = :jny)
Maar het zal niet correct werken, omdat we willen dat als de parameter "jny" null was, het verzoek er als volgt uit zou zien:
from Employee
where (occupation = :ocp)
and (salary = :sal)
We kunnen proberen het verzoek te herschrijven door de parameter op null te controleren, dan krijgen we zoiets als dit:
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)
Zie je hoe de werkelijkheid ingewikkelder wordt? De realiteit is vaak zo :)
Maar het filter kan nog ingewikkelder zijn. Hoe zit het met zoeken naar gebruikers die taken hebben met het woord 'kopen' erin? Of gebruikers die achterstallige taken hebben?
from Employee
where (occupation = :ocp)
and (salary = :sal)
and (YEAR(join_date) = :jny)
and (tasks.name like '%buy%')
and (tasks.deadline < curdate())
Als u ergens in zo'n query schrijft of null is , wordt de join tussen tabellen hierdoor niet geannuleerd.
Dus in de praktijk, wanneer u een complex filter uitvoert op de velden van verschillende tabellen, kan de Criteria API u gewoon helpen. Zo gaat het.
Meer details zijn te vinden in de officiële documentatie .