Gruplandırma ve toplama işlevleri

Criteria API'sine basit isteklerin nasıl yapılacağını zaten öğrendiniz. Daha karmaşık sorguların nasıl yapıldığını görelim.

Örneğin bir şirketteki çalışan sayısını belirlemek için bir sorgu yazmak istiyoruz. HQL'de şöyle görünecek:

select count(*) from Employee

Ve Criteria API'sinde bunun gibi:

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

Java kodunun tamamı şöyle görünecektir:

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

HQL kullanırken de durum aynıdır:

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

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

Şimdi şirketteki ortalama maaşı hesaplamaya çalışalım. HQL sorgusu şöyle görünecektir:

select avg(salary) from Employee

Ve Criteria API'sinde bunun gibi:

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

Java kodunun tamamı şöyle görünecektir:

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

Kriter Güncellemesi

Bir tabloyu değiştirmek, ondan veri almak kadar kolaydır. Bunu yapmak için, CriteriaBuilder'ın özel bir yöntemi vardır - bir nesne oluşturan createCriteriaUpdate() .Kriter Güncellemesi<T>Bu, veritabanındaki varlıkları günceller.

10 binin altında maaş alan çalışanların maaşına zam yapalım. Bu HQL sorgusu şöyle görünür:

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

Criteria API'sinde şu şekilde görünecek:

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

KriterSil

Ve kayıtları silmek, onları değiştirmekten daha kolaydır. Bunu yapmak için, bir nesne oluşturan createCriteriaDelete() özel bir yöntemi vardır.ÖlçütSil<T>.

Değeri olmayan tüm çalışanları keselim: maaşı 10 binden az. Bu HQL sorgusu şöyle görünür:

delete from Employee where salary<=10000

Criteria API'sinde şu şekilde görünecek:

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

Criteria API'nin Avantajları

Peki Criteria API'nin faydası nedir? Sorgular zahmetlidir, HQL kesinlikle daha derli toplu olacaktır.

İlk olarak, parametreleri onlara iletmeniz gerekiyorsa, HQL sorguları o kadar kısa değildir. Karşılaştırmak:

10 binin altında maaş alan çalışan sayısını dikkate alıyoruz.
HQL
String hqlQuery = "from Employee where salary < :sal";
Query<Employee> query = session.createQuery(hqlQuery);
query.setParametr("sal", 10000);
List<Employee> results = query.getResultList();
Kriter API'si
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();

İkincisi, çoğu zaman bir sorgunun dinamik olarak oluşturulması gereken bir durum vardır. Örneğin, çalışanları, daireleri ve her şeyi filtreleyen bir web sayfanız var. Ve bazı parametreler kullanıcı için önemli değilse, o zaman bunu belirtmez. Buna göre, sunucuya bunun yerine null iletilir.

İşte göreviniz: belirli bir mesleğe (meslek), maaşa (maaş) ve çalışma yılına (YIL (join_date)) sahip çalışanları seçmek. Ancak herhangi bir parametre değeri boşsa, bunu filtrede kullanmayın.

Ardından, HQL sorgusu şuna benzer:

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

Ancak "jny" parametresinin boş olması durumunda isteğin şöyle görünmesini istediğimiz için doğru çalışmaz:

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

Parametreyi null için kontrol ederek isteği yeniden yazmayı deneyebiliriz, o zaman şöyle bir şey elde ederiz:

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)

Gerçekliğin nasıl daha karmaşık hale geldiğini görüyor musunuz? Gerçek genellikle böyledir :)

Ancak filtre daha da karmaşık olabilir. İçinde "satın al" kelimesi olan görevleri olan kullanıcıları aramaya ne dersiniz? Veya gecikmiş görevleri olan kullanıcılar?

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

Böyle bir sorguda herhangi bir yere or is null yazarsanız , bu, tablolar arasındaki birleştirmeyi iptal etmez.

Pratikte, birkaç tablonun alanlarında herhangi bir karmaşık filtre uyguladığınızda, Criteria API size yardımcı olabilir. O zaman o gider.

Daha fazla ayrıntı resmi belgelerde bulunabilir .