不知不覺,已經1年半沒碰hibernate了,東西愈來愈多,愈來愈雜.感受人也愈來愈浮躁.也該是時候沉靜下來進行消化了.sql
對於hibernate,正如本身對ddd的認識同樣,從一開始的驚爲天人,無比推崇,再到複雜的實際應用時落入陷阱,開始疑惑--懷疑--抱怨--拋棄 --走向另外一極端(好比去研究使用ibatis),最後經歷種種溝壑,時間的沉澱讓本身可以以一種平和的眼光看待這些所謂的"人云亦云""看上去很完美" 的東西,終於發現,脫離實際單純地抱着技術的眼光去看待任何一門學問,都是片面的膚淺的.存在即合理,刀可用來作菜,也可用來殺人,所用何途全在使用者的 一念之間.所謂破然後立,大道至簡,也許本身還遠遠未到這個層次,可是卻不再會被一項技術所迷惑.特此總結以下: 數據庫
1.Session是本次請求使用到的持久對象的容器,並在其中使用jdbc的Connection派發sql緩存
2.Session的生命週期的管理:究竟是在1次數據庫操做之間打開,仍是選擇在1次完整的請求過程當中一直打開(即osiv),決定了應該使用哪些抓取策略以及優化措施.(我的以爲理解這一條是可否能用好hibernate的前提)服務器
3.hibernate做爲一款優秀的ORM框架,可以徹底支持複雜的領域模型到不匹配的數據庫模式的映射:如類表模式/嵌入值模式/類映射到多張表/繼承的映射,解決關鍵字:組件映射,繼承映射網絡
4.hierbnate的缺點:查詢老是加載一個對象的全部列,而屬性延遲加載須要運行字節碼加強器.解決關鍵字:類/表/列拆分session
5.所謂的查詢性能/n+1查詢問題:在默認的狀況下由於延遲加載子對象/集合,經過父象查詢子對象時須要先經過1條sql返回要查詢的主體對象(列表),再根據關聯外鍵id,每個對象發一個select查詢,獲取關聯的對象,造成n+1次查詢併發
解決關鍵字:抓取策略/主動加載/緩存框架
5-1.fetch=join 使用外鏈接形式經過1條sql獲取父/子表數據性能
5-2.fetch=subselect 使用1句select xxx from 子表 where 子表外鍵id in(select 主表id from 主表)的相關子查詢,使得遍歷多個父對象的子對象集合時只須要發送1條SQLfetch
5-3.batch-size=xx 子查詢抓取的變種 原理相同
5-4.與主動加載相矛盾的是,若是要使被加載的數據命中cache,則不能使用主動加載
6.若是session生命週期只在1次數據庫操做之間,5-1是最爲合適的主動加載方式.若是可以保持session一直打開,如osiv,那麼5-2,5-3能夠在默認的抓取策略即fetch=select也即lazy=true的基礎上做爲補充方式
7.靜態配置抓取策略(即在配置文件中指定)的做用範圍:get/load/criteria條件查詢,而在hql中則必須經過fetch join關鍵字才能使用鏈接主動加載,若是隻有join沒有fetch,則雖然鏈接可是不會獲得子表數據
8.動態設置抓取策略(setFetchModel(FetchModel.xx))優先級高於靜態配置,便可以在QBC查詢中經過設置 FetchModel而使配置文件中的靜態配置失效.而全部抓取策略優先於預約義的lazy策略(即默認的fetch=select),即一旦經過靜態或 動態修改默認抓取策略後lazy=xx的配置就不會起做用
9.使用DetachedCriteria時,可能會由於API實現中沒有public Criteria createAlias(String associationPath, String alias, int joinType) throws HibernateException 這個方法而致使使用別名後沒法使自定義抓取策略生效
10.綜上所述,若是將session交給sping管理,在默認配置狀況下,延遲加載就等於沒有加載(可能須要顯示地在HibernateCallback的回調方法中實現+1查詢).解決:參考5,6
11.OSIV的缺陷:併發大且網絡阻塞(頁面的輸出時間即out.print的時間過長致使filter阻塞)會形成數據庫鏈接一直被佔用(雖然 事務已提交可是鏈接一直沒有放回池中)而致使鏈接池資源不足.同時因爲session得不到及時釋放也會致使session級緩存佔用JVM內存至關長一 段時間.解決:增長鏈接池數量/用包裝器包裝response輸出頁面後當即顯示關閉SESSION/服務器提供NIO/AIO支持
12.inverse和cascade:inverse指定誰來維護"關係"(表示是否把對set的改動反映到數據庫中 去.inverse=false————反映;inverse=true————不反映.inverse屬性默認爲false).cascade則簡化了 在代碼中的級聯更新和刪除.通常在雙向關聯的一對多中,在父對象集合屬性上面設置cascade=all或all-delete-orphan以及 inverse="true"(many-to-many中能夠在任意一端設置inverse="true"),而在子對象中設置 cascade=none.即(下面這段是引用的,我的以爲說得很好):
老爸能夠有多個孩子,一個孩子不能有多個老爸,並且老爸說的算, 孩子圍着老爸轉。
因此Photos老爸要有權力因此 cascade 這個關鍵字都是送給老爸的, 也就是級聯更新,
老爸改姓了,兒子也得跟着改,呵呵。「否則,就沒有零花錢咯」。
而Picture兒子總體捱罵,可是仍是要維護父子之間良好的關係,對老爸百依百順,所
以老爸就說,兒子,「關係,由你來維護(inverse="true") ,否則就不給零花錢。呵。」。
13.關於session.flush():清空緩存時執行SQL操做數據庫的順序 save-->update-->delete(在1次事務中屢次執行save/update/delete時應注意這點並正確地使用 session.flush同步緩存數據到數據庫以便確保多個操做按正確的順序執行)
14...
暫時想到這麼多,未完待續......