一。 inverse = ?
inverse=false(default)
用于單向one-to-many關(guān)聯(lián)
parent.getChildren().add(child) // insert child
parent.getChildren().delete(child) // delete child
inverse=true
用于雙向one-to-many關(guān)聯(lián)
child.setParent(parent); session.save(child) // insert child
session.delete(child)
在分層結構的體系中
parentDao, childDao對于CRUD的封裝導致往往直接通過(guò)session接口持久化對象,而很少通過(guò)關(guān)聯(lián)對象可達性
二。 one-to-many關(guān)系
單向關(guān)系還是雙向關(guān)系?
parent.getChildren().add(child)對集合的觸及操作會(huì )導致lazy的集合初始化,在沒(méi)有對集合配置二級緩存的情況下,應避免此類(lèi)操作
select * from child where parent_id = xxx;
性能口訣:
1. 一般情況下避免使用單向關(guān)聯(lián),盡量使用雙向關(guān)聯(lián)
2. 使用雙向關(guān)聯(lián),inverse=“true”
3. 在分層結構中通過(guò)DAO接口用session直接持久化對象,避免通過(guò)關(guān)聯(lián)關(guān)系進(jìn)行可達性持久化
三。many-to-one關(guān)系
單向many-to-one表達了外鍵存儲方
靈活運用many-to-one可以避免一些不必要的性能問(wèn)題
many-to-one表達的含義是:0..n : 1,many可以是0,可以是1,也可以是n,也就是說(shuō)many-to-one可以表達一對多,一對一,多對一關(guān)系
因此可以配置雙向many-to-one關(guān)系,例如:
1. 一桌四人打麻將,麻將席位和打麻將的人是什么關(guān)系?是雙向many-to-one的關(guān)系
四。one-to-one
通過(guò)主鍵進(jìn)行關(guān)聯(lián)
相當于把大表拆分為多個(gè)小表
例如把大字段單獨拆分出來(lái),以提高數據庫操作的性能
Hibernate的one-to-one似乎無(wú)法lazy,必須通過(guò)bytecode enhancement
五。集合List/Bag/Set
one-to-many
1. List需要維護index column,不能被用于雙向關(guān)聯(lián),必須inverse=“false”,被謹慎的使用在某些稀有的場(chǎng)合
2. Bag/Set語(yǔ)義上沒(méi)有區別
3. 我個(gè)人比較喜歡使用Bag
many-to-many
1. Bag和Set語(yǔ)義有區別
2。 建議使用Set
六。集合的過(guò)濾
1. children = session.createFilter(parent.getChildren(), “where this.age > 5 and this.age < 10”).list()
針對一對多關(guān)聯(lián)當中的集合元素非常龐大的情況,特別適合于龐大集合的分頁(yè):
session.createFilter(parent.getChildren(),“”).setFirstResult(0).setMaxResults(10).list();
七。繼承關(guān)系當中的隱式多態(tài)
HQL: from Object
1. 把所有數據庫表全部查詢(xún)出來(lái)
2. polymorphism=“implicit”(default)將當前對象,和對象所有繼承子類(lèi)全部一次性取出
3. polymorphism=“explicit”,只取出當前查詢(xún)對象
八。Hibernate二級緩存
著(zhù)名的n+1問(wèn)題:from Child,然后在頁(yè)面上面顯示每個(gè)子類(lèi)的父類(lèi)信息,就會(huì )導致n條對parent表的查詢(xún):
select * from parent where id = ?
.......................
select * from parent where id = ?
解決方案
1. eager fetch
2. 二級緩存
九。inverse和二級緩存的關(guān)系
當使用集合緩存的情況下:
1. inverse=“false”,通過(guò)parent.getChildren()來(lái)操作,Hibernate維護集合緩存
2. inverse=“true”,直接對child進(jìn)行操作,未能維護集合緩存!導致緩存臟數據
3. 雙向關(guān)聯(lián),inverse=“true”的情況下應避免使用集合緩存
十。Hibernate二級緩存是提升web應用性能的法寶
OLTP類(lèi)型的web應用,由于應用服務(wù)器端可以進(jìn)行群集水平擴展,最終的系統瓶頸總是逃不開(kāi)數據庫訪(fǎng)問(wèn);
哪個(gè)框架能夠最大限度減少數據庫訪(fǎng)問(wèn),降低數據庫訪(fǎng)問(wèn)壓力, 哪個(gè)框架提供的性能就更高;針對數據庫的緩存策略:
1. 對象緩存:細顆粒度,針對表的記錄級別,透明化訪(fǎng)問(wèn),在不改變程序代碼的情況下可以極大提升web應用的性能。對象緩存是ORM的制勝法寶。
2. 對象緩存的優(yōu)劣取決于框架實(shí)現的水平,Hibernate是目前已知對象緩存最強大的開(kāi)源ORM
3. 查詢(xún)緩存:粗顆粒度,針對查詢(xún)結果集,應用于數據實(shí)時(shí)化要求不高的場(chǎng)合
十一。應用場(chǎng)合決定了系統架構
一、是否需要ORM
Hibernate or iBATIS?
二、采用ORM決定了數據庫設計
Hibernate:
傾向于細顆粒度的設計,面向對象,將大表拆分為多個(gè)關(guān)聯(lián)關(guān)系的小表,消除冗余column,通過(guò)二級緩存提升性能(DBA比較忌諱關(guān)聯(lián)關(guān)系的出現,但是ORM的緩存將突破關(guān)聯(lián)關(guān)系的性能瓶頸);Hibernate的性能瓶頸不在于關(guān)聯(lián)關(guān)系,而在于大表的操作
iBATIS:
傾向于粗顆粒度設計,面向關(guān)系,盡量把表合并,通過(guò)表column冗余,消除關(guān)聯(lián)關(guān)系。無(wú)有效緩存手段。iBATIS的性能瓶頸不在于大表操作,而在于關(guān)聯(lián)關(guān)系。
性能口訣
1、使用雙向一對多關(guān)聯(lián),不使用單向一對多
2、靈活使用單向多對一關(guān)聯(lián)
3、不用一對一,用多對一取代
4、配置對象緩存,不使用集合緩存
5、一對多集合使用Bag,多對多集合使用Set
6、繼承類(lèi)使用顯式多態(tài)
7、表字段要少,表關(guān)聯(lián)不要怕多,有二級緩存撐腰
聯(lián)系客服