ฉันเพิ่งเห็นประเภทของไฮเบอร์เนตที่กำหนดเอง ฉันไม่เคยสัมผัสมาก่อน ฉันจะบันทึกไว้ที่นี่เป็นการรวมความรู้ของฉันและให้เพื่อนที่ไม่เคยสัมผัสกับการเรียนรู้และศึกษาด้วยกัน
1) ประเภทที่กำหนดเองตามชื่อที่แนะนำเป็นประเภทหลักสูตรที่ดำเนินการด้วยตัวเองเพราะประเภทภายในไม่ตรงกับความต้องการ มีสถานการณ์ไม่มากนัก แต่เรายังต้องเรียนรู้ หากเรามีทักษะมากขึ้นเราจะไม่ระงับร่างกายของเรา นอกจากนี้ยังเรียนรู้ว่าคนอื่นพิจารณาวิธีคิดเกี่ยวกับความสามารถในการขยายเวลาอย่างไรเมื่อทำเฟรมเวิร์ก
มีสองวิธีในการใช้ประเภทที่กำหนดเองอย่างใดอย่างหนึ่งคือการใช้ UserType อีกวิธีหนึ่งคือการใช้ CompositeUserType และอาจมีวิธีการบางอย่าง แต่ฉันไม่ได้ใช้มันในขณะนี้ดังนั้นฉันจะไม่พูดถึงเรื่องนี้ในตอนนี้
ฉันใช้เฉพาะ UserType ในขณะนี้มาดูคำจำกัดความของอินเทอร์เฟซ UserType ก่อน:
ส่วนต่อประสานสาธารณะ UserType { /*** ส่งคืนรหัสประเภท SQL สำหรับคอลัมน์ที่แมปตามประเภทนี้ รหัส * ถูกกำหนดไว้ใน <tt> java.sql.types </tt> */ public int [] sqltypes (); /*** คลาสที่ส่งคืนโดย <tt> nullsafeget () </tt> */ คลาสสาธารณะกลับมา (); /*** เปรียบเทียบสองอินสแตนซ์ของคลาสที่แมปโดยประเภทนี้เพื่อการคงอยู่ "ความเท่าเทียมกัน" * ความเท่าเทียมกันของสถานะถาวร */ บูลีนสาธารณะเท่ากับ (วัตถุ X, Object y) พ่น HibernateException; / ** * รับ hashcode สำหรับอินสแตนซ์สอดคล้องกับการคงอยู่ "ความเท่าเทียม" */ public int hashcode (วัตถุ x) พ่น HibernateException; /*** ดึงอินสแตนซ์ของคลาสที่แมปจากชุดผลลัพธ์ JDBC ผู้ใช้ * ควรจัดการกับความเป็นไปได้ของค่า NULL */ วัตถุสาธารณะ nullsafeget (Resultset rs, string [] ชื่อ, เจ้าของวัตถุ) พ่น HibernateException, sqlexception; /*** เขียนอินสแตนซ์ของคลาสที่แมปไปยังคำสั่งที่เตรียมไว้ ผู้ใช้ * ควรจัดการกับความเป็นไปได้ของค่า NULL ควรเขียนประเภทหลายคอลัมน์ * ไปยังพารามิเตอร์เริ่มต้นจาก <tt> ดัชนี </tt> */ โมฆะสาธารณะ nullSafeset (PreparedStatement ST, ค่าวัตถุ, ดัชนี int) พ่น HibernateException, Sqlexception; /** * ส่งคืนสำเนาลึกของสถานะถาวรหยุดที่เอนทิตีและที่ * คอลเลกชัน ไม่จำเป็นต้องคัดลอกวัตถุที่ไม่เปลี่ยนรูปหรือค่า NULL * ซึ่งในกรณีนี้ปลอดภัยที่จะคืนอาร์กิวเมนต์ */ วัตถุสาธารณะ DEEPCOPY (ค่าวัตถุ) พ่น HibernateException; /*** วัตถุประเภทนี้ไม่แน่นอนหรือไม่? * * @return Boolean */ Public Boolean ismutable (); /*** แปลงวัตถุให้เป็นตัวแทนที่แคชได้ อย่างน้อยที่สุดวิธีนี้ * ควรทำสำเนาลึกหากประเภทนั้นไม่แน่นอน อย่างไรก็ตามอาจไม่เพียงพอสำหรับการใช้งานบางอย่าง ตัวอย่างเช่นการเชื่อมโยงจะต้องแคชเป็น * ค่าตัวระบุ (การดำเนินการทางเลือก) * * @param ค่าวัตถุที่จะแคช * @return การแสดงที่แคชได้ของวัตถุ * @throws hibernateException */ public serializable disassemble (ค่าวัตถุ) โยน hibernateException; /*** สร้างวัตถุใหม่จากการเป็นตัวแทนที่แคช อย่างน้อยที่สุดวิธีนี้ * ควรทำสำเนาลึกหากประเภทนั้นไม่แน่นอน (การดำเนินการเสริม) */ การประกอบวัตถุสาธารณะ (แคชที่เป็น serializable, เจ้าของวัตถุ) โยน hibernateException; /** * ในระหว่างการผสานให้แทนที่ค่า (เป้าหมาย) ที่มีอยู่ในเอนทิตีที่เรารวมเข้ากับ * ด้วยค่าใหม่ (ต้นฉบับ) จากเอนทิตีเดี่ยวที่เรารวมอยู่ สำหรับวัตถุ * ที่ไม่เปลี่ยนรูปหรือค่า NULL มันปลอดภัยที่จะส่งคืนพารามิเตอร์แรก สำหรับ * วัตถุที่ไม่แน่นอนมันปลอดภัยที่จะส่งคืนสำเนาของพารามิเตอร์แรก สำหรับวัตถุ * ที่มีค่าส่วนประกอบมันอาจเหมาะสมที่จะแทนที่ค่าส่วนประกอบซ้ำ */ วัตถุสาธารณะแทนที่ (วัตถุต้นฉบับ, เป้าหมายวัตถุ, เจ้าของวัตถุ) พ่น HibernateException; - ในความเป็นจริงคุณสามารถเข้าใจเป็นภาษาอังกฤษโดยทั่วไปดังนั้นฉันจะไม่อธิบายเพิ่มเติม ที่นี่สิ่งสำคัญที่เราต้องใช้วิธี nullSafeset () วิธีนี้ส่วนใหญ่ใช้การบันทึกค่าประเภทนี้ไปยังฐานข้อมูล เวลานี้เราจะได้เรียนรู้วิธีการใช้ก่อนจากนั้นเราจะศึกษาอย่างช้าๆว่ามันถูกนำไปใช้ภายในอย่างไร
2) ตัวอย่างที่ฉันเขียนเมื่อฉันกำลังศึกษากำลังอ้างถึงตัวอย่างของ Xia Xin ดังนั้นมันจึงเป็นแบบเดียวกับออนไลน์ส่วนใหญ่ มาวิเคราะห์กันเถอะ:
ด้านล่างคือคลาสผู้ใช้
แพ็คเกจ org.hibernate.tutorial.domain; นำเข้า java.io.serializable; นำเข้า java.util.list; ผู้ใช้ระดับสาธารณะใช้ serializable {Public Long ID; ชื่อสตริงส่วนตัว; อีเมลรายการส่วนตัว ละเว้นวิธีการรับ/ตั้งค่า} ถัดไปคือคลาส Emaillist ที่กำหนดเอง:
แพ็คเกจ org.hibernate.tutorial.domain; นำเข้า java.io.serializable; นำเข้า java.sql.preparedStatement; นำเข้า java.sql.resultset; นำเข้า java.sql.sqlexception; นำเข้า java.sql.sql.types; นำเข้า java.util.arraylist; นำเข้า java.util.list; นำเข้า org.hibernate.hibernate; นำเข้า org.hibernate.HibernateException; นำเข้า org.hibernate.usertype.usertype; Emaillist คลาสสาธารณะใช้ UserType {Private Static Final Char Splitter = ';'; int สุดท้ายคงที่ int [] type = new int [] {types.varchar}; การประกอบสตริงส่วนตัว (รายการ emaillist) {StringBuilder strBuf = new StringBuilder (); สำหรับ (int i = 0; i <emaillist.size () - 1; i ++) {strbuf.append (emaillist.get (i)). ผนวก (ตัวแยก); } strbuf.append (emaillist.get (emaillist.size ()-1)); return strbuf.toString (); } รายการส่วนตัวแยกวิเคราะห์ (ค่าสตริง) {string [] strs = org.hibernate.util.stringhelper.split (value, string.valueof (splitter)); รายการ emaillist = new ArrayList (); สำหรับ (int i = 0; i <strs.length; i ++) {emaillist.add (strs [i]); } ส่งคืน Emaillist; } วัตถุสาธารณะ DEEPCOPY (ค่าวัตถุ) พ่น HiberNateException {รายการ sourceList = (รายการ) ค่า; รายการ targetList = new ArrayList (); TargetList.add (sourcelist); ส่งคืนรายการเป้าหมาย; } การถอดแบบ serializable สาธารณะ (ค่าวัตถุ) พ่น HibernateException {return null; } บูลีนสาธารณะเท่ากับ (วัตถุ X, Object y) พ่น HibernateException {ถ้า (x == y) ส่งคืนจริง; System.out.println ("x:"+x+"y:"+y); if (x! = null && y! = null) {list xlist = (รายการ) x; รายการ ylist = (รายการ) y; if (xlist.size ()! = ylist.size ()) ส่งคืนเท็จ; สำหรับ (int i = 0; i <xlist.size (); i ++) {string str1 = (สตริง) xlist.get (i); string str2 = (สตริง) ylist.get (i); if (! str1.equals (str2)) กลับเท็จ; } return true; } return false; } บูลีนสาธารณะ ismutable () {return false; } วัตถุสาธารณะ nullsafeget (Resultset rs, string [] ชื่อ, เจ้าของวัตถุ) พ่น hibernateException, sqlexception {ค่าสตริง = (สตริง) hibernate.string.nullsafeget (rs, ชื่อ [0]); if (value! = null) {return parse (value); // paste list; แยก} else {return null; }} โมฆะสาธารณะ nullSafeset (PreparedStatement ST, ค่าวัตถุ, ดัชนี int) พ่น HibernateException, Sqlexception {System.out.println ("Set Method Executed!"); System.out.println ("ค่า:" + ค่า); if (value! = null) {string str = assemble ((รายการ) ค่า); // ใช้สตริง; Splice hibernate.string.nullsafeset (ST, Str, INDEX); } else {hibernate.string.nullsafeset (ST, ค่า, ดัชนี); }} คลาสสาธารณะ ReturnedClass () {return list.class; } public int [] sqltypes () {ประเภทการส่งคืน; } // ละเว้นวิธีการอื่น ๆ ที่ไม่จำเป็นต้องมีการแก้ไข} วิธีการที่ใช้ในชั้นเรียนเป็นวิธีการที่จำเป็นต้องแก้ไขและวิธีการอื่น ๆ ที่ไม่จำเป็นต้องแก้ไขในขณะที่ยังไม่ได้ถูกเขียนออกไป แต่พวกเขายังคงต้องดำเนินการ
3) ถัดไปคือไฟล์การแมปของคลาสผู้ใช้:
<class name = "user" table = "user"> <id name = "id" คอลัมน์ = "user_id" type = "java.lang.long"> <generator/> </id> <name property = "name" type = "string" column = "user_name"/>
ฉันเชื่อว่าทุกคนรู้วิธีแก้ไขและฉันจะไม่อธิบายที่นี่ ส่วนใหญ่จะเปลี่ยนประเภทของอีเมลและเปลี่ยนเป็นคลาส Emaillist ที่เราเพิ่งกำหนดไว้
4) สุดท้ายมาเขียนคลาสทดสอบ:
นำเข้า java.util.hashmap; นำเข้า java.util.list; นำเข้า java.util.map; นำเข้า java.util.arraylist; นำเข้า junit.framework.testcase; นำเข้า org.hibernate.entityMode; นำเข้า org.hibernate.session; นำเข้า org.hibernate.sessionfactory; นำเข้า org.hibernate.transaction; นำเข้า org.hibernate.cfg.configuration; นำเข้า org.hibernate.tutorial.domain.user; ชั้นเรียนสาธารณะ hibernatetest ขยาย testcase {เซสชันส่วนตัวเซสชัน = null; การตั้งค่าโมฆะที่ได้รับการป้องกัน () โยนข้อยกเว้น {การกำหนดค่า cfg = การกำหนดค่าใหม่ (). configure (); SessionFactory SessionFactory = cfg.buildsessionFactory (); session = sessionfactory.opensession (); } โมฆะสาธารณะ testInsert () {ธุรกรรม tran = null; ลอง {tran = session.beginTransaction (); ผู้ใช้ผู้ใช้ = ผู้ใช้ใหม่ (); user.setName ("Shun"); รายการรายการ = new ArrayList (); list.add ("[email protected]"); list.add ("[email protected]"); user.setEmails (รายการ); session.save (ผู้ใช้); tran.commit (); } catch (exception ex) {ex.printstacktrace (); if (tran! = null) {tran.rollback (); }} การป้องกันการฉีกขาด () พ่นข้อยกเว้น {session.close (); - อาจมีปัญหาที่นี่ เมื่อเราบันทึกอีเมลเพียงครั้งเดียวมันจะมีข้อยกเว้น ฟิลด์อีเมลในฐานข้อมูลว่างเปล่า เมื่อเรามีสองรหัสเช่นรหัสข้างต้นจะไม่มีปัญหา ผลลัพธ์ในฐานข้อมูลดังแสดงในรูป:
และเมื่อเราบันทึกเพียงหนึ่งข้อยกเว้นมีดังนี้:
java.lang.classcastexception: java.util.arraylist ไม่สามารถส่งไปที่ java.lang.string
มันเกิดขึ้นในวิธี Equals ของ Emaillist, String str1 = (String) xlist.get (i); ในรหัสนี้หลังจากการตรวจสอบจะกลายเป็นรายการของรายการเมื่อแทรกข้อมูลและส่งผ่านไปยังวิธี nullSafeset ของ Emaillist นั่นคือนั่นคือนั่นคือ
ค่า: [[[email protected], [email protected]]]] แบบฟอร์มนี้จะทำให้เกิดปัญหาเมื่อเปรียบเทียบ มันมักจะมีค่าเพียงหนึ่งค่า แต่มันจะแตกต่างกันเมื่อเปรียบเทียบ
if (xlist.size ()! = ylist.size ()) ส่งคืนเท็จ;
ดังนั้นจะมีปัญหาเมื่อคัดเลือกนักแสดง
หลังจากการตรวจสอบวิธีการเท่ากับ:
x: [[[email protected], [email protected]] y: [[email protected], [email protected]]
ผลลัพธ์นี้แปลกมาก อินเทอร์เน็ตไม่ได้พูดถึงสาเหตุที่สถานการณ์นี้เกิดขึ้น ให้ฉันเสนอที่นี่: เวอร์ชันไฮเบอร์เนตที่ฉันใช้คือไฮเบอร์เนต 3.3.2.ga ฉันไม่รู้ว่าเป็นปัญหาเวอร์ชันหรือปัญหาอื่นมาศึกษากันในวันพรุ่งนี้ ถ้าใครรู้ว่าทำไมฉันหวังว่าฉันจะบอกฉัน