Hibernate 的三種狀態 持久化 遊離 臨時 的關係

臨時(Transient) - 由new操做符建立,且還沒有與Hibernate Session 關聯的對象被認定爲臨時(Transient)的。臨時(Transient)對象不會被持久化到數據庫中,也不會被賦予持久化標識(identifier)。 若是臨時(Transient)對象在程序中沒有被引用,它會被垃圾回收器(garbage collector)銷燬。 使用Hibernate Session能夠將其變爲持久(Persistent)狀態。(Hibernate會自動執行必要的SQL語句)

持久(Persistent) - 持久(Persistent)的實例在數據庫中有對應的記錄,並擁有一個持久化標識(identifier)。 持久(Persistent)的實例多是剛被保存的,或剛被加載的,不管哪種,按定義,它存在於相關聯的Session做用範圍內。 Hibernate會檢測處處於持久(Persistent)狀態的對象的任何改動,在當前操做單元(unit of work)執行完畢時將對象數據(state)與數據庫同步(synchronize)。 開發者不須要手動執行UPDATE。將對象從持久(Persistent)狀態變成瞬時(Transient)狀態一樣也不須要手動執行DELETE語句。

遊離(Detached) - 與持久(Persistent)對象關聯的Session被關閉後,對象就變爲遊離(Detached)的。 對遊離(Detached)對象的引用依然有效,對象可繼續被修改。遊離(Detached)對象若是從新關聯到某個新的Session上, 會再次轉變爲持久(Persistent)的(在Detached其間的改動將被持久化到數據庫)。 這個功能使得一種編程模型,即中間會給用戶思考時間(user think-time)的長時間運行的操做單元(unit of work)的編程模型成爲可能。 咱們稱之爲應用程序事務,即從用戶觀點看是一個操做單元(unit of work)。
Hibernate中對象的遊離狀態是指Session關閉以後,持久化對象變成離線對象,離線對象就不能同數據庫同步,也再也不受Hibernate管理。操做 處於遊離態對象 常常會報 session已關閉的錯誤。

舉例
有兩個類, Team, Person. 映射關係是Team一對多Person, 採用lazy fetch策略。
session begin
Team t = *Dao.get()
session end
t.getPersons()// 出錯
若是是用spring管理session的狀況,事務外操做t.getPerons()也跟上面狀況同樣。
這種狀況在生產環境多表現爲在jsp頁面操做 t對象時出錯。
解決方法:
1. 取消lazy fetch策略
缺點:會致使過多的數據庫訪問,由於是一對多的狀況。
2. 在事務內就先把關聯的對象取出
缺點:會致使service層方法不統一,由於要分開取出與不取出的狀況。
3. 使用spring的 openSessionInview機制
缺點: session打開的時間比較長, 使用很差可能會致使out of memory

一個遊離態的對象轉換爲持久戰態,有如下幾種方法:
一、session.saveOrUpdate(object)。這語句會把遊離態的PO轉爲持久態的PO並提交給數據庫
二、session.merge(object)。這語句會把遊離態的PO轉爲持久態的PO,並進行合併操做。
三、session.lock(object, LockMode.NONE)。這語句只會把遊離態的PO轉爲持久態PO,不做其餘操做。不過,PO必須是沒有修改過的,這方法挺適合作一個應用層。spring

相關文章
相關標籤/搜索