hibernate 多对多(many-to-many)
多對多(many-to-many):在操作和性能方面都不太理想,所以多對多的映射使用較少,實際使用中最好轉換成一對多的對象模型;hibernate會為我們創建中間關聯表,轉換成兩個一對多。
1. E-R圖
?
2. 實體類:
Teacher實體類如下:
Java代碼 ??Student實體類如下:
Java代碼 ??3.映射文件如下:
Teacher.hbm.xml如下:
Xml代碼 ??Student.hbm.xml如下:
Xml代碼 ??一定要注意映射文件中<many-to-many class="Teacher" column="teacher_id"/>中class的值,它必須與你另一個關聯映射文件中的class屬性的name值一致,其實就是與你的實體類的類名一致,如:<many-to-many class="Teacher" column="teacher_id"/>中class的值就不能寫成"teacher"。如果寫成這樣的話,就會拋出如下異常:An association from the table teacher_student refers to an unmapped class: com.reiyen .hibernate.domain.teacher
4. 測試程序如下:
Java代碼 ??運行此程序后:控制臺打印的sql語句如下所示:
Hibernate: insert into Teacher (name) values (?)
Hibernate: insert into Teacher (name) values (?)
Hibernate: insert into Student (name) values (?)
Hibernate: insert into Student (name) values (?)
Hibernate: insert into teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into teacher_student (teacher_id, student_id) values (?, ?)
一共在中間表里面插入了4條記錄。
中間表結構如下所示:
DROP TABLE IF EXISTS `test`.`teacher_student`;
CREATE TABLE? `test`.`teacher_student` (
? `teacher_id` int(11) NOT NULL,
? `student_id` int(11) NOT NULL,
? PRIMARY KEY (`student_id`,`teacher_id`),
? KEY `FK2E2EF2DE6C8A2663` (`teacher_id`),
? KEY `FK2E2EF2DE5BEEDBC3` (`student_id`),
? CONSTRAINT `FK2E2EF2DE5BEEDBC3` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`),
? CONSTRAINT `FK2E2EF2DE6C8A2663` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
表中插入的記錄如下所示:
mysql> select * from teacher_student;
+------------+------------+
| teacher_id | student_id |
+------------+------------+
|????????? 1 |????????? 1 |
|????????? 1 |????????? 2 |
|????????? 2 |????????? 1 |
|????????? 2 |????????? 2 |
+------------+------------+
4 rows in set (0.00 sec)
?
程序中注釋為1的語句非常重要,它是建立Teacher與Student關聯的語句,如果沒有這兩條語句,雖然程序照樣會執行,但是在中間表teacher_student沒有任何記錄,也就是Teacher與Student之間未關聯。
當然你也可以通過程序中注釋為2的語句來建立Teacher與Student之間的關聯關系,同樣會產生與注釋為1的語句的效果。但是你不能在程序中同時出現以上四句程序,否則會拋出異常( PRIMARY KEY (`student_id`,`teacher_id`),所以會出現主鍵沖突的異常),:
Hibernate: insert into teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into teacher_student (student_id, teacher_id) values (?, ?)
Hibernate: insert into teacher_student (student_id, teacher_id) values (?, ?)
Hibernate: insert into teacher_student (student_id, teacher_id) values (?, ?)
Hibernate: insert into teacher_student (student_id, teacher_id) values (?, ?)
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
解決上面產生異常的辦法是設置inverse屬性。即在Tearcher一端或Student一端設置inverse="true",即讓他們之中的某一方放棄維護關聯關系。此時,雖然上面四句程序在測試程序中同時出現了(其實就是在對象模型上相互設置了他們的關聯關系),但程序照樣能運行正常,因為了在數據庫模型上,只會有兩句程序生效,也就是沒有設置inverse="true"的那一端會去維護關聯關系。有關inverse的說細信息,可以參看我的文章hibernate級聯(cascade和inverse).
?
執行測試程序中的查詢測試,控制臺打印的信息如下所示:
Hibernate: select teacher0_.id as id5_0_, teacher0_.name as name5_0_ from Teacher teacher0_ where teacher0_.id=?
Hibernate: select students0_.teacher_id as teacher1_1_, students0_.student_id as student2_1_, student1_.id as id7_0_, student1_.name as name7_0_ from teacher_student students0_ left outer join Student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
students:2
從打印出的sql語句可以看出,多對多關系進行查詢時,效率是比較低的。
總結
以上是生活随笔為你收集整理的hibernate 多对多(many-to-many)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hibernate中List一对多映射关
- 下一篇: Hibernate4多对多关系映射