Terakhir kali kami belajar cara menggunakan kriteria untuk melakukan operasi terkait bersama, tetapi karena kriteria bukanlah metode kueri yang secara resmi direkomendasikan oleh Hibernate, kami tidak banyak menggunakannya. Sekarang mari kita lihat HQL yang direkomendasikan secara resmi dan pelajari betapa kuatnya itu bersama -sama.
Apa perbedaan antara HQL, atau Pernyataan Kueri Hibernate dan SQL? Perbedaan antara satu huruf, haha.
Tentu saja ini bukan masalahnya. Perbedaan antara HQL dan SQL terletak pada berbagai ide. HQL menggunakan arah yang berorientasi pada objek untuk meminta, sedangkan SQL menggunakan kueri untuk tabel basis data dua dimensi. Yang termasuk di sini adalah perbedaan dalam ide. HQL sebenarnya SQL, dan dibuat oleh Hibernate untuk mengonversi dan menghasilkan SQL secara internal.
1) Tanpa basa -basi lagi, mari kita lihat kekuatannya.
dari pengguna
Kode ini sangat akrab, karena kita sering menggunakan dari nama tabel di SQL, tetapi perbedaannya di sini adalah bahwa pengguna bukan nama tabel di sini, tetapi nama kelas entitas, dan hibernate membantu kita memetakan.
Rekan pernyataan SQL, jika kita ingin menemukan atribut tertentu dan membatasi kondisional sesuai dengan atribut tertentu, kita bisa mendapatkan pernyataan serupa:
Pilih usr.name, usr.age dari pengguna di mana usr.age> 20 dan usr.age <60
Dengan cara ini, kami menemukan nama dan usia pengguna yang lebih tua dari 20 dan lebih muda dari 60. Mudah dimengerti.
Dan, atau, seperti, <,>, = dan sebagainya dalam pernyataan SQL semuanya dapat digunakan dalam HQL.
Perlu dicatat bahwa ketika kita menanyakan banyak atribut, hasil yang dikembalikan adalah array objek [], dan ketika hanya satu, objek dikembalikan. Ini membutuhkan metode parsing yang berbeda, jadi Anda perlu memperhatikannya saat bertanya.
2) Tentu saja, kami mengatakan sebelumnya bahwa HQL berorientasi objek, dan jika kami melakukan ini, itu bukan ide yang berorientasi objek. Ayo ubah:
Pilih Pengguna Baru (USR.NAME, USR.AGE) dari USER USR WHERE USR.AGE> 20Dengan cara ini, kami memasukkan hasil kueri ke dalam objek pengguna. Perhatikan bahwa konstruktor pengguna dipanggil di sini. Harus ada konstruktor pengguna yang menerima dua parameter di kelas pengguna, jika tidak kesalahan akan dilaporkan. Pesan kesalahan kira -kira sebagai berikut:
Tidak dapat menemukan konstruktor yang tepat di kelas [org.hibernate.tutorial.domain8.user]
Itu tidak dapat menemukan konstruktor yang cocok. Sangat jelas bahwa cukup tambahkan konstruktor yang menerima parameter yang sesuai.
Perhatikan bahwa ketika kami memeriksa ID yang sesuai, kami tidak mengetahuinya. Jika kita memanggil metode SaveorUpdate saat ini, itu benar -benar melakukan operasi yang disimpan.
Mari kita lihat kode uji:
Setelah menjalankan pernyataan kueri di atas, saya melakukan operasi berikut:
while (iter.hasnext ()) {user user = (user) iter.next (); user.setname ("Sun2"); session.saveorupdate (pengguna); } Saat ini, pernyataan hibernasi adalah:
Hibernate: masukkan ke nilai pengguna (user_name, usia) (?,?)
Ini memasukkan yang baru, bukan pembaruan.
Kemudian jika kita perlu memperbarui, kita perlu mencari tahu ID bersama -sama:
Pilih Pengguna Baru (USR.NAME, USR.AGE, USR.ID) dari USER USR WHERE USR.AGE> (Pilih AVG (USR.AGE) dari USR)
Ingatlah untuk memodifikasi konstruktor pengguna.
Saat ini, kami menjalankan kode pengujian kami lagi dan Anda akan mendapatkan:
Hibernate: Perbarui pengguna set user_name =?, Usia =? dimana user_id =?
Pilih USR.NAME DARI PENGGUNA USR WHERE USR.AGE> (Pilih AVG (USR.AGE) dari USR)
HQL ini mendeteksi nama pengguna yang lebih tua dari usia rata -rata.
4) Dalam Hibernate 3, kita dapat dengan mudah memperbarui dan menghapus objek, tanpa harus memuat terlebih dahulu dan kemudian menghapus dalam 2. Kita dapat melakukannya secara langsung dalam satu pernyataan:
Perbarui Nama Set Pengguna = '123123' Where Name = 'Sun33'
Pernyataan Hapus serupa:
Hapus pengguna di mana nama = '123123'
5) Juga mudah untuk dikelompokkan dan diurutkan dalam Hibernate. Cukup gunakan grup dan pesan oleh, dan saya tidak akan membicarakannya lebih banyak saat ini.
6) Kami melihat bahwa hal di atas ditulis langsung untuk permintaan atau pembaruan. Jika kita membutuhkan penugasan dinamis, atau ada terlalu banyak tugas, kita tidak dapat menyambungkan string seperti JDBC. Diperkirakan ada lebih dari 5, dan semua orang di tim proyek ingin memarahi saya, haha.
Lebih baik menggunakan metode modern, menggunakan placeholder sebagai gantinya dan kemudian menetapkan nilai -nilai tertentu.
Kode Langsung Kami:
Kueri kueri = session.createqueery ("Pilih pengguna baru (usr.name, usr.age, usr.id) dari pengguna usr di mana usr.name =?"); query.setstring (0, "shun"); Kami melihat bahwa metode ini mirip dengan persiapan yang kami gunakan secara langsung. Itu diatur melalui set ***, tetapi perbedaannya adalah bahwa posisi di sini dimulai dari 0, sedangkan persiapan disiapkan dimulai dari 1, jadi beri perhatian khusus di sini.
Ada juga metode sesi. Temukan di Hibernate2, tetapi karena saya menggunakan 3 sekarang, saya tidak akan banyak bicara tentang hal itu.
Placeholder yang kami gunakan di atas disebut Placeholder Pesanan, dan ada satu lagi yang disebut Placeholder Referensi. Mari kita lihat:
Kueri kueri = session.createqueery ("Pilih pengguna baru (usr.name, usr.age, usr.id) dari pengguna usr di mana usr.name =: name"); query.setParameter ("name", "shun"); Saya melihat ada hal seperti: nama dalam pernyataan HQL kami. Ini adalah placeholder referensi. Kita hanya perlu mengatur nilai melalui setParameter nanti. Perhatikan bahwa parameter pertama di sini harus sesuai dengan nilai placeholder dalam pernyataan HQL.
Tentu saja, beberapa orang mungkin mengatakan bahwa ini tidak berorientasi pada objek, jadi mari kita berorientasi pada objek lagi:
Pertama, buat kelas untuk merangkum nilai yang kami minta
Public Class UserQuery {Private String Name; usia int pribadi; // hilangkan metode get/atur} kueri kueri = session.createQuery ("Pilih pengguna baru (usr.name, usr.age, usr.id) dari pengguna usr di mana usr.name =: name"); UserQuery uq = UserQuery baru (); uq.setname ("shun"); query.setProperties (UQ); Kami merangkum nilai yang kami butuhkan untuk meminta langsung melalui kelas ini. Sangat berorientasi objek.
Beberapa tim proyek memiliki beberapa peraturan aneh bahwa pernyataan SQL tidak diizinkan muncul dalam kode. Jika ini adalah spesifikasi, maka semua kode perusahaan kami yang saya lihat tidak memenuhi syarat. Banyak splicing string di dalam cangkir membuatnya terlihat tertekan. Sangat sulit untuk disakiti untuk mempertahankan proyek yang ada.
Pernyataan SQL tidak diizinkan dalam kode. Ini adalah saran yang bagus, tetapi tergantung pada kesempatan itu. Mari kita lihat bagaimana Hibernate mengkonfigurasi HQL dalam pemetaan file.
Lihat langsung pada file konfigurasi:
<query name = "querybyname"> <! [cdata [dari user usr where usr.name =: name]]> </query>
Kami menambahkan tag seperti ini, yang menunjukkan bahwa itu adalah pernyataan HQL.
Ketika kita perlu mendapatkan pernyataan ini, kita hanya perlu menambahkan kalimat ke kode:
Kueri kueri = session.getNamedQuery ("querybyname"); Dengan cara ini, pernyataan HQL diperoleh.
HQL juga dapat ditanyai menggunakan kombinasi di SQL, seperti bagian dalam, bergabung dengan luar kiri, gabungan luar kanan, gabungan penuh.
Mari kita lihat penggunaannya:
Mari kita lihat kelas entitas terlebih dahulu, apa yang perlu kita gunakan dalam tes kita:
Tuser kelas publik mengimplementasikan serial {private static final long serialversionuid = 1l; Private Int ID; usia int pribadi; nama string pribadi; set pribadi <spulht> alamat = hashset baru <damate> (); // hilangkan metode get/atur} alamat kelas publik mengimplementasikan serializable {private static final long serialversionuid = 1l; Private Int ID; alamat string pribadi; Pengguna Tuser Pribadi; // hilangkan metode get/atur} Mari kita lihat file pemetaan:
<package pemetaan hibernate = "org.hibernate.tutorial.domain6"> <class name = "tuser" table = "t_user" dinamis-insert = "true" dynamic-update = "true"> <id name = "id" column = "id"> <Generator/> </id </id name = "name" name = "ID" = "> <Generator/> </id </id name =" name "name =" ID "=" ID "> <Generator/> </id name </id name =" name "loav =" ID " type = "java.lang.integer" kolom = "usia"/> <set name = "alamat" cascade = "all" table = "t_address" Inverse = "true"> <Key Column = "user_id"/> <-satu-ke-banyak/> </set> </class> </hibernate-papping> <satu-ke-banyak-tap Mapperping. name = "Alamat" Table = "t_address" Dynamic-insert = "false" dinamis-update = "false" dinamis-update = "false" dinamis-update = "id" type = "java.lang.integer"> <generator /> </d> <nama properti = "alamat" kolom = "alamat" type = "java." "" "" "" "" "" "" "name" name = "" "" "" name = "" name "name =" "" not-null = "true"> </banyak-ke-satu> </slass> </hibernate-Mapping>
Anda hanya perlu memodifikasi nama paket yang sesuai.
Mari kita melakukan tes formal:
Sebelum pengujian, mari kita lihat data dalam tabel:
Data tabel T_Address adalah sebagai berikut:
Data tabel T_USER adalah sebagai berikut:
1) Pertama, mari kita lihat gabungan batin, yang diambil di HQL oleh batin gabungan fetch. Perhatikan bahwa arti pengambilan di sini adalah untuk mengambil data yang diperlukan. Jika pengambilan tidak digunakan, data yang kami ambil adalah tipe data objek [].
Mari kita lihat dulu
Dari Tuser USR Batin Bergabunglah dengan USR.Addresses
Ketika kita menjalankannya, kita melihat bahwa output hibernasi adalah:
Hibernate: Pilih tuser0_.id sebagai id1_0_, alamat1_.id sebagai id0_1_, tuser0_.name as name1_0_, tuser0_.age As Age1_0_, alamat1_.address sebagai alamat0_1_, alamat1_.user_id as uses1_.address sebagai address0_1_, addresses1_.user_id as uses1_.address sebagai alamat0_1_, addresses1_.user_id as uses1_.address sebagai alamat0_1_, alamat1_.user_id as User3_0_1_1_11_ T_Address alamat1_ di tuser0_.id = addresses1_.user_id
Kita dapat melihat hasilnya saat berjalan di MySQL:
Kita dapat melihat bahwa Hibernate mengubahnya menjadi pernyataan bergabung dalam dan mencari tahu alamatnya.
Kami melihat bahwa tidak ada catatan shun4 dalam hasilnya, karena tidak memiliki alamat dan catatan yang sesuai.
Ketika kami menggunakan batin gabungan alih -alih ambil, pernyataan yang dicetaknya adalah:
Hibernate: Pilih tuser0_.id sebagai id1_0_, alamat1_.id sebagai id0_1_, tuser0_.name as name1_0_, tuser0_.age as Age1_0_, alamat1_.address sebagai alamat0_1_, addresses1_.user_id as Useres1_. tuser0_.id = addresses1_.user_id
Tampaknya pernyataan itu tidak berbeda, tetapi ketika kita mengetahuinya, itu mendapatkan tipe array objek [], jadi Anda perlu memperhatikan analisis ini.
Ketika kita tidak menggunakan fetch tetapi hanya gabungan batin, kita perlu menguraikannya seperti ini:
Kueri kueri = session.createqueery ("Dari Tuser USR Inner bergabung dengan usr.addresses"); Daftar daftar = query.list (); Iterator iter = list.iterator (); while (iter.hasnext ()) {objek [] hasil = (objek []) iter.next (); untuk (int i = 0; i <results.length; i ++) {System.out.println (hasil [i]); }} Kami melihat hasil cetak:
org.hibernate.tutorial.domain6.tuser@16925b0 org.hibernate.tutorial.domain6.address@914f6a org.hibernate.tutorial.domain6.tuser org.hibernate.tutorial.domain6.tuser@1326484 org.hibernate.tutorial.domain6.address@16546ef
Masing -masing hasilnya adalah objek yang sesuai.
2) Bergabung luar kiri, ini setara dengan koneksi kiri SQL. Mari kita lihat contoh secara langsung:
Dari Tuser USR Left Outer Gabung Fetch USR.Addresses
Ketika kita menjalankan pernyataan di atas, Hibernate mencetak:
Hibernate: Pilih tuser0_.id sebagai id1_0_, alamat1_.id sebagai id0_1_, tuser0_.name as name1_0_, tuser0_.age As Age1_0_, alamat1_.address sebagai alamat0_1_, alamat1_.user_id as use3_0_1_1_111111111111 Bergabunglah dengan Alamat T_Address1_ di tuser0_.id = addresses1_.user_id
Kami memeriksanya di MySQL dan melihat:
Kami melihat bahwa meskipun Shun4 tidak memiliki alamat yang sesuai, masih ditemukan. Bahan luar kiri mengacu pada mencari tahu semua catatan di meja kiri.
Saya tidak akan membicarakan situasi tanpa mengambil di sini.
3) Selanjutnya, mari kita lihat gabungan luar yang tepat. Dilihat dari nama, itu harus terkait dengan gabungan luar kiri. Kami dapat dengan jelas melihatnya dengan melihat contoh secara langsung.
Dari Tuser USR Right Outer Gabung Fetch USR.Addresses
Kami menjalankannya dan mendapatkan output pernyataan hasil dari hibernate adalah:
Hibernate: Pilih tuser0_.id sebagai ID1_0_, alamat1_.id sebagai id0_1_, tuser0_.name as name1_0_, tuser0_.age as Age1_0_, alamat1_.address sebagai alamat0_1_, addresses1_.user_id as uses1_.address sebagai address0_1_, alamat1_.user_id as uses1_.address sebagai alamat0_1_, alamat1_.user_id as use3_0_1_1_11_ Bergabunglah dengan Alamat T_Address1_ di tuser0_.id = addresses1_.user_idKita dapat melihat hasilnya setelah dieksekusi di MySQL:
Di sini kita dapat melihat bahwa alamatnya adalah test4 dan tidak memiliki pengguna yang sesuai yang sesuai dengannya, tetapi masih ditemukan. Bantalan luar kanan mengacu untuk mencari tahu semua catatan di tabel kanan.
Situasi fetch adalah seperti di atas. Jika Anda tidak mengerti, Anda dapat melihat bagian dalam gabungan.