1. สมาคมคีย์หลักสองทาง
การเชื่อมโยงคีย์หลักแบบสองทิศทางเป็นกรณีพิเศษของการเชื่อมโยงคีย์หลักแบบหนึ่งต่อหนึ่ง อย่างไรก็ตามการกำหนดค่า <หนึ่งต่อหนึ่ง> จะต้องดำเนินการในไฟล์การแมปที่ปลายทั้งสองของวัตถุที่เกี่ยวข้องและนอกจากนี้คุณลักษณะการเชื่อมโยงคีย์ต่างประเทศจะต้องใช้ที่ปลายด้านหนึ่งของคีย์หลักของแผนที่หลัก
ที่นี่เรายังใช้บุคคลและ Idcard เพื่อหารือ บุคคลที่สอดคล้องกับบัตรประจำตัวที่ไม่ซ้ำกันและบัตรประจำตัวประชาชนยังแมปบุคคลโดยไม่ซ้ำกันดังนั้นสิ่งนี้จะสร้างความสัมพันธ์ระหว่างสองทาง คีย์หลักของบุคคลนั้นยังเป็นคีย์หลักของ Idcard ซึ่งเป็นทั้งคีย์หลักและคีย์ต่างประเทศ ความสัมพันธ์การเชื่อมโยงนี้กลายเป็นการแมปแบบหนึ่งต่อหนึ่งซึ่งสามารถแสดงในรูปแบบความสัมพันธ์ดังที่แสดงด้านล่าง:
สองตารางในรูปใช้การเชื่อมโยงคีย์หลัก คีย์หลักของบุคคลคือคีย์หลักของ Idcard ดังนั้นพวกเขาจึงสร้างความสัมพันธ์แบบ จำกัด ระหว่างคีย์ต่างประเทศจู้และสร้างความมั่นใจในเอกลักษณ์ให้แมปเป็นโมเดลวัตถุและเปลี่ยนเป็นความสัมพันธ์แบบหนึ่งต่อหนึ่งระหว่างคลาสบุคคลและคลาส Idcard ดังแสดงในรูปด้านล่าง:
ความสัมพันธ์แบบตัวต่อตัวนี้ยังกล่าวถึงในบทความก่อนหน้านี้ว่ามีการใช้แท็ก <หนึ่งต่อหนึ่ง> และการแมปแบบหนึ่งต่อหนึ่งนี้เป็นแบบสองทิศทางดังนั้นเราจึงต้องกำหนดค่า <หนึ่งต่อหนึ่ง> ระหว่างวัตถุสองชิ้นในเวลาเดียวกัน ก่อนอื่นให้ดูที่รหัสคลาสและรหัสไฟล์การแมปที่สอดคล้องกับ Idcard
1. ข้อมูลที่สอดคล้องกับ Idcard
มีความสัมพันธ์แบบหนึ่งต่อหนึ่งระหว่างคลาส Idcard.java, คลาส Idcard และคลาสบุคคล ดังนั้นควรเพิ่มแอตทริบิวต์บุคคลที่เกี่ยวข้องในคลาส Idcard นี่คือการเพิ่มแอตทริบิวต์ที่สอดคล้องกันในคีย์ต่างประเทศในไฟล์การแมปและตั้งค่าคลาสสมาคมคีย์ต่างประเทศที่สอดคล้องกัน
แพ็คเกจ com.src.hibernate; Idcard คลาสสาธารณะ {// id attribute id private int id; สาธารณะ int getId () {return id; } โมฆะสาธารณะ setId (int id) {this.id = id; } // หมายเลขบัตรแอตทริบิวต์สตริงส่วนตัว Cardno; สตริงสาธารณะ getCardno () {return cardno; } โมฆะสาธารณะ setCardno (สตริง cardno) {this.cardno = cardno; } // คนที่สอดคล้องกับหมายเลขบัตรบุคคลส่วนตัวบุคคล; บุคคลสาธารณะ getPerson () {บุคคลที่กลับมา; } โมฆะสาธารณะ setperson (บุคคลบุคคล) {this.person = บุคคล; -ไฟล์การแมป idcard.hbm.xml เพิ่มผู้ใช้แอตทริบิวต์คีย์ต่างประเทศให้กับไฟล์การแมปและเพิ่มแท็ก <หนึ่งต่อหนึ่งที่สอดคล้องกัน วัตถุประสงค์คือเพื่อบังคับให้ชนชั้นบุคคลที่มีข้อ จำกัด เพื่อให้บรรลุความสัมพันธ์การทำแผนที่แบบหนึ่งต่อหนึ่ง ในที่สุดตั้งค่าแอตทริบิวต์ข้อ จำกัด เป็น TRUE ในการแมปเพื่อให้แน่ใจว่ามีความสัมพันธ์แบบ จำกัด ข้อ จำกัด
<? xml เวอร์ชัน = "1.0"?> <! Doctype hibernate-mapping สาธารณะ "-// hibernate/hibernate mapping dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" -> <hibernate-mapping> <class name = "com.src.hibernate.idcard" table = "idcard"> <id name = "id" type = "int" คอลัมน์ = "personid"> <generator> <param name = "property"> person </param> constrained = "true"> </one-to-one> </class> </hibernate-mapping>
2. ข้อมูลที่สอดคล้องกันของบุคคล
ในคลาส Person.java นอกเหนือจากการเพิ่มแอตทริบิวต์พื้นฐานแล้วคลาส Idcard ที่สอดคล้องกันจะต้องเพิ่มเป็นแอตทริบิวต์เพราะพวกเขาเป็นความสัมพันธ์แบบหนึ่งต่อสองทางดังนั้นคลาส Idcard จะต้องเพิ่มในคลาสบุคคล เหตุผลเดียวกันก็คือแอตทริบิวต์คลาสบุคคลจะถูกเพิ่มเข้าไปในคลาส Idcard
แพ็คเกจ com.src.hibernate; บุคคลชั้นเรียนสาธารณะ {// หมายเลข ID ID int ส่วนตัว; สาธารณะ int getId () {return id; } โมฆะสาธารณะ setId (int id) {this.id = id; } // ชื่อชื่อสตริงส่วนตัว; สตริงสาธารณะ getName () {ชื่อคืน; } โมฆะสาธารณะ setName (ชื่อสตริง) {this.name = name; } // Idcard Idcard Idcard; Idcard สาธารณะ getIdCard () {return idcard; } โมฆะสาธารณะ SetIdCard (Idcard Idcard) {this.idcard = idcard; -person.hbm.xml ไฟล์การแมปกลยุทธ์การสร้างคีย์หลักในไฟล์นี้ไม่มีข้อกำหนดพิเศษเนื่องจากมีการ จำกัด ร่วมกันโดยคลาส Idcard คีย์หลักและคีย์ต่างประเทศเป็นทั้งคีย์หลักของ Idcard นอกจากนี้เนื่องจากเป็นความสัมพันธ์แบบตัวต่อตัวควรเพิ่มแท็ก <หนึ่งต่อหนึ่ง> ในไฟล์การแมปเพื่อระบุ
<? xml เวอร์ชัน = "1.0"?> <! Doctype hibernate-mapping สาธารณะ "-// hibernate/hibernate mapping dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" -> <hibernate-mapping> <class name = "com.src.hibernate.person" table = "person"> <id name = "id" type = "int" คอลัมน์ = "personid"> <senerator> โดยค่าเริ่มต้นจะโหลดตามคีย์หลักนั่นคือรับค่าของฟิลด์ความสัมพันธ์และโหลดวัตถุที่เกี่ยวข้องตามคีย์หลักของฝ่ายตรงข้าม-> <ชื่อหนึ่งต่อหนึ่ง = "Idcard"> </nego to-one>
3. ไฟล์การแมปไฮเบอร์เนต
หลังจากกำหนดค่าไฟล์คลาสและการแมปด้านบนข้อมูลเกี่ยวกับการแมปฐานข้อมูลใน hibernate.cfg.xml จำเป็นต้องเพิ่มไฟล์การกำหนดค่าสองไฟล์ลงในไฟล์การกำหนดค่าไฮเบอร์เนตเพื่อให้สามารถพบรายการการสร้างที่สอดคล้องกันเมื่อสร้างฐานข้อมูลที่สอดคล้องกัน
<? XML เวอร์ชัน = "1.0" การเข้ารหัส = "UTF-8"?> <! doctype hibernate-configuration สาธารณะ "-// hibernate/hibernate การกำหนดค่า dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-configuration-3 <session-factory> <property name = "hibernate.connection.driver_class"> com.mysql.jdbc.driver </คุณสมบัติ> <property name = "hibernate.connection.url"> jdbc: mysql: // localhost: 3306/hibernate_one2one_pk1 name = "hibernate.connection.username"> root </property> <property name = "hibernate.connection.password"> 1234 </คุณสมบัติ> <property name = "hibernate.dialect"> org.hibernate.dialect.mysqldialect </คุณสมบัติ> < Resource = "com/src/hibernate/idcard.hbm.xml"> </mapping> </session-factory> </HiberNate-Configuration>
4. สร้างผลลัพธ์
หลังจากการกำหนดค่าเสร็จสมบูรณ์คุณสามารถสร้างฐานข้อมูลที่เกี่ยวข้องจากเนื้อหาข้างต้น ในฐานข้อมูลมันจะสร้างโครงสร้างตารางที่สอดคล้องกันตามเนื้อหาที่กำหนดค่าและมีคีย์ต่างประเทศที่สอดคล้องกันและฟิลด์คีย์หลักในตาราง เมื่อสร้างโครงสร้างตารางไฮเบอร์เนตจะส่งออกคำสั่ง SQL ที่เกี่ยวข้องในคอนโซลดังนี้:
เปลี่ยนตาราง Idcard วางคีย์ต่างประเทศ FK806F76ABAC038CD8 ตารางวางถ้ามีตารางดร็อปดรอปบัตรหากมีอยู่คนสร้างตาราง IDCARD (Integer Personid ไม่ใช่ NULL, Cardno Varchar (255), คีย์หลัก (personid)) สร้างตารางบุคคล FK806F76AC038CD8 (personID), เพิ่มข้อ จำกัด FK806F76AC038CD8 คีย์ต่างประเทศ (บุคคล) อ้างอิงบุคคล (personID)
โครงสร้างตารางที่สร้างขึ้นดังแสดงในรูป:
คีย์หลักของบุคคลนั้นถูกสร้างขึ้นในทั้งสองตารางในเวลาเดียวกันและยังเป็นคีย์ต่างประเทศที่สอดคล้องกัน นอกจากนี้ยัง จำกัด ปุ่มหลักของสองตารางในเวลาเดียวกันและไม่ซ้ำกัน
5. การทดสอบเขียนและโหลด
หลังจากสร้างตารางให้เขียนตารางและอ่านข้อมูลจากตารางเขียนคลาสทดสอบที่สอดคล้องกันและการทดสอบใช้การทดสอบหน่วยและเขียนวิธีการทดสอบที่สอดคล้องกัน
5.1 การทดสอบเขียน
เมื่อเขียนลงในฐานข้อมูลโปรดทราบว่าวัตถุทั้งสองที่เขียนจะต้องถูกแปลงเป็นสถานะการฝึกอบรมที่สอดคล้องกันมิฉะนั้นจะเกิดข้อผิดพลาดในการแปลงสถานะ รหัสทดสอบมีดังนี้:
โมฆะสาธารณะ TestSave1 () {เซสชันเซสชัน = null; ลอง {// สร้างเซสชันเซสชันเซสชัน = hibernateutils.getSession (); // เปิดใช้งานเซสชันการทำธุรกรรมเซสชัน BEGINTRANSACTION (); // สร้างวัตถุบุคคลและบันทึกบุคคลบุคคล = บุคคลใหม่ (); person.setName ("Zhangsan"); เซสชั่น SAVE (บุคคล); // สร้างวัตถุ IDCARD และบันทึก IDCARD IDCARD = ใหม่ IDCARD (); idcard.setCardno ("111111111111111111); idcard.setperson (บุคคล); session.save (idcard); // ส่งธุรกรรมและแก้ไขเซสชันฐานข้อมูล GetTransaction (). commit (); } catch (ข้อยกเว้น e) {// ข้อความแสดงข้อผิดพลาดพิมพ์ e.printstacktrace (); // การย้อนกลับของธุรกิจ Session.getTransaction (). การย้อนกลับ (); } ในที่สุด {// ปิดเซสชัน hibernateutils.closesession (เซสชัน); - ข้อมูลที่แทรกแสดงอยู่ด้านล่าง:
5.2 การทดสอบการโหลด
เขียนวิธีการโหลด เนื่องจากความสัมพันธ์ระหว่างการเชื่อมโยงเป็นแบบสองทิศทางการดำเนินการโหลดที่สอดคล้องกันควรโหลดปลายอีกด้านหนึ่งผ่านปลายด้านหนึ่งนั่นคือเพื่อให้ได้คลาสบุคคลที่เกี่ยวข้องและรับข้อมูล IDCARD ที่สอดคล้องกันผ่านคลาสบุคคล ตรงกันข้ามควรเป็นจริงรหัสมีดังนี้:
โมฆะสาธารณะ testload1 () {เซสชันเซสชัน = null; ลอง {// สร้างเซสชันเซสชันเซสชัน = hibernateutils.getSession (); // เปิดใช้งานเซสชันการทำธุรกรรมเซสชัน BEGINTRANSACTION (); // รับวัตถุบุคคลและบันทึกบุคคลบุคคล = (บุคคล) เซสชันโหลด (person.class, 5); System.out.println ("idcard.id:"+person.getIdCard (). getId ()); System.out.println ("idcard.cardno:"+person.getIdcard (). getCardno ()); // สร้างวัตถุ IDCARD และบันทึก IDCARD IDCARD = (IDCARD) Session.Load (IDCARD.CLASS, 5); System.out.println ("person.id:"+idcard.getPerson (). getId ()); System.out.println ("person.name:"+idcard.getPerson (). getName ()); // ส่งธุรกรรมและแก้ไขเซสชันฐานข้อมูล GetTransaction (). commit (); } catch (ข้อยกเว้น e) {// ข้อความแสดงข้อผิดพลาดพิมพ์ e.printstacktrace (); // การย้อนกลับของธุรกิจ Session.getTransaction (). การย้อนกลับ (); } ในที่สุด {// ปิดเซสชัน hibernateutils.closesession (เซสชัน); - เรียกใช้วิธีการทดสอบด้านบนและพิมพ์เนื้อหาที่เกี่ยวข้องบนคอนโซลดังนี้:
2. ความสัมพันธ์ที่สำคัญในต่างประเทศสองทาง
สมาคมคีย์ต่างประเทศแบบสองทิศทางสามารถเข้าใจได้ว่าเป็นกรณีพิเศษของสมาคมคีย์ต่างประเทศ ความพิเศษนี้ส่วนใหญ่เป็นเพราะมันเป็นจดหมายโต้ตอบแบบสองทิศทาง ในบทความก่อนหน้านี้มีการกล่าวถึงว่าหากคุณต้องการเพิ่มฟิลด์คีย์ต่างประเทศลงในตารางคุณสามารถใช้แท็ก <หลายต่อหนึ่งต่อหนึ่ง> ซึ่งจะสร้างคอลัมน์คีย์ต่างประเทศที่สอดคล้องกันในรูปแบบความสัมพันธ์ แท็กนี้จะต้องใช้หากคุณต้องการบรรลุสมาคมคีย์ต่างประเทศสองทาง
1. โมเดลวัตถุ
ก่อนอื่นให้ดูที่โมเดลวัตถุ ผู้คนและบัตรประจำตัวมีความสัมพันธ์แบบตัวต่อตัว บุคคลหนึ่งสอดคล้องกับตัวตนดังนั้นมัลติเพล็กซ์ระหว่างพวกเขาเป็นหนึ่งต่อหนึ่งและการติดต่อนี้เป็นสองทาง ดังนั้นโมเดลวัตถุของมันจึงเหมือนกับคีย์หลักแบบสองทิศทางหนึ่งต่อหนึ่งดังแสดงในรูปด้านล่าง:
2. โมเดลเชิงสัมพันธ์
รูปแบบความสัมพันธ์ที่สอดคล้องกันจะเปลี่ยนไปอย่างมาก ความสัมพันธ์คีย์ต่างประเทศแบบหนึ่งต่อหนึ่งจะสร้างคีย์ต่างประเทศที่สอดคล้องกันในตาราง เมื่อคุณได้รับบุคคลและบัตรประจำตัวมันหมายความว่าจะมีคอลัมน์คีย์หลักของหมายเลขบัตรประจำตัวในรูปแบบความสัมพันธ์และสถานการณ์แบบตัวต่อตัวแบบสองทางจะเกิดขึ้นระหว่างพวกเขาดังที่แสดงในรูปด้านล่าง:
การติดต่อระหว่างพวกเขาดังที่เห็นในรูปด้านบน มีคีย์หลักของตาราง Idcard ในตารางบุคคลสร้างความสัมพันธ์สมาคมคีย์ต่างประเทศแบบหนึ่งต่อหนึ่งและเป็นแบบสองทิศทาง กล่าวคือ Idcard สามารถรับได้ผ่านบุคคลและบุคคลนั้นสามารถรับได้ผ่าน Idcard
รหัสในวัตถุบุคคลและวัตถุ IDCARD เหมือนกับรหัสวัตถุในบทความก่อนหน้า มันไม่ได้ระบุไว้ในรหัส ความแตกต่างเพียงอย่างเดียวคือปัญหาการกำหนดค่าในไฟล์การแมป
3. ไฟล์การแมป
idcard.hbm.xml ไฟล์การแมป ตาราง IDCARD ไม่ใช่ตารางหลักของการแมปดังนั้นเมื่อทำการแมปแบบหนึ่งต่อหนึ่งคุณต้องใช้แท็ก <หนึ่งต่อหนึ่ง> เพื่อกำหนดค่าและคุณต้องกำหนดคุณลักษณะคีย์ต่างประเทศในรูปแบบความสัมพันธ์ของบุคคล รหัสเฉพาะมีดังนี้:
<? xml เวอร์ชัน = "1.0"?> <! Doctype hibernate-mapping สาธารณะ "-// hibernate/hibernate mapping dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" 3.4.0.cr1-> <hibernate-mapping> <class name = "com.src.hibernate.idcard" table = "idcard"> <id name = "id" type = "int"> <generator /> < /id> <property name = "cardno" type = "java.lang.string" Property-ref = "Idcard"> </nego to-one> </class> </hibernate-mapping>
person.hbm.xml ไฟล์การแมปตารางบุคคลคือตารางหลักของการแมป ต้องเพิ่มคอลัมน์แอตทริบิวต์คีย์ต่างประเทศลงในตารางเพื่อระบุตาราง IDCARD ดังนั้นต้องใช้แท็ก <หลายต่อหนึ่ง-หนึ่ง> ที่นี่เพื่อสร้างคีย์ต่างประเทศที่เกี่ยวข้องในวัตถุบุคคลและไม่ซ้ำกันจะต้องใช้เอกลักษณ์เพื่อระบุว่าแอตทริบิวต์นั้นไม่ซ้ำกัน
<? xml เวอร์ชัน = "1.0"?> <! Doctype hibernate-mapping สาธารณะ "-// hibernate/hibernate mapping dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" 3.4.0.cr1-> <hibernate-mapping> <class name = "com.src.hibernate.person" table = "person"> <id name = "id" type = "int" คอลัมน์ = "personid"> <generator /> </id> <property name = "name" type = "java.lang.string" column = "idcardno" unique = "true" not-null = "true"> </หลายแบบถึงหนึ่ง> </class> </hibernate-mapping>
การกำหนดค่าไฟล์การแมปของวัตถุเสร็จสมบูรณ์จากนั้นสร้างโมเดลเชิงสัมพันธ์ คำสั่ง SQL มีดังนี้:
เปลี่ยนตารางบุคคลวางคีย์ต่างประเทศ fk8c768f55794a52ca ตารางวางถ้ามีตารางดร็อปดร็อปถ้ามีคนสร้าง Idcard ตาราง (ID จำนวนเต็มไม่ใช่ null auto_increment, cardno varchar (255), คีย์หลัก (ID)) สร้าง Table Person (personid)) เปลี่ยนตารางบุคคลเพิ่มดัชนี FK8C768F55794A52CA (IDCARDNO) เพิ่มข้อ จำกัด FK8C768F55794A52CA คีย์ต่างประเทศ (IDCARDNO) อ้างอิง IDCARD (ID)
คำสั่ง SQL ที่สร้างขึ้นเป็นครั้งแรกของตารางที่สร้างขึ้นทั้งหมด เมื่อสร้างตารางคอลัมน์คีย์หลักจะถูกระบุ หลังจากการสร้างเสร็จสิ้นตารางทั้งสองจะได้รับการแก้ไขเพื่อระบุแอตทริบิวต์คีย์ต่างประเทศเพื่อสร้างความสัมพันธ์แบบหนึ่งต่อหนึ่ง
เขียนวิธีการทดสอบนำการทดสอบหน่วยโหลดวัตถุของสองคลาสและรับวัตถุอื่นจากปลายด้านหนึ่งของวัตถุตามลำดับ
// โหลดวัตถุและโหลดวัตถุบุคคลโดยใช้ Idcard Object Public Public Void testload1 () {เซสชันเซสชัน = null; ลอง {session = hibernateutils.getSession (); session.beginTransaction (); // รับวัตถุ IDCARD และรับวัตถุบุคคลที่เชื่อมโยงกับวัตถุโดยเฉพาะใน Idcard Idcard Idcard = (idcard) session.load (idcard.class, 1); System.out.println ("person.id ="+idcard.getPerson (). getId ()); System.out.println ("idcard.person.name ="+idcard.getPerson (). getName ()); // getPerson Object และรับวัตถุ Idcard ที่เกี่ยวข้องอย่างไม่ซ้ำกันกับมันในบุคคลวัตถุบุคคลบุคคล = (บุคคล) เซสชันโหลด (person.class, 1); System.out.println ("idcard.id:"+person.getIdCard (). getId ()); System.out.println ("idcard.cardno:"+person.getIdcard (). getCardno ()); // commit transaction session.getTransaction (). commit (); } catch (exception e) {e.printstacktrace (); session.getTransaction (). ย้อนกลับ (); } ในที่สุด {hibernateutils.closesession (เซสชัน); - เนื้อหาที่สร้างขึ้น:
การเปรียบเทียบความสัมพันธ์การทำแผนที่ทั้งสองความสัมพันธ์หลักและความสัมพันธ์การแมปคีย์ต่างประเทศเป็นทั้งความสัมพันธ์การทำแผนที่แบบสองทิศทางและความสัมพันธ์การทำแผนที่จะต้องมีการกำหนดค่าในเวลาเดียวกันที่ปลายทั้งสองของวัตถุ ความแตกต่างคือคีย์หลักต้องใช้ <หนึ่งต่อหนึ่ง> เนื่องจากไม่จำเป็นต้องสร้างคอลัมน์แอตทริบิวต์ แต่ต้องใช้กลยุทธ์การสร้างคีย์หลักในต่างประเทศสำหรับคีย์หลักของตารางและวัตถุคีย์ต่างประเทศถูกทำเครื่องหมาย กลยุทธ์การสร้างคีย์ต่างประเทศจำเป็นต้องใช้แท็ก <หลายต่อหนึ่ง> เพื่อสร้างคอลัมน์คีย์ต่างประเทศใหม่
บทสรุป
การทำแผนที่แบบหนึ่งต่อหนึ่งในสมาคมสองทางได้รับการหารือกันจนถึงตอนนี้ บทความทั้งสองส่วนใหญ่จะพูดถึงการใช้สองครั้งของสมาคมสองทาง ในความเป็นจริงมันยังคงง่ายมาก อย่าลืมใช้แท็ก <หลายต่อหนึ่ง> หากคุณต้องการสร้างคีย์ต่างประเทศ หากเป็นเอกลักษณ์ให้เพิ่มแอตทริบิวต์ที่ไม่ซ้ำกัน แท็ก <หนึ่งต่อหนึ่ง> หมายถึงความสัมพันธ์แบบหนึ่งต่อหนึ่งเท่านั้น มันระบุเพียงว่าวัตถุหนึ่งโหลดวัตถุอื่นและไม่เพิ่มคอลัมน์ใหม่ในโมเดลความสัมพันธ์ บทความถัดไปจะหารือเกี่ยวกับความสัมพันธ์แบบตัวต่อตัว