目錄:
-----configuration
-----sessionFactory
-----session
(session 和factory有個緩存的差别:請參考:
https://blog.csdn.net/qq_36098284/article/details/80086519)
-----transaction
1 configuration
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CXwcmaNRzaE1kMNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jM3MzMyADN1EzMyQDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
預設使用config.configure()的時候,讀取的配置檔案就是hibernate.cfg.xml。
但是configure()的方法有好幾個,可以用于配置自定義的XML檔案。
如果更改了.cfg.xml檔案的名字,那麼相應的config處也要更改。
2 SessionFactory
是以每次要建立一個session的時候,隻需要調用這個工廠類的方法OpenSession即可。
當然還可以把closeSession()方法寫進去。
3 Session
複習下,session有三種狀态 參考:https://blog.csdn.net/qq_36098284/article/details/80072932
3.1 get方法詳解:
Session.load/get方法均可以根據指定的實體類和id從資料庫讀取記錄,并傳回與之對應的實體對象。
get與load的差別:
1.如果未能發現符合條件的記錄,get方法傳回null,而load方法會抛出一個ObjectNotFoundException。
2.load方法可傳回實體的代理類執行個體,而get方法永遠直接傳回實體類。
3.load方法可以充分利用内部緩存和二級緩存中的現有資料,而get方法則僅僅在内部緩存中進行資料查找,如沒有發現對應資料,将越過二級緩存,直接調用SQL完成資料讀取。
Session在加載實體對象時,将經過的過程:
首先,Hibernate中維持了兩級緩存。第一級緩存由Session執行個體維護,其中保持了Session目前所有關聯實體的資料,也稱為内部緩存。而第二級緩存則存在于SessionFactory層次,由目前所有由本SessionFactory構造的Session執行個體共享。出于性能考慮,避免無謂的資料庫通路,Session在調用資料庫查詢功能之前,會先在緩存中進行查詢。首先在第一級緩存中,通過實體類型和id進行查找,如果第一級緩存查找命中,且資料狀态合法,則直接傳回。
之後,Session會在目前“NonExists(把無效的條件寫成一個黑名單,既然無效,那麼也沒必要再查下去)”記錄中進行查找,如果“NonExists”記錄中存在同樣的查詢條件,則傳回null。“NonExists”記錄了目前Session執行個體在之前所有查詢操作中,未能查詢到有效資料的查詢條件(相當于一個查詢黑名單清單)。如此一來,如果Session中一個無效的查詢條件重複出現,即可迅速作出判斷,進而獲得最佳的性能表現。
對于load方法而言,如果内部緩存中未發現有效資料,則查詢第二級緩存,如果第二級緩存命中,則傳回。
如在緩存中未發現有效資料,則發起資料庫查詢操作(Select SQL),如經過查詢未發現對應記錄,則将此次查詢的資訊在“NonExists”中加以記錄,并傳回null。
根據映射配置和Select SQL得到的ResultSet,建立對應的資料對象。
将其資料對象納入目前Session實體管理容器(一級緩存)。
執行Interceptor.onLoad方法(如果有對應的Interceptor)。
将資料對象納入二級緩存。
如果資料對象實作了LifeCycle接口,則調用資料對象的onLoad方法。
傳回資料對象。
get()----不支援LAZY
load()----支援LAZY
load和get一共是2個差別 先講第一個 延遲加載
load是true而get是false
意 思就是 load采用的是延遲加載的方式 而get不是,hibernate思想是 既然這個方法支援延遲加載 他就認為這個對象一定在資料庫存在,在你 聲明 TFaq tfag2=(TFaq)sess.load(TFaq.class, 300); 這句時候,hibernate就幹了一件事
1.查詢session緩存
2.緩存中沒有這個對象 就建立個代理
因為延遲加載需要代理來執行 是以就建立了個代理
ok 到此為止 這句話就幹了個這個 并沒有去資料庫互動查詢
當你使用這個對象 比如tfag2.getTfRtitle()或get方法時候
這個時候 hibernate就去查詢二級緩存和資料庫,資料庫沒有這條資料 就抛出異常
整個load方法調用結束 load沒什麼神奇 這就是他幹過所有的事情
load方法講完了 我在講一下get方法工作原理
因為hibernate規定get方法不能使用延遲加載 是以和load還是不一樣的
TFaq tfag2=(TFaq)sess.get(TFaq.class, 300);
在建立這條語句時候 我們看看hibernate幹了哪些事
1.get方法首先查詢session緩存 (session緩存就是hibernate的一級緩存 這個概念大家應該清楚吧 )
2.get方法如果在session緩存中找到了該id對應的對象,如果剛好該對象前面是被代理過的,如被load方法使用過,或者被其他關聯對象延遲加載過,那麼傳回的還是原先的代理對象,而不是實體類對象。
3.如果該代理對象還沒有加載實體資料(就是id以外的其他屬性資料),那麼它會查詢二級緩存或者資料庫來加載資料,但是傳回的還是代理對象,隻不過已經加載了實體資料。
(這個代理實際就是空的對象 并沒有去資料庫查詢得到的 我們叫代理對象,如果 去資料庫查詢了 傳回到了這個對象 我們叫實體對象 就是這個對象真實存在)
我在總結性一句話這2者差別
get方法首先查詢session緩存,最後查詢資料庫;反而load方法建立時首先查詢session緩存,沒有就建立代理,實際使用資料時才查詢二級緩存和資料庫
參考:https://blog.csdn.net/houjiyu243042162/article/details/27243029
舉例:
3.2 save方法詳解
3.2.1.save(): 把一個臨時對象加入到緩存中,使它變成持久化對象
-->選用映射檔案指定的主鍵生成器為持久化對象配置設定唯一的OID
-->計劃一條insert語句,把參數對象目前的屬性值組裝到insert語句中,但是save()方法并不立即執行SQL insert語句,隻有當Session清理緩存時候才會執行。
-->如果在save()方法之後,又修改了持久化對象的屬性,會使得Session在清理緩存的時候額外執行SQL update語句。
注意:save()方法是用來持久化一個臨時對象的!
如果将一個持久化對象傳給save()方法将不會執行任何操作,多餘的步驟
如果将一個遊離态對象傳給save()方法,session會将它當作臨時對象來處理,再次向資料庫中插入一條記錄,不符合業務需求!
3.2.2舉例
3.3 update方法詳解
3.3.2.update():把Customer對象重新加入到Session緩存中,使之變為持久化對象。
--->計劃一條update語句,隻有在清理緩存的時候才會執行,并且在執行的時候才會把參數對象中的屬性值組裝到update語句中。
注意:update()是将一個遊離對象轉變為持久化對象的。
隻要通過update()方法使遊離對象被一個session關聯,即使沒有修改參數對象的任何屬性,Session在清理緩存的時候也會執行由update方法計劃的Update語句。
3.3.3舉例
相當于select。insert。
3.4.saveOrUpdate詳解
同時包含了save()與update()方法的功能。
如果傳入的參數是臨時對象,調用save方法。
如果參入參數是遊離對象,調用update()方法。
如果傳入的是持久化對象,直接傳回。
3.5.evict與clear詳解
5.1.evict():從緩存中清除參數指定的持久化對象。
适用場合:不希望Session繼續按照該對象的狀态改變來同步更新資料庫。
在批量更新或批量删除的場合,當更新或者删除一個對象後,及時釋放該對象占用的記憶體。當然批量操作優先考慮JDBC.
5.2.clear():清空緩存中所有持久化對象。
3.6.delete詳解
用于從資料庫中删除與參數對象對應的記錄。
如果傳入的參數是持久化對象,Session就計劃執行一個delete語句,如果傳入的參數是遊離對象,先使遊離對象被Session關聯,使它變為持久化對象,然後計劃一個delete語句,在清理緩存的時候執行。
相當于 select 。drop
3.7.queryAll詳解
相當于select。
4. Transation
(此處是對于事務的一個基本了解,深入了解在另一個文章中,參考:https://blog.csdn.net/qq_36098284/article/details/80094923)
隻要try中代碼出現問題進入到catch中,那麼就不會執行commit(),而是去執行rollback()代碼。就相當于回到了session = null 建立那一步。
而且标準的寫法也是必須要有try-catch的。否則會出現資料的錯誤。
事物復原的解釋:
最近在用做hibernate做項目,一直不明白session.beginTransaction().commit() 和 session.beginTransaction().rollback(); 有什麼差別
一組業務整體處理的行為叫一個事務。這一組的業務都能成功處理,我們就可以把這個事務送出來儲存你已做的行為結果。但如果一組中有任何的差錯出現的話,我們就認為這事務不成功,需要復原來撤消之前的操作。
舉例:你去銀行轉賬,轉賬我們有兩步吧,從你賬戶中取出錢再往他賬戶中加錢。那這兩步銀行是必須要確定正确無誤的進行的。要被看做成一個事務。其中任何一步出錯就算是轉賬失敗,但可能你這時是已經從你賬戶中扣了錢了,又沒往他賬戶裡加錢?怎麼辦算了?你不肯吧。是以銀行會事務復原,不儲存你剛才的操作,即恢複到你沒轉賬之前的狀态。
參考:https://www.cnblogs.com/demongao/p/6053853.html
參考:https://blog.csdn.net/qq_33642117/article/details/52008152