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