Pencegat
Berbicara tentang Interceptor, saya percaya bahwa sepatu anak -anak yang akrab dengan Struts2 jelas akrab dengan Struts2. Struts2 dapat menyesuaikan pencegat untuk melakukan serangkaian pekerjaan terkait yang Anda inginkan. Dan pencegat yang kita bicarakan di sini juga memiliki fungsi yang serupa.
Tanpa mengatakan omong kosong, hanya kode:
Berikut ini adalah kelas myinterceptor, yang mengimplementasikan antarmuka interceptor:
string publik onPrepareStAtement (String arg0) {return arg0; } public boolean onsave (objek arg0, serializable arg1, objek [] arg2, string [] arg3, type [] arg4) melempar callbackexception {if (arg0 instance dari pengguna) {system.outname (); } return false; } Saya tidak akan membaca metode lain, cukup ikuti implementasi default. Kita hanya perlu mengubah kedua metode ini. Kita perlu mengubah nilai pengembalian di OnPareStatement untuk mengembalikan pernyataan SQL saat ini. Parameternya adalah pernyataan SQL yang dieksekusi. Kita dapat mencetak pernyataan dengan langsung mengembalikannya.
Di Onsave, Anda dapat mengatakan bahwa itu dipanggil saat menabung. Kami dapat melakukan serangkaian pekerjaan pra-pelestarian.
Saya percaya semua orang dapat memahaminya dengan melihat nama parameter.
Serializable mengacu pada parameter nomor urutan, yang mengacu pada atribut yang memetakan ke ID database.
Object [] Ini adalah serangkaian negara, yang belum banyak digunakan untuk saat ini. Saya akan mempelajarinya nanti. Namun, API menjelaskan bahwa tidak peduli bagaimana nilai dalam array ini dimodifikasi, metode Onsave harus mengembalikan true.
String [] mengacu pada nama atribut dan ketik [] adalah jenis atribut yang sesuai.
1) Interceptor ini dapat melakukan beberapa operasi yang sesuai sebelum dan sesudah menyimpan database. Misalnya, jika Anda ingin memodifikasi data dan menambahkan awalan atau akhiran, Anda dapat menggunakannya untuk mengimplementasikannya. Mari kita lihat di bawah ini.
Onsave boolean publik (objek arg0, serializable arg1, objek [] arg2, string [] arg3, type [] arg4) melempar callbackexception {if (arg0 instance dari pengguna) {System.out.println ("pengguna yang akan disimpan =>"+((pengguna) arg0) .getName ()); } // Kami menambahkan 123 sebagai awalan nama di sini pengguna pengguna = (pengguna) arg0; user.setname ("123"+user.getName ()); mengembalikan false; }Mari kita lihat metode pengujian:
public static void main (string [] args) {configuration cfg = new configuration (). configure (); SessionFactory sessionFactory = cfg.buildsessionFactory (); Interceptor Interceptor = myinteceptor baru (); Sesi sesi = sessionfactory.opensession (interceptor); Pengguna pengguna = pengguna baru (); user.setname ("shun"); Transaksi tx = session.begintransaction (); session.save (pengguna); tx.commit (); session.close (); } Ini sangat sederhana, kami hanya menyimpannya dengan sederhana. Tidak ada file pemetaan dan kelas entitas di sini, coba saja.
Jalankan dan kita bisa melihat:
Pengguna yang akan disimpan => Shun Hibernate: Masukkan ke dalam nilai pengguna (user_name, usia) (?,?) Hibernate: Perbarui pengguna set pengguna_name =?, Usia =? dimana user_id =?Ini akan memperbarui nama dan usia di akhir, terutama karena kami telah membuat perubahan dalam metode Onsave.
Onload boolean publik (objek arg0, serializable arg1, objek [] arg2, string [] arg3, type [] arg4) melempar callbackexception {if (arg0 instance dari pengguna) {System.out.println ("pengguna yang akan dimuat =>"+(arg2 [0]+":"+arg2 [1])); } Pengguna pengguna = (pengguna) arg0; // menilai atribut mana nama untuk (int i = 0; i <arg3.length; i ++) {if (arg3 [i] .equals ("name")) {user.setname ((string) arg2 [i]). Ganti ("123", "")); arg2 [i] = ((string) arg2 [i]). ganti ("123", ""); }} return false; } Nilai atribut yang dimodifikasi saat memuat ditulis dalam metode Onload.
Arg0 di sini adalah objek pengguna kami. Itu belum memiliki nilai. Metode ini dipanggil setelah metode pemuatan, sehingga tidak berguna bagi kami untuk mengoperasikan pengguna saat ini, dan pengguna.setname di sini adalah operasi yang tidak berguna. Terutama di:
arg2 [i] = ((string) arg2 [i]). ganti ("123", "");
Kode ini mengubah nilai atribut yang dikembalikan, sehingga nilai dalam objek pengguna yang kami dapatkan dalam program juga akan berubah. Mari kita jalankan metode tes untuk melihat:
public static void main (string [] args) {configuration cfg = new configuration (). configure (); SessionFactory sessionFactory = cfg.buildsessionFactory (); Interceptor Interceptor = myinteceptor baru (); Sesi sesi = sessionfactory.opensession (interceptor); Pengguna pengguna = (user) session.load (user.class, new long (39)); System.out.println ("Nama Pengguna:"+user.getName ()); session.close (); }Melihat hasilnya, kami mendapat:
Hibernate: Pilih user0_.user_id sebagai user1_0_0_, user0_.user_name sebagai user2_0_0_, user0_.age as age0_0_ dari pengguna pengguna0_ di mana user0_.user_id =? Pengguna yang akan dimuat => 123Shun: 0 Nama Pengguna: Shun
Kami telah menghapus 123 asli dan melakukan pemrosesan yang relevan setelah pemuatan yang sebenarnya, tetapi ini bukan pemrosesan nyata sebelum pemuatan yang sebenarnya, dan agak mencurigakan spekulasi. Tetapi juga merupakan pertimbangan. Interceptor dapat digunakan paling banyak dalam pemrosesan log yang relevan. Misalnya, kita perlu mencatat secara bersamaan untuk setiap operasi, jadi Interceptor adalah pilihan yang baik.
Koleksi
Ingat set yang kami gunakan dalam satu-ke-banyak dalam contoh sebelumnya, apakah Anda masih memiliki kesan? Jika tidak, periksa informasi dan tinjau. Hari ini kita akan belajar di sekitar koleksi ini.
Mari kita sampai intinya.
1) Pertama mari kita pelajari set. Semua orang tahu bahwa ada juga set dalam paket Java Util. Jadi apa perbedaan dan koneksi antara set dan diatur dalam Hibernate? Kami membuka API Hibernate, menemukan set, dan Anda bisa melihatnya.
Apa yang kita lihat adalah kelas induk dari koleksi hibernate semacam itu. Ini adalah kelas abstrak dengan serangkaian kelas implementasi konkret. Ketika kami terus melihat metode berikut, kami menemukan bahwa kelas ini mengimplementasikan enkapsulasi koleksi Java, jadi kami memahami bahwa set hibernate yang disebut sebenarnya hanya merangkum set Java.
Jadi, apakah karakteristik ini yang tidak memungkinkan elemen duplikat pada set juga dalam hibernate? Jawabannya tentu saja ya.
Kami tidak melihatnya di sini. Di masa lalu, ketika kami belajar pemetaan, kami secara langsung menghubungkan properti dengan kelas terkait, tetapi hari ini kami tidak seperti ini. Kami menggunakan metode lain, cukup asosiasikan string untuk melihat apakah ada masalah.
Tetapi sebelum melihat pertanyaan ini, mari kita lihat perbandingan string di Java.
Apa yang kita lihat adalah kelas induk dari koleksi hibernate seperti itu. Ini adalah kelas abstrak dengan serangkaian kelas implementasi konkret. Ketika kami terus melihat metode berikut, kami menemukan bahwa kelas ini mengimplementasikan enkapsulasi koleksi Java, jadi kami memahami bahwa set hibernate yang disebut sebenarnya hanya merangkum set Java.
Jadi, apakah karakteristik ini yang tidak memungkinkan elemen duplikat pada set juga dalam hibernate? Jawabannya tentu saja ya.
Kami tidak melihatnya di sini. Di masa lalu, ketika kami belajar pemetaan, kami secara langsung menghubungkan properti dengan kelas terkait, tetapi hari ini kami tidak seperti ini. Kami menggunakan metode lain, cukup asosiasikan string untuk melihat apakah ada masalah.
Tetapi sebelum melihat pertanyaan ini, mari kita lihat perbandingan string di Java.
public static void main (string [] args) {string s1 = "shun1"; String s2 = "shun1"; System.out.println ("S1 == S2:"+(S1 == S2)); } Saya percaya banyak sepatu anak -anak tahu bahwa jawabannya benar.
Sebelum membuat contoh, mari kita lihat file pemetaan kami. Kami tidak akan menulis kelas pemetaan:
Ini adalah file pemetaan untuk Tuser:
<class name = "tuser" table = "t_user" dinamis-insert = "true" dynamic-upDate = "true" dynamic-upDate = "true"> <id name = "id" kolom = "id"> <generator/> </d> <nama properti = "name" usia = "java.Lang.string" name = "name"/name = "type =" java.Lang.string "colum ="/a name = "name" lead = "java" java "java" java "java" colum = "a name =" name = "name =" java "java" java. kolom = "usia"/> <set name = "alamat" cascade = "all" table = "t_address"> <key column = "user_id"/> <!-<satu-ke-banyak/>-> <elemen kolom = "alamat" type = "string"/> </atur> </slass>
Berikutnya adalah file pemetaan alamat:
<class name = "alamat" tabel = "t_address" dynamic-insert = "false" dinamis-update = "false"> <id name = "id" column = "id" type = "java.lang.integer"> <generator /> < /id nama properti = "alamat" <"alamat" type "type =" java.string "=" "ALAMAT" <"ALAMAT =" ALAMAT "TYPE =" JAVA.RANG. " not-null = "true"> </banyak-ke-satu> </slace>
Sepatu anak -anak telah melihatnya dengan jelas. Saya berkomentar satu-ke-banyak di set di Tuser dan menggunakan elemen. Tidak peduli apa masalahnya, mari kita lihat database terlebih dahulu:
Ini adalah tabel T_Address:
Ini tabel T_USER:
Kita dapat melihat bahwa pengguna dengan ID 4 sesuai dengan tiga alamat. Selanjutnya, mari kita lihat metode pengujian:
public static void main (string [] args) {configuration cfg = new configuration (). configure (); SessionFactory sessionFactory = cfg.buildsessionFactory (); Sesi sesi = sessionfactory.opensession (); Tuser user = (tuser) session.load (tuser.class, integer baru (4)); Set set = user.getAddresses (); session.close (); System.out.println ("Ukuran Alamat:"+set.size ()); } Kelas kueri yang sangat sederhana, baru saja mengeluarkan hasil ini, kami melihat fenomena aneh:
Ukuran alamat: 1
Inilah hasilnya!
Anda pasti akan mengatakan, itu pasti salah, itu adalah bug di Hibernate. Saya pasti bahagia di sini. Saya akhirnya bisa mengirimkan bug. Ketika saya beralih pekerjaan, saya bisa mengatakan dengan keras bahwa saya mengirimkan bug untuk Hibernate. Haha, tapi sayangnya, ini bukan bug.
Saya baru saja mengatakan bahwa perbandingan string yang kami miliki di depan adalah membuka jalan di sini, jadi bagaimana cara membuka?
Kami menggunakan set dalam file konfigurasi dan mengaitkannya melalui karakter string. Kemudian, ketika dikeluarkan dalam database dan memasukkannya ke dalam set, pertama -tama akan menentukan apakah nilai -nilai karakter yang terkait sama. Di sini, karena nilai -nilai kita sama (kita tidak akan menggali bagaimana perbandingannya untuk saat ini), kita hanya perlu tahu bahwa ketika kita menggunakan string untuk membandingkan, kita jatuh ke dalam perangkap string di java lagi. Jika Anda mengetahui bahwa hanya ada satu, maka penghapusan lebih merepotkan saat menghapusnya, itu akan menghapus semua catatan yang sama.
Lalu mari kita lihat yang dihapus:
Tuser user = (tuser) session.load (tuser.class, integer baru (4)); Transaksi tx = session.begintransaction (); Objek obj = user.getAddresses (). Iterator (). Next (); user.getAddresses (). hapus (obj); tx.commit (); session.close ();
Output pernyataan oleh Hibernate di sini adalah:
Hibernate: hapus dari t_address di mana user_id =?
Saya percaya semua orang tahu kapan harus menghapus semua alamat di bawah pengguna. Tidak ada pilihan selain menghapus semua ini.
Jadi, Anda perlu memperhatikannya dalam pengembangan nyata.
2) Kami berbicara tentang set di atas, tampaknya tidak menyenangkan untuk digunakan. Ada jebakan seperti itu, tetapi tidak ada cara. Set adalah yang paling kami gunakan, dan umumnya tidak ada yang akan secara langsung mengaitkan string. Tetapi banyak orang masih tidak bahagia, jadi Hibernate akan memiliki tas tambahan sesuai kebutuhan (mungkin tidak seperti yang diperlukan, mungkin beberapa orang di dalamnya tidak puas, haha).
Pertama -tama mari kita lihat penggunaan dasarnya:
Pertama, kita perlu memodifikasi tag set di file pemetaan tuser sebelumnya ke:
<name tas = "alamat" malas = "true" table = "t_address"> <Key column = "user_id" /> <element type = "string" column = "address" /> </bag>
Dan kelas entitas yang sesuai perlu memodifikasi jenis alamat ke jenis daftar.
Di sini kami menambahkan tiga alamat:
Kami menjalankan kode uji:
public static void main (string [] args) {configuration cfg = new configuration (). configure (); SessionFactory sessionFactory = cfg.buildsessionFactory (); Sesi sesi = sessionfactory.opensession (); Tuser user = (tuser) session.load (tuser.class, integer baru (4)); System.out.println ("Ukuran Alamat:"+user.getAddresses (). Size ()); session.close (); }
Di sini kita lihat:
Ukuran alamat: 3
Kali ini kita bisa melihat semuanya, terlepas dari apakah ada pengulangan atau tidak.
Tapi kami hanya melihat masalah penghapusan. Tas belum diselesaikan di sini, dan kita perlu menggunakan Idbag. Kami melihat file konfigurasi dan memerlukan modifikasi berikut:
IDBAG NAME = "ALAMAT" TABLE = "t_Address" Lazy = "true"> <collection-id type = "int" column = "id"> <generator /> < /collection-id> <Key column = "user_id" /> <element type = "string" column = "address" /> < /idbag>
Kami melihat bahwa ia hanya memiliki satu koleksi-ID dari tas untuk menunjukkan nomor catatan yang akan dihapus.
Saat kami menjalankan kembali kode yang dihapus:
Tuser user = (tuser) session.load (tuser.class, integer baru (4)); Transaksi tx = session.begintransaction (); Objek obj = user.getAddresses (). Iterator (). Next (); user.getAddresses (). hapus (obj); tx.commit ();
Kami melihat bahwa pernyataan output adalah:
Hibernate: hapus dari t_address di mana id =?
Kali ini, tidak dihapus melalui user_id, tetapi berdasarkan ID T_Address, yang berarti benar -benar menghapus catatan yang perlu kita hapus.
Kami melihat database dan catatannya sekarang:
Kami telah menghapus catatan pertama, itu benar.
3) Setelah melihat dua metode di atas, mari kita lihat peta. Perbedaan terbesar antara itu dan dua di atas adalah bahwa ia dapat sesuai dengan nilai -nilai kunci. Lihat langsung pada kode, sudut pandang intuitif:
Pertama, kita perlu memodifikasi file konfigurasi:
<peta name = "alamat" tabel = "t_address" lazy = "true"> <key column = "user_id" /> <index type = "string" column = "type" /> <element type = "string" column = "address" /> < /peta>
Perbedaan terbesar antara itu dan dua sebelumnya adalah bahwa ada indeks, yang setara dengan kunci peta di java, dan kami menggunakan ini untuk mengambil catatan yang sesuai. Ingat, setelah berubah di sini, Anda perlu mengubah kelas entitas yang sesuai, dan Anda perlu mengubah jenis atribut alamat ke peta.
Lihatlah data database:
Di sini kita melihat bahwa ada dua kantor dan satu rumah, jadi kantor mana yang harus digunakan?
Jangan khawatir, kita akan tahu setelah menjalankan kode tes:
Tuser user = (tuser) session.load (tuser.class, integer baru (4)); System.out.println (user.getAddresses (). Get ("home")); System.out.println (user.getAddresses (). Get ("Office"));Shanwei Shanghai
Ya, seperti yang ditunjukkan hasilnya, kami mendapatkan yang di belakang, yang sama dengan prinsip peta. Nilai yang disimpan akan menimpa nilai -nilai sebelumnya (jika mereka adalah kunci yang sama).
Peta relatif sederhana, yang sebanding dengan dua yang pertama.
4) Mari kita lihat yang terakhir. Daftar berbeda dari yang sebelumnya, dan dapat disortir.
Mari kita lihat bagaimana itu diimplementasikan:
Pertama, mari kita ubah file pemetaan:
<daftar nama = "alamat" Tabel = "t_address" lazy = "true"> <Key column = "user_id" /> <index type = "string" kolom = "idx" /> <element type = "string" kolom = "alamat" /> < /daftar>
Ini mirip dengan konfigurasi peta, tetapi atribut indeks berbeda. Indeks dalam peta digunakan sebagai kunci untuk mendapatkan nilai, sedangkan indeks daftar digunakan sebagai penyortiran.
Mari kita lihat database:
Kami menetapkan tiga nilai dalam urutan 0, 1, dan 2.
Mari kita jalankan kode untuk mengubah nilai 0 dan 2:
Tuser user = (tuser) session.load (tuser.class, integer baru (4)); Transaksi tx = session.begintransaction (); Objek obj1 = user.getAddresses (). Get (0); Objek obj2 = user.getAddresses (). Get (2); user.getAddresses (). Set (0, obj2); user.getAddresses (). Set (2, obj1); tx.commit ();
Kami melihat hasilnya:
Kita melihat bahwa 0 dan 2 telah diganti, dan tentu saja ini hanya mengubah nilai IDX. Tetapi ini pada dasarnya telah menerapkan fungsi penyortiran.