Menyusun dengan Hibernate

1. Gambaran keseluruhan

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

2. Menyusun Dengan HQL

Menyusun dengan HQL Hibernate semudah menambahkan klausa Order By ke rentetan pertanyaan HQL:

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

Setelah kod ini dilaksanakan, Hibernate akan menghasilkan pertanyaan SQL berikut:

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

Arah urutan urutan lalai menaik. Inilah sebabnya mengapa keadaan pesanan, asc , tidak termasuk dalam pertanyaan SQL yang dihasilkan.

2.1. Menggunakan Urutan Penyusunan yang Eksplisit

Untuk menentukan urutan penyusun secara manual - anda perlu memasukkan arahan pesanan dalam rentetan pertanyaan HQL :

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

Dalam contoh ini, menetapkan klausa asc dalam HQL termasuk dalam pertanyaan 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. Menyusun mengikut Lebih daripada Satu Atribut

Pelbagai atribut, bersama dengan urutan pengurutan pilihan, dapat ditambahkan ke klausa Order By dalam rentetan pertanyaan HQL:

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

Pertanyaan SQL yang dihasilkan akan berubah dengan sewajarnya:

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. Menetapkan Mengutamakan Keutamaan Nilai Nol

Secara lalai, apabila atribut yang akan disusun mempunyai nilai nol , terserah kepada RDMS untuk menentukan keutamaan. Rawatan lalai ini boleh diatasi dengan meletakkan satu nulls PERTAMA atau nulls LAST klausa dalam rentetan HQL pertanyaan .

Contoh mudah ini meletakkan sebarang nol di akhir senarai hasil:

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

Mari kita lihat klausa nol maka 1 lagi 0 dalam pertanyaan 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. Menyusun Satu Hubungan Banyak

Mari menganalisis kes penyortiran yang kompleks: menyusun entiti dalam hubungan satu ke banyak - Bar yang mengandungi koleksi entiti Foo .

Kami akan melakukannya dengan memberi penjelasan pada koleksi dengan anotasi Hibernate @OrderBy ; kami akan menentukan bidang di mana pesanan dibuat, dan juga arahnya:

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

Perhatikan hujah klausa kepada penjelasan. Ini unik untuk Hibernate @OrderBy , berbanding dengan penjelasan @OrderBy JPA yang serupa . Ciri lain yang membezakan pendekatan ini dari setara JPA adalah bahawa argumen klausa menunjukkan bahawa penyortiran dilakukan berdasarkan lajur NAMA pada jadual FOO , bukan pada atribut nama Foo .

Sekarang mari kita lihat penyusun bar dan Foos yang sebenarnya :

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

Yang mengakibatkan SQL kenyataan menunjukkan bahawa disusun Foo diletakkan di dalam 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 perkara yang perlu diingat ialah tidak boleh menyusun Daftar seperti yang berlaku pada JPA. Dokumentasi hibernate menyatakan:

“Hibernate pada masa ini mengabaikan @OrderBy di @ElementCollection on misalnya List. Urutan elemen seperti yang dikembalikan oleh pangkalan data, tidak ditentukan. "

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

3. Menyusun Dengan Kriteria Hibernate

Kriteria Objek API menyediakan kelas Pesanan sebagai API utama untuk menguruskan penyortiran.

3.1. Menetapkan Urutan Menyusun

The Order kelas mempunyai dua kaedah untuk menetapkan perintah menyusun:

  • asc (String atribut) : Menyusun pertanyaan mengikut atribut mengikut tertib menaik.
  • desc (Atribut tali) : Menyusun pertanyaan mengikut atribut dalam urutan menurun.

Mari kita mulakan dengan contoh mudah - menyusun mengikut satu atribut id :

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

Perhatikan bahawa argumen untuk kaedah asc peka huruf besar kecil dan harus sesuai dengan nama atribut untuk diurutkan.

API Objek Kriteria Hibernate secara eksplisit menetapkan arah urutan penyusun dan ini tercermin dalam pernyataan SQL yang dihasilkan oleh kod:

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

3.2. Menyusun mengikut Lebih daripada Satu Atribut

Menyusun berdasarkan beberapa atribut hanya memerlukan penambahan objek Pesanan ke instance Kriteria , seperti dalam contoh di bawah:

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

Pertanyaan yang dihasilkan dalam 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. Menetapkan Mengutamakan Keutamaan Nilai Nol

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.

Sebagai contoh, jika nilai f.anIntVariable adalah nol, maka pelaksanaan pertanyaan:

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

akan membuang:

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 meneroka penyortiran dengan Hibernate - menggunakan API yang tersedia untuk entiti sederhana dan juga entiti dalam hubungan satu-ke-banyak.

Pelaksanaan Tutorial Penyortiran Hibernate ini boleh didapati di projek github - ini adalah projek berasaskan Eclipse, jadi semestinya mudah diimport dan dijalankan sebagaimana adanya.