Menyortir dengan Hibernate

1. Ikhtisar

Artikel ini mengilustrasikan cara mengurutkan dengan Hibernate , menggunakan Hibernate Query Language (HQL) dan Criteria API.

2. Menyortir Dengan HQL

Menyortir dengan HQL Hibernate semudah menambahkan klausa Order By ke string kueri HQL:

String hql = "FROM Foo f ORDER BY f.name"; Query query = sess.createQuery(hql);

Setelah kode ini dijalankan, Hibernate akan menghasilkan kueri SQL berikut:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ from FOO foo0_ order by foo0_.NAME

Arah urutan pengurutan default adalah menaik. Inilah mengapa kondisi pesanan, asc , tidak disertakan dalam kueri SQL yang dihasilkan.

2.1. Menggunakan Urutan Sortir Eksplisit

Untuk menentukan urutan penyortiran secara manual - Anda harus menyertakan arah urutan dalam string kueri HQL :

String hql = "FROM Foo f ORDER BY f.name ASC"; Query query = sess.createQuery(hql);

Dalam contoh ini, pengaturan klausa asc di HQL disertakan dalam kueri SQL yang dihasilkan:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ from FOO foo0_ order by foo0_.NAME ASC

2.2. Menyortir Berdasarkan Lebih dari Satu Atribut

Beberapa atribut, bersama dengan urutan pengurutan opsional, dapat ditambahkan ke klausa Urutan Menurut di string kueri HQL:

String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC"; Query query = sess.createQuery(hql);

Kueri SQL yang dihasilkan akan berubah sesuai:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ from FOO foo0_ order by foo0_.NAME DESC, foo0_.ID ASC

2.3. Pengaturan Urutan Urutan Nilai Null

Secara default, jika atribut yang akan diurutkan memiliki nilai null , RDMS-lah yang memutuskan prioritasnya. Pengobatan default ini dapat ditimpa dengan menempatkan sebuah NULLS PERTAMA atau NULLS TERAKHIR klausul dalam string HQL permintaan .

Contoh sederhana ini menempatkan null apa pun di akhir daftar hasil:

String hql = "FROM Foo f ORDER BY f.name NULLS LAST"; Query query = sess.createQuery(hql);

Mari kita lihat klausa is null lalu 1 else 0 dalam kueri SQL yang dihasilkan :

Hibernate: select foo0_.ID as ID1_1_, foo0_.NAME as NAME2_1_, foo0_.BAR_ID as BAR_ID3_1_, foo0_.idx as idx4_1_ from FOO foo0_ order by case when foo0_.NAME is null then 1 else 0 end, foo0_.NAME

2.4. Menyortir Satu Untuk Banyak Hubungan

Mari menganalisis kasus pengurutan yang kompleks: menyortir entitas dalam relasi satu ke banyak - Bar berisi kumpulan entitas Foo .

Kami akan melakukan ini dengan memberi anotasi pada koleksi dengan anotasi Hibernate @OrderBy ; kami akan menentukan bidang tempat pemesanan dilakukan, serta arahnya:

@OrderBy(clause = "NAME DESC") Set fooList = new HashSet();

Perhatikan argumen klausa untuk anotasi tersebut. Ini unik untuk @OrderBy Hibernate , dibandingkan dengan anotasi JPA @OrderBy yang serupa . Karakteristik lain yang membedakan pendekatan ini dari padanan JPA-nya adalah bahwa argumen klausa menunjukkan bahwa pengurutan dilakukan berdasarkan kolom NAME pada tabel FOO , bukan pada atribut nama Foo .

Sekarang mari kita lihat pengurutan sebenarnya dari Bar dan Foos :

String hql = "FROM Bar b ORDER BY b.id"; Query query = sess.createQuery(hql);

The dihasilkan SQL pernyataan menunjukkan bahwa diurutkan Foo ditempatkan di fooList:

Hibernate: select bar0_.ID as ID1_0_, bar0_.NAME as NAME2_0_ from BAR bar0_ order by bar0_.ID Hibernate: select foolist0_.BAR_ID as BAR_ID3_0_0_, foolist0_.ID as ID1_1_0_, foolist0_.ID as ID1_1_1_, foolist0_.NAME as NAME2_1_1_, foolist0_.BAR_ID as BAR_ID3_1_1_, foolist0_.idx as idx4_1_1_ from FOO foolist0_ where foolist0_.BAR_ID=? order by foolist0_.NAME desc

Satu hal yang perlu diingat adalah bahwa tidak mungkin untuk mengurutkan Daftar seperti yang terjadi pada JPA. Dokumentasi Hibernate menyatakan:

“Hibernasi saat ini mengabaikan @OrderBy di @ElementCollection di misalnya Daftar. Urutan elemen seperti yang dikembalikan oleh database, tidak ditentukan. "

Sebagai catatan tambahan, adalah mungkin untuk mengatasi batasan ini dengan menggunakan konfigurasi XML lama untuk Hibernate, dan elemen dengan a elemen.

3. Memilah Dengan Kriteria Hibernasi

API Objek Kriteria menyediakan kelas Pesanan sebagai API utama untuk mengelola pengurutan.

3.1. Mengatur Urutan Penyortiran

Kelas Order memiliki dua metode untuk mengatur urutan pengurutan:

  • asc (String atribut) : Mengurutkan kueri berdasarkan atribut dalam urutan menaik.
  • desc (String atribut) : Mengurutkan kueri menurut atribut dalam urutan menurun.

Mari kita mulai dengan contoh sederhana - mengurutkan berdasarkan satu atribut id :

Criteria criteria = sess.createCriteria(Foo.class, "FOO"); criteria.addOrder(Order.asc("id"));

Perhatikan bahwa argumen ke metode asc peka huruf besar kecil dan harus cocok dengan nama atribut yang akan diurutkan.

API Objek Kriteria Hibernasi secara eksplisit menetapkan arah urutan penyortiran dan ini tercermin dalam pernyataan SQL yang dihasilkan oleh kode:

Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_ from FOO this_ order by this_.ID sac

3.2. Menyortir Berdasarkan Lebih dari Satu Atribut

Mengurutkan berdasarkan beberapa atribut hanya perlu menambahkan objek Order ke instance Criteria , seperti pada contoh di bawah ini:

Criteria criteria = sess.createCriteria(Foo.class, "FOO"); criteria.addOrder(Order.asc("name")); criteria.addOrder(Order.asc("id"));

Kueri yang dihasilkan di SQL adalah:

Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_ from FOO this_ order by this_.NAME asc, this_.ID sac

3.3. Pengaturan Urutan Urutan Nilai Null

By default, when the attribute to sort by has null values, it is up to the RDMS to decide the precedence. Hibernate Criteria Object API makes it simple to change that default and place nulls at the end of an ascending ordered list:

Criteria criteria = sess.createCriteria(Foo.class, "FOO"); criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST));

Here is the underlying SQL query – with the is null then 1 else 0 clause:

Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_, this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when this_.NAME is null then 1 else 0 end, this_.NAME asc

Alternatively, we can also place the nulls at the beginning of a descending ordered list:

Criteria criteria = sess.createCriteria(Foo.class, "FOO"); criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST));

The corresponding SQL query follows – with the is null then 0 else 1 clause:

Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_, this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when this_.NAME is null then 0 else 1 end, this_.NAME desc

Note that, if the attribute to sort by is a primitive type like an int, a PresisitenceException will thrown.

Misalnya, jika nilai f.anIntVariable adalah null, maka eksekusi kueri:

String jql = "Select f from Foo as f order by f.anIntVariable desc NULLS FIRST"; Query sortQuery = entityManager.createQuery(jql);

akan melempar:

javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of com.cc.jpa.example.Foo.anIntVariable

4. Kesimpulan

Artikel ini membahas pengurutan dengan Hibernate - menggunakan API yang tersedia untuk entitas sederhana serta untuk entitas dalam relasi satu-ke-banyak.

Penerapan Tutorial Penyortiran Hibernasi ini dapat ditemukan di proyek github - ini adalah proyek berbasis Eclipse, jadi semestinya mudah untuk mengimpor dan menjalankannya apa adanya.