Pertanyaan Kriteria JPA

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan membincangkan ciri JPA yang sangat berguna - Pertanyaan Kriteria.

Ini bukan sahaja membolehkan kita menulis pertanyaan tanpa melakukan SQL mentah, tetapi juga memberi kita kawalan Berorientasi Objek terhadap pertanyaan, yang merupakan salah satu ciri utama Hibernate. API Kriteria membolehkan kami membuat objek pertanyaan kriteria secara terprogram, di mana kami dapat menerapkan pelbagai jenis peraturan penyaringan dan keadaan logik.

Sejak Hibernate 5.2, Hibernate Criteria API sudah tidak digunakan lagi dan pengembangan baru difokuskan pada JPA Criteria API. Kami akan meneroka cara menggunakan Hibernate dan JPA untuk membina Pertanyaan Kriteria.

2. Pergantungan Maven

Untuk menggambarkan API, kami akan menggunakan pelaksanaan JPA rujukan - Hibernate.

Untuk menggunakan Hibernate, pastikan anda menambahkan versi terkini ke fail pom.xml anda :

 org.hibernate hibernate-core 5.3.2.Final 

Versi terbaru Hibernate boleh didapati di sini.

3. Contoh Mudah Menggunakan Kriteria

Mari mulakan dengan melihat cara mendapatkan data menggunakan pertanyaan Kriteria Kami akan melihat bagaimana mendapatkan semua contoh kelas tertentu dari pangkalan data.

Kami mempunyai kelas Item yang mewakili tuple "ITEM" dalam pangkalan data:

public class Item implements Serializable { private Integer itemId; private String itemName; private String itemDescription; private Integer itemPrice; // standard setters and getters }

Mari lihat pertanyaan kriteria mudah yang akan mengambil semua baris " ITEM" dari pangkalan data:

Session session = HibernateUtil.getHibernateSession(); CriteriaBuilder cb = session.getCriteriaBuilder(); CriteriaQuery cr = cb.createQuery(Item.class); Root root = cr.from(Item.class); cr.select(root); Query query = session.createQuery(cr); List results = query.getResultList();

Pertanyaan di atas adalah demonstrasi ringkas bagaimana mendapatkan semua item. Mari lihat apa yang dilakukan, langkah demi langkah:

  1. Buat contoh Sesi dari objek SessionFactory
  2. Buat satu contoh C riteriaBuilder dengan menghubungi () getCriteriaBuilder kaedah
  3. Buat contoh CriteriaQuery dengan memanggil kaedah CriteriaBuilder createQuery ()
  4. Buat satu contoh Pertanyaan dengan menghubungi Sesi createQuery () kaedah
  5. Memanggil getResultList () kaedah yang Pertanyaan objek yang memberikan kita keputusan

Setelah kita membahas asasnya, mari beralih ke beberapa ciri pertanyaan kriteria:

3.1. Menggunakan Ungkapan

The CriteriaBuilder boleh digunakan untuk menyekat hasil pertanyaan berdasarkan keadaan tertentu. Dengan menggunakan kaedah CriteriaQuery mana () dan berikan Ekspresi yang dibuat oleh CriteriaBuilder.

Berikut adalah beberapa contoh Ungkapan yang biasa digunakan :

Untuk mendapatkan barang dengan harga lebih dari 1000:

cr.select(root).where(cb.gt(root.get("itemPrice"), 1000));

Seterusnya, dapatkan item yang mempunyai itemHarga kurang dari 1000:

cr.select(root).where(cb.lt(root.get("itemPrice"), 1000));

Item yang mempunyai itemNames mengandungi Kerusi :

cr.select(root).where(cb.like(root.get("itemName"), "%chair%"));

Rekod yang mempunyai itemHarga antara 100 dan 200:

cr.select(root).where(cb.between(root.get("itemPrice"), 100, 200));

Untuk memeriksa sama ada harta yang diberikan adalah nol:

cr.select(root).where(cb.isNull(root.get("itemDescription")));

Untuk memeriksa sama ada harta yang diberikan tidak sah:

cr.select(root).where(cb.isNotNull(root.get("itemDescription")));

Anda juga boleh menggunakan kaedah isEmpty () dan isNotEmpty () untuk menguji sama ada Senarai dalam kelas kosong atau tidak.

Sekarang pasti persoalannya muncul, adakah kita dapat menggabungkan dua atau lebih perbandingan di atas atau tidak. Jawapannya, tentu saja, ya - API Kriteria membolehkan kita merantai ungkapan dengan mudah :

Predicate[] predicates = new Predicate[2]; predicates[0] = cb.isNull(root.get("itemDescription")); predicates[1] = cb.like(root.get("itemName"), "chair%"); cr.select(root).where(predicates);

Untuk menambahkan dua ungkapan dengan operasi logik:

Predicate greaterThanPrice = cb.gt(root.get("itemPrice"), 1000); Predicate chairItems = cb.like(root.get("itemName"), "Chair%");

Item dengan syarat yang ditentukan di atas bergabung dengan Logik ATAU :

cr.select(root).where(cb.or(greaterThanPrice, chairItems));

Untuk mendapatkan item yang sepadan dengan syarat yang ditentukan di atas bergabung dengan Logik DAN :

cr.select(root).where(cb.and(greaterThanPrice, chairItems));

3.2. Menyusun

Setelah mengetahui asas penggunaan Kriteria , mari kita lihat fungsi menyusun Kriteria .

Dalam contoh berikut, kami menyusun senarai dalam urutan menaik nama dan kemudian dalam urutan menurun harga:

cr.orderBy( cb.asc(root.get("itemName")), cb.desc(root.get("itemPrice")));

Pada bahagian seterusnya, kita akan melihat bagaimana melakukan fungsi agregat.

3.3. Unjuran, Agregat dan Fungsi Pengumpulan

Setakat ini kita telah merangkumi sebahagian besar topik asas. Sekarang mari kita lihat fungsi agregat yang berbeza:

Dapatkan kiraan baris:

CriteriaQuery cr = cb.createQuery(Long.class); Root root = cr.from(Item.class); cr.select(cb.count(root)); Query query = session.createQuery(cr); List itemProjected = query.getResultList();

Berikut ini adalah contoh fungsi agregat:

Fungsi agregat untuk Purata :

CriteriaQuery cr = cb.createQuery(Double.class); Root root = cr.from(Item.class); cr.select(cb.avg(root.get("itemPrice"))); Query query = session.createQuery(cr); List avgItemPriceList = query.getResultList();

Kaedah agregat berguna lain yang tersedia adalah jumlah () , maks () , min () , kiraan () dll.

3.4. Kemas kini Kriteria

Bermula dari JPA 2.1, ada dukungan untuk melakukan pembaruan pangkalan data menggunakan Criteria API.

CriteriaUpdate has a set() method that can used to provide new values for database records:

CriteriaUpdate criteriaUpdate = cb.createCriteriaUpdate(Item.class); Root root = criteriaUpdate.from(Item.class); criteriaUpdate.set("itemPrice", newPrice); criteriaUpdate.where(cb.equal(root.get("itemPrice"), oldPrice)); Transaction transaction = session.beginTransaction(); session.createQuery(criteriaUpdate).executeUpdate(); transaction.commit();

In the above snippet, we create an instance of CriteriaUpdate from the CriteriaBuilder and use its set() method to provide new values for the itemPrice. To update multiple properties, we just need to call the set() method multiple times.

3.5. CriteriaDelete

CriteriaDelete, as its name implies, enables a delete operation using the Criteria API. All we need is to create an instance of CriteriaDelete and use the where() method to apply restrictions:

CriteriaDelete criteriaDelete = cb.createCriteriaDelete(Item.class); Root root = criteriaDelete.from(Item.class); criteriaDelete.where(cb.greaterThan(root.get("itemPrice"), targetPrice)); Transaction transaction = session.beginTransaction(); session.createQuery(criteriaDelete).executeUpdate(); transaction.commit();

4. Advantage Over HQL

In the previous sections we've covered how to use Criteria Queries.

Clearly, the main and most hard-hitting advantage of Criteria queries over HQL is the nice, clean, Object Oriented API.

We can simply write more flexible, dynamic queries compared to plain HQL. The logic can be refactored with the IDE and has all the type-safety benefits of the Java language itself.

There are of course some disadvantages as well, especially around more complex joins.

So, generally speaking, we'll have to use the best tool for the job – that can be the Criteria API in most cases, but there are definitely cases where we'll have to go lower level.

5. Conclusion

In this article, we focused on the basics of Criteria Queries in Hibernate and JPA, and also on some of the advanced features of the API.

Kod yang dibincangkan di sini boleh didapati di repositori Github.