Baru -baru ini saya melihat jenis kustom hibernate. Saya belum pernah terpapar sebelumnya. Saya akan merekamnya di sini sebagai konsolidasi pengetahuan saya dan membiarkan teman -teman yang belum pernah terpapar untuk belajar dan mempelajarinya bersama.
1) Jenis kustom, seperti namanya, tentu saja jenis yang diimplementasikan sendiri karena tipe internal tidak memenuhi kebutuhan. Tidak banyak situasi seperti itu, tetapi kita masih perlu mempelajarinya. Jika kami memiliki lebih banyak keterampilan, kami tidak akan menekan tubuh kami. Pelajari juga bagaimana orang lain mempertimbangkan cara berpikir tentang ekstensibilitas saat membuat kerangka kerja.
Ada dua cara untuk mengimplementasikan tipe kustom, satu adalah untuk mengimplementasikan UserType, yang lain adalah mengimplementasikan CompositeSerType, dan mungkin ada beberapa metode, tetapi saya belum menggunakannya untuk saat ini, jadi saya tidak akan membicarakannya untuk saat ini.
Saya hanya menggunakan userType untuk saat ini, mari kita lihat definisi antarmuka usertype:
Public Interface UserType { /*** Mengembalikan kode tipe SQL untuk kolom yang dipetakan berdasarkan jenis ini. Kode * didefinisikan pada <tt> java.sql.types </tt>. */ int int [] sqlTypes (); /*** Kelas yang dikembalikan oleh <tt> nullsafeget () </tt>. */ kelas public returnedclass (); /*** Bandingkan dua contoh kelas yang dipetakan oleh jenis ini untuk "kesetaraan" persistensi. * Kesetaraan keadaan persisten. */ boolean publik sama (objek x, objek y) melempar hibernateException; / ** * Dapatkan kode hash untuk instance, konsisten dengan persistensi "kesetaraan" */ public int hashCode (objek X) melempar hibernateException; /*** Ambil contoh kelas yang dipetakan dari hasil JDBC. Implementor * harus menangani kemungkinan nilai nol. */ objek publik nullsafeget (hasil rs, string [] nama, pemilik objek) melempar hibernateException, sqlexception; /*** Tulis contoh kelas yang dipetakan ke pernyataan yang disiapkan. Implementor * harus menangani kemungkinan nilai nol. Jenis multi-kolom harus ditulis * ke parameter mulai dari <tt> index </tt>. */ public void nullsafeSet (disiapkan ST, nilai objek, indeks int) melempar hibernateException, sqlexception; /** * Kembalikan salinan yang mendalam dari keadaan persisten, berhenti di entitas dan di * koleksi. Tidak perlu menyalin objek yang tidak dapat diubah, atau nilai nol *, dalam hal ini aman untuk hanya mengembalikan argumen. */ Objek Publik DeepCopy (Nilai Objek) Melempar HibernateException; /*** Apakah objek jenis ini dapat berubah? * * @return boolean */ public boolean ismutable (); /*** Ubah objek menjadi representasi yang dapat di -cache. Paling tidak metode * ini harus melakukan salinan yang dalam jika jenisnya dapat berubah. Namun, itu mungkin tidak cukup * untuk beberapa implementasi; Misalnya, asosiasi harus di -cache sebagai * nilai pengidentifikasi. (operasi opsional) * * @param nilai objek yang akan di -cache * @return representasi yang dapat di -cache dari objek * @Throws HibernateException */ Disassemble Serializable Public (Nilai Objek) Melemparkan HibernateException; /*** merekonstruksi objek dari representasi yang dapat di -cache. Paling tidak metode * ini harus melakukan salinan yang dalam jika jenisnya dapat berubah. (Operasi Opsional) */ Public Object Assemble (di -serializable di -cache, pemilik objek) melempar HibernateException; /** * Selama penggabungan, ganti nilai (target) yang ada di entitas yang kita gabungkan ke * dengan nilai baru (asli) dari entitas terpisah yang kita gabungkan. Untuk objek yang tidak dapat diubah *, atau nilai nol, aman untuk hanya mengembalikan parameter pertama. Untuk * objek yang dapat berubah, aman untuk mengembalikan salinan parameter pertama. Untuk objek * dengan nilai komponen, mungkin masuk akal untuk secara rekursif mengganti nilai komponen. */ Ganti Objek Publik (Objek Asli, Target Objek, Pemilik Objek) Melempar HibernateException; } Bahkan, Anda dapat memahaminya dalam bahasa Inggris secara umum, jadi saya tidak akan menjelaskannya lebih banyak. Di sini, hal utama kami untuk mengimplementasikan metode nullsafeSet (). Metode ini terutama menggunakan menyimpan jenis nilai ini ke database. Kali ini kita akan belajar cara menggunakannya terlebih dahulu, dan kemudian kita akan perlahan -lahan mempelajari bagaimana itu diimplementasikan secara internal.
2) Contoh yang saya tulis ketika saya belajar merujuk pada contoh Xia Xin, jadi itu pasti sama dengan sebagian besar yang online. Mari kita analisis secara kasar:
Di bawah ini adalah kelas pengguna
paket org.hibernate.tutorial.domain; impor java.io.serializable; impor java.util.list; Pengguna kelas publik mengimplementasikan Serializable {Public Long ID; nama string pribadi; email daftar pribadi; hilangkan metode get/atur} Berikutnya adalah Kelas Emaillist Kustom:
paket org.hibernate.tutorial.domain; impor java.io.serializable; impor java.sql.preparedstatement; impor java.sql.Resultset; impor java.sql.sqlexception; impor java.sql.sql.types; impor java.util.arraylist; impor java.util.list; impor org.hibernate.hibernate; impor org.hibernate.hibernateException; impor org.hibernate.usertype.userType; Emaillist kelas publik mengimplementasikan UserType {private static final char splitter = ';'; private static final int [] type = new int [] {type.varchar}; Private String Assemble (daftar emaillist) {stringBuilder strbuf = new StringBuilder (); untuk (int i = 0; i <emaillist.size () - 1; i ++) {strbuf.append (emaillist.get (i)). append (splitter); } strbuf.append (emaillist.get (emaillist.size ()-1)); return strbuf.tostring (); } private list parse (nilai string) {string [] strs = org.hibernate.util.stringhelper.split (value, string.valueof (splitter)); Daftar emaillist = arraylist baru (); untuk (int i = 0; i <strs.length; i ++) {emaillist.add (strs [i]); } return emaillist; } objek publik DeepCopy (Nilai Objek) Melempar HibernateException {List Sourcelist = (Daftar) Nilai; Daftar TargetList = ArrayList baru (); TargetList.Add (Sourcelist); Return TargetList; } Disassemble Serializable Public (nilai objek) melempar HibernateException {return null; } public boolean sama (objek x, objek y) melempar hibernateException {if (x == y) mengembalikan true; System.out.println ("x:"+x+"y:"+y); if (x! = null && y! = null) {daftar xlist = (daftar) x; Daftar yList = (daftar) y; if (xlist.size ()! = ylist.size ()) Return false; untuk (int i = 0; i <xlist.size (); i ++) {string str1 = (string) xlist.get (i); String str2 = (string) ylist.get (i); if (! str1.equals (str2)) mengembalikan false; } return true; } return false; } public boolean isMutable () {return false; } Objek publik nullSafeget (hasil rs, string [] nama, pemilik objek) melempar hibernateException, sqlexception {string value = (string) hibernate.string.nullsafeget (rs, nama [0]); if (value! = null) {return parse (value); // paste list; split} else {return null; }} public void nullSafeSet (disiapkan stasiun st, nilai objek, indeks int) melempar hibernateException, sqlexception {system.out.println ("Set Metode dieksekusi!"); System.out.println ("Nilai:" + nilai); if (value! = null) {string str = rakitan ((daftar) nilai); // gunakan string; splice hibernate.string.nullsafeset (st, str, index); } else {hibernate.string.nullsafeset (st, value, index); }} kelas public returnedclass () {return list.class; } public int [] sqlTypes () {return tipe; } // hilangkan metode lain yang tidak memerlukan modifikasi} Metode yang diterapkan di kelas adalah metode yang perlu dimodifikasi, dan metode lain yang tidak perlu dimodifikasi untuk saat ini belum ditulis, tetapi mereka masih perlu diimplementasikan.
3) Berikutnya adalah file pemetaan kelas pengguna:
<class name = "user" table = "user"> <id name = "id" column = "user_id" type = "java.lang.long"> <generator/> </d> <name properti = "name" type = "string" column = "User_name"/> <name property = "email" type = "org.hibernate.tutorial.
Saya percaya semua orang tahu cara memodifikasinya, dan saya tidak akan menjelaskannya di sini. Ini terutama mengubah jenis email dan mengubahnya ke kelas emaillist yang baru saja kami tentukan.
4) Akhirnya, mari kita tulis kelas tes:
impor java.util.hashmap; impor java.util.list; impor java.util.map; impor java.util.arraylist; impor junit.framework.testcase; impor org.hibernate.entityMode; impor org.hibernate.Session; impor org.hibernate.SessionFactory; impor org.hibernate.transaction; impor org.hibernate.cfg.configuration; impor org.hibernate.tutorial.domain.user; kelas publik hibernatetest memperluas testcase {private sesi sesi = null; pelindung void setup () melempar pengecualian {configuration cfg = configuration baru (). configure (); SessionFactory sessionFactory = cfg.buildsessionFactory (); session = sessionfactory.opensession (); } public void testInsert () {transaction tran = null; coba {tran = session.begintransaction (); Pengguna pengguna = pengguna baru (); user.setname ("shun"); Daftar Daftar = ArrayList baru (); list.add ("[email protected]"); list.add ("[email protected]"); user.setemails (daftar); session.save (pengguna); Tran.Commit (); } catch (exception ex) {ex.printstacktrace (); if (tran! = null) {tran.rollback (); }} void teardown yang dilindungi () melempar Exception {session.close (); }} Mungkin ada masalah di sini. Ketika kami hanya menyimpan satu email, itu akan memiliki pengecualian. Bidang email dalam database kosong. Ketika kami memiliki dua kode seperti kode di atas, tidak akan ada masalah. Hasil dalam database adalah seperti yang ditunjukkan pada gambar:
Dan ketika kita hanya menyimpan satu, pengecualian adalah sebagai berikut:
java.lang.classcastException: java.util.arraylist tidak dapat dilemparkan ke java.lang.string
Itu terjadi dalam metode Equals emaillist, string str1 = (string) xlist.get (i); Dalam kode ini, setelah memeriksa, itu menjadi daftar daftar saat memasukkan data dan meneruskannya ke metode nullsafeSet emaillist, yaitu,
Nilai: [[[email protected], [email protected]]]] Formulir ini akan menyebabkan masalah saat membandingkan. Itu selalu memiliki satu nilai, tetapi berbeda saat membandingkan.
if (xlist.size ()! = ylist.size ()) Return false;
Jadi akan ada masalah saat casting.
Setelah inspeksi, metode yang sama:
X: [[[email protected], [email protected]]] y: [[email protected], [email protected]]
Hasil ini sangat aneh. Internet tidak berbicara tentang mengapa situasi ini terjadi. Izinkan saya mengusulkannya di sini: Versi Hibernate yang saya gunakan adalah Hibernate 3.3.2.ga. Saya tidak tahu apakah itu masalah versi atau masalah lain, mari kita pelajari besok. Jika ada yang tahu mengapa, saya harap saya akan memberi tahu saya.