hibernate 一对多(one-to-many)双向关联
一對(duì)多(one-to-many)雙向關(guān)聯(lián)實(shí)例(Department- Employee)
這里的一對(duì)多雙向關(guān)聯(lián)是在域模型(實(shí)體對(duì)象模型)上的概念,在關(guān)系數(shù)據(jù)庫(kù)中,只存在外鍵參照關(guān)系,而且總是由"many"方參照"one"方,因?yàn)檫@樣才能消除冗余數(shù)據(jù),因上關(guān)系數(shù)據(jù)庫(kù)實(shí)際上只支持多對(duì)一或一對(duì)一的單向關(guān)聯(lián).在實(shí)體(類與類之間)各種各樣的關(guān)系中,數(shù)多對(duì)一的的單向關(guān)聯(lián)關(guān)系與數(shù)據(jù)庫(kù)中的外鍵參照關(guān)系最匹配了.
在我的前一篇文章多對(duì)一的基礎(chǔ)上進(jìn)行修改。
1.修改Department實(shí)體類:
Java代碼 ??2.修改Department.hbm.xml文件:
Xml代碼 ?<set>元素的屬性name:設(shè)定待映射的持久化類的屬性名,這里為Depatment類的emps屬性.
<set>元素的兩個(gè)子元素:
<key>:設(shè)定與所關(guān)聯(lián)的持久化類對(duì)應(yīng)的表的外鍵,此處為Employee表的depart_id字段.
<one-to-many>:設(shè)定所關(guān)聯(lián)的持久化類,此處為Employee.
Hibernate根椐以上配置信息獲得如下信息:
<set>元素表明Department類的emps屬性為java.util.Set集合類型.
<class>子元素表明emps集合中存放的是一組Employee對(duì)象
<key>子元素表明employee表是通過(guò)外鍵depart_id參照department表的.
?
?3. 其余的保持原樣,測(cè)試類如下:
Java代碼 ??控制臺(tái)打印信息如下:
Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: select department0_.id as id1_0_, department0_.name as name1_0_ from Department department0_ where department0_.id=?
Hibernate: select emps0_.depart_id as depart3_1_, emps0_.id as id1_, emps0_.id as id2_0_, emps0_.name as name2_0_, emps0_.depart_id as depart3_2_0_ from Employee emps0_ where emps0_.depart_id=?
emp size:2
數(shù)據(jù)庫(kù)中記錄如下所示:
mysql> select * from employee;
+----+-----------------+-----------+
| id | name??????????? | depart_id |
+----+-----------------+-----------+
|? 1 | employee1 name2 |???????? 1 |
|? 2 | employee2 name2 |???????? 1 |
+----+-----------------+-----------+
2 rows in set (0.00 sec)
mysql> select * from department;
+----+-----------------+
| id | name??????????? |
+----+-----------------+
|? 1 | department name |
+----+-----------------+
1 row in set (0.00 sec)
?
雖然對(duì)象模型修改了,但數(shù)據(jù)庫(kù)關(guān)系模型并沒(méi)有改變。
?
如果把測(cè)試程序中注釋部分去掉,同時(shí)將注釋為“建立對(duì)象模型”這兩句程序注釋掉,雖然也能正確運(yùn)行,但控制臺(tái)會(huì)多打印出兩條更新語(yǔ)句,說(shuō)明數(shù)據(jù)庫(kù)多執(zhí)行了兩次更新操作,效率上有影響,如下所示:
Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: update Employee set depart_id=? where id=?
Hibernate: update Employee set depart_id=? where id=?
Hibernate: select department0_.id as id1_0_, department0_.name as name1_0_ from Department department0_ where department0_.id=?
Hibernate: select emps0_.depart_id as depart3_1_, emps0_.id as id1_, emps0_.id as id2_0_, emps0_.name as name2_0_, emps0_.depart_id as depart3_2_0_ from Employee emps0_ where emps0_.depart_id=?
emp size:2
?
4.懶加載分析:
(1)如果將程序中標(biāo)記為1的程序注釋掉,控制臺(tái)打印信息如下:
Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?
此時(shí)只是將Department對(duì)象查詢出來(lái)了,而對(duì)應(yīng)的Employee并沒(méi)有進(jìn)行查詢。
(2)如果將程序中標(biāo)記為1的程序注釋掉,同時(shí)將標(biāo)記為2的前面的注釋去掉,運(yùn)行程序,控制臺(tái)打印信息如下:
Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?
emps class:class org.hibernate.collection.PersistentSet
此時(shí)可以看到其實(shí)Hibernate將hashset替換成了它自己寫(xiě)的PersistentSet,所以才能實(shí)現(xiàn)懶加載功能。同時(shí)可以發(fā)現(xiàn)當(dāng)調(diào)用department.getEmps();hibernate只是獲取了集合代理對(duì)象的引用,它并沒(méi)有去查詢數(shù)據(jù)庫(kù)來(lái)填充集合對(duì)象。你還可以進(jìn)一步測(cè)試來(lái)驗(yàn)證這個(gè)問(wèn)題。如果你將程序中標(biāo)記為1的程序注釋掉,同時(shí)去掉標(biāo)記為3的語(yǔ)句前面的注釋,你會(huì)發(fā)現(xiàn)程序能正常運(yùn)行,但如果去掉標(biāo)記為4的語(yǔ)句前面的注釋,運(yùn)行程序,則會(huì)拋出如下異常:
?org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.reiyen.hibernate.domain.Department.emps, no session or session was closed
(3)當(dāng)進(jìn)行department對(duì)象查詢時(shí),從department的表結(jié)構(gòu)中也不能判斷這個(gè)Department對(duì)象是否有對(duì)應(yīng)的Employee,那為什么它不像一對(duì)一查詢時(shí),也一次性把相關(guān)聯(lián)的對(duì)象查詢出來(lái)呢??這是因?yàn)槿绻麑㈥P(guān)聯(lián)的對(duì)象查詢出來(lái)的話,因?yàn)閿?shù)據(jù)較多,它會(huì)嚴(yán)重影響效率,而不像一對(duì)一時(shí),反正從對(duì)象只有一個(gè),一次性查詢出來(lái)影響也不是太大,所以hibernate就假定你有相對(duì)應(yīng)的Employee,直接創(chuàng)建了一個(gè)集合代理對(duì)象的返回給你(把對(duì)象引用先給你),等你需要數(shù)據(jù)的時(shí)候再去查詢數(shù)據(jù)庫(kù),以提高效率!
?
總結(jié)
以上是生活随笔為你收集整理的hibernate 一对多(one-to-many)双向关联的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: hibernate 多对一(Many-t
- 下一篇: hibernate 一对一(One-to