Session 中的快取機制
Session介面是Hibernate嚮應用程式提供的操縱資料庫的最主要的介面,它提供了基本的儲存、更新、刪除和查詢方法。Session具有一個快取,位於快取中的物件處於持久化狀態,它和資料庫中的相關記錄對應,Session能夠在某些時間點,按照快取中持久化物件的屬性變化來同步更新資料庫,這一過程被稱為清理快取。
處理持久化狀態,物件還能處於遊離狀態和臨時狀態,Session的特定方法能使物件從一個狀態轉換到另一個狀態。
一、Java物件在JVM中的生命週期
當應用程式通過new語句建立一個Java物件時,JVM會為這個物件分配一塊記憶體空間,只要這個物件被引用變數引用,它就一直存在於記憶體中。如果這個物件不被任何引用變數引用,它就結束生命週期,此時
二、理解Session的快取
如果希望一個Java物件一直處於生命週期中,就必須保證至少有一個變數引用它,或者在一個Java集合中存放了這個物件的引用。在Session介面的實現類SessionImpl中定義了一系列的Java集合,這些Java集合構成了Session的快取。
Session快取的三大作用:
1、減少訪問資料庫的頻率。從而提高資料訪問的效能。
2、保證快取中的物件與資料庫中的相關記錄保持同步。位於快取中的物件被稱為持久化物件。當快取中的物件的狀態發生了變換,Session並不會立即執行相應的SQL於戶,這使得Session
3、當快取中的持久化物件之間存在迴圈關聯關係時,Session會保證不出現訪問物件圖的死迴圈,以及由於死迴圈引起的JVM棧溢位異常。
注:當Session載入了物件後,會為物件的值型別的屬性賦值一份快照。當Session清理快取時,通過比較物件的當前屬性和它的快照,Session能夠判斷物件的哪些屬性發生了變化。
Session在清理快取時,按照以下順序執行SQL語句。
l按照應用程式呼叫session.save()方法的先後順序,執行所有對實體進行插入的insert語句。
l執行所有對實體進行更新的
l執行所有對集合進行刪除的delete語句。
l執行所有對集合元素進行刪除、更新或者插入的SQL語句。
l執行所有對集合進行插入的insert語句。
l按照應用程式呼叫session.delete()方法的先後順序,執行所有對實體進行刪除的delete語句。
在預設情況下,Session會在下面的時間點清理快取。
l當應用程式呼叫net.sf.hibernate.Transaction的commit()方法的時候,commit()方法先清理快取,然後在向資料庫提交事務。
l當應用程式呼叫Session的find()或者iterate()時,如果快取中持久化物件的屬性發生了變化,就會先清理快取,以保證查詢結果能能反映持久化物件的最新狀態。
l當應用程式顯式呼叫Session的flush()方法的時候。
Session進行清理快取的例外情況是,如果物件使用native生成OID,那麼當呼叫Session的save()儲存該物件時,會立即執行向資料庫插入實體的 insert語句。
注:Session的commit()和flush()方法的區別。flush方法進行清理快取的操作,執行一系列的SQL語句,但不會提交事務;commit方法會先呼叫flush方法,然後提交事務。提交事務意味著對資料庫所作的更新被永久儲存下來。
Session的setFlushMode()方法用於設定清理快取的時間點。
清理快取的模式 |
Session的查詢方法 |
Session的commit() |
Session的flush() |
FlushMode.AUTO |
清理 |
清理 |
清理 |
FlushMode.COMMIT |
不清理 |
清理 |
清理 |
FlushMode.NEVER |
不清理 |
不清理 |
清理 |
AUTO時預設值,這也是優先考慮的清理模式,他會保證在整個事務中,資料保持一致。如果事務僅包含查詢資料庫的操作,而不會修改資料庫的資料,也可以選COMMIT模式,這可以避免在執行Session的查詢方法時先清理快取,以稍微提高應用程式的效能。
在多說情況下,應用程式不需要顯式呼叫Session的flush方法,flush方法適用於以下場合。
A、插入、刪除或更新某個持久化物件會引發資料庫中的觸發器。
B、在應用程式中混合使用Hibernate API和JDBC API。
C、JDBC驅動程式不健壯,導致Hibernate在自動清理快取的模式下無法正常工作。
三、在Hibernate應用中Java物件的狀態
對於需要持久化的Java物件,在它的生命週期中,可處於以下三個狀態之一。
l臨時狀態(transient):剛剛用new語句建立,還沒有被持久化,不處於Session的快取中。處於臨時狀態的Java物件被稱為臨時物件。
l持久化狀態(persistent):已經被持久化,加入到Session的快取中。處於持久化狀態的Java物件被稱為持久化物件。
l遊離狀態(detached):已經被持久化,但不在處於Session的快取中。處於遊離狀態的Java物件被稱為遊離物件。
注:持久化類與持久化物件是不同的概念。持久化類的例項可以處於臨時狀態、持久化狀態和遊離狀態,其中處於持久化狀態的例項被稱為持久化物件。
1、臨時物件的特徵
不處於Session的快取中(不被任何一個Session例項關聯);在資料庫中沒有對應的記錄。
以下情況下,Java物件進入臨時狀態:
A、當new語句剛剛建立物件;
B、Session的delete()方法能使一個持久化物件或遊離物件轉變為臨時物件。
2、持久化物件的特徵
位於一個Session例項的快取中;持久化物件和資料庫中的相應記錄對應;Session在清理快取時,會根據持久化物件的屬性變化,來同步更新資料庫。
Session的許多方法能觸發Java物件轉變為持久化物件:
A、save把臨時轉為持久化狀態;
B、load或get返回的物件總處於持久化狀態;
C、find返回的List集合中存放的都是持久化物件;
D、update、saveOrUpdate和lock方法使遊離物件轉變為持久化物件;
E、當一個持久化物件關聯一個臨時物件,在允許級聯儲存的情況下,清理快取時會把臨時物件轉化為持久化物件。
3、遊離物件的特徵
不再位於Session的快取中;遊離物件是由持久化物件轉變過來的,因此再資料庫中可能存在與它對應的記錄(前提是沒有其他程式刪除這條記錄)。
Session的以下方法使持久化物件轉變為遊離物件:
A、close方法,快取被清理空,所有持久化物件都變為於哦裡物件;
B、evict方法能夠從快取中刪除一個持久化物件。
四、Session的儲存、更新、刪除和查詢方法
1、Session的save方法
使一個臨時的物件轉變為持久化物件。
Session的save方法完成以下操作:
A、把物件加入到快取中,使它變為持久化物件。
B、選用對映檔案指定的識別符號生成器為持久化物件分配唯一的OID。
C、計劃執行一個insert語句,把物件當前的屬性值組裝到insert語句中。
值得注意的是,save方法並不立即執行SQL insert語句。只有當Session清理快取時,才會執行語句。
Session的save方法是用來持久化一個臨時物件的。再應用中,不應該把持久化物件或遊離物件傳給save方法。
2、Session的update方法
使一個遊離物件轉變為持久化物件。
Session的update方法完成以下操作:
A、把物件重新加入到Session的快取中,使它變為持久化物件。
B、計劃執行一個update語句。(不立即執行,清楚快取執行)
3、Session的saveOrUpdate方法
同時包含了save和update方法的功能,如果傳入的引數是臨時物件,就呼叫save方法;如果傳入的引數是遊離物件,就呼叫update方法;如果傳入的引數是持久化物件,那就直接返回。
4、Session的load和get方法
根據給定的OID從資料庫中載入一個持久化物件,這兩個方法的區別在於:當資料庫中不存在與OID對應的記錄時,load方法丟擲異常,而get方法返回null。
5、Session的delete方法
在資料庫中刪除與Java物件對應的記錄。如果傳入的引數時持久化物件,Session就計劃執行一個delete語句。如果傳入的引數時遊離物件,先是的遊離物件被Session關聯,使它變為持久化物件,然活計劃執行一個delete語句。