Funzioni di raggruppamento e aggregazione

Hai già capito come effettuare semplici richieste all'API Criteria. Vediamo come fare query più complesse.

Ad esempio, vogliamo scrivere una query per determinare il numero di dipendenti in un'azienda. Ecco come apparirà in HQL:

select count(*) from Employee

E così sull'API Criteria:

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

Il codice Java completo sarà simile a questo:

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

Ed è lo stesso usando HQL:

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

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

Ora proviamo a calcolare lo stipendio medio in azienda. La query HQL sarà simile a questa:

select avg(salary) from Employee

E così sull'API Criteria:

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

Il codice Java completo sarà simile a questo:

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

CriteriAggiornamento

Modificare una tabella è facile come ottenere dati da essa. Per fare ciò, CriteriaBuilder ha un metodo speciale - createCriteriaUpdate() , che crea un oggettoAggiornamento criteri<T>Il che aggiorna le entità nel database.

Alziamo lo stipendio dei dipendenti che percepiscono meno di 10mila. Ecco come sarebbe questa query HQL:

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

Ed ecco come apparirà sull'API Criteria:

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

CriteriElimina

Ed eliminare i record è ancora più semplice che modificarli. Per fare ciò, esiste un metodo speciale createCriteriaDelete() , che crea un oggettoCriteri Elimina<T>.

Tagliamo tutti i dipendenti che non hanno valore: il loro stipendio è inferiore a 10mila. Ecco come sarebbe questa query HQL:

delete from Employee where salary<=10000

Ed ecco come apparirà sull'API Criteria:

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

Vantaggi dell'API Criteria

Quindi qual è il vantaggio dell'API Criteria? Le query sono ingombranti, HQL sarà sicuramente più compatto.

In primo luogo, le query HQL non sono così brevi se è necessario passare loro dei parametri. Confrontare:

Consideriamo il numero di dipendenti con uno stipendio inferiore a 10mila
HQL
String hqlQuery = "from Employee where salary < :sal";
Query<Employee> query = session.createQuery(hqlQuery);
query.setParametr("sal", 10000);
List<Employee> results = query.getResultList();
API dei criteri
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();

In secondo luogo, molto spesso si verifica una situazione in cui una query deve essere costruita dinamicamente. Ad esempio, hai una pagina web che filtra dipendenti, appartamenti e qualsiasi altra cosa. E se qualche parametro non è importante per l'utente, semplicemente non lo indica. Di conseguenza, null viene invece passato al server.

Ecco il tuo compito: selezionare i dipendenti con una determinata professione (occupazione), stipendio (stipendio) e anno di impiego (YEAR (join_date)). Ma se un valore di parametro è nullo, non utilizzarlo nel filtro.

Quindi la query HQL sarà simile a questa:

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

Ma non funzionerà correttamente, poiché vogliamo che se il parametro "jny" fosse nullo, la richiesta sarebbe simile a questa:

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

Possiamo provare a riscrivere la richiesta controllando il parametro per null, quindi otterremo qualcosa del genere:

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)

Vedi come la realtà diventa più complicata? La realtà spesso è così :)

Ma il filtro può essere ancora più complicato. Che ne dici di cercare utenti che hanno attività con la parola "acquista"? O utenti che hanno attività scadute?

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

Se scrivi o è nullo da qualche parte in tale query , questo non annullerà il join tra le tabelle.

Quindi, in pratica, quando esegui un filtro complesso sui campi di diverse tabelle, l'API Criteria può aiutarti. Così è andata.

Maggiori dettagli possono essere trovati nella documentazione ufficiale .