在面向對象的開發中,程序的運行都是通過對象的方式對數據庫進行增刪改查的操作,必然在持久化過程中產生一些列的對象,比如登陸,必然會有實例化的UserEntity對象,從數據庫Select出來的對象,Save到數據庫的對象,如何區分這些對象以及當前會話的狀態,下面看NHibernate中的對象狀態的管理:
Nhibernate在持久化對象的生命周期,將對象分為三個狀態:
也叫臨時態,顧名思義,對象是臨時創建的,即剛實例化的對象:
UserEntityenUser = new UserEntity();
這個enUser對象現在就處于瞬時態,因為此時只是給enUser對象分配了一塊內存空間,還沒有進入Nhibernate的Session緩存,更沒有持久化到數據庫。
瞬時對象特點:
對象在數據庫沒有記錄,也不和Session關聯。
瞬時對象被保存到數據庫或者從數據庫查詢來的對象,并且還在Session管理中的對象。
瞬時對象轉化為持久對象:(1)通過Session的Save()和SaveOrUpdate()方法將瞬時對象持久化到數據庫,(2)通過Get(),Load()等查詢方法查詢到數據對象。
持久化對象的特點:
對象與數據庫中記錄同步,并且數據變更處于Session的管理之下。
由持久態轉換而來,在與持久化對象關聯的Session被關閉后,對象就變成游離態,但是還擁有持久化對象的所有屬性。
游離對象的特點:
和瞬時對象一樣,都沒有處于Session關聯。不同的是游離對象是經過持久化的對象,在數據庫中有記錄。
以上簡單的介紹了Nhibernate持久化的三個狀態,在持久化對象的生命周期內,這三個狀態并不是孤立的,它們之間存在的相互轉換的過程:
狀態分析:
//瞬時態對象
UserEntity enUser = new UserEntity();
enUser.name = "yiming";
//關聯Session,調用Save(enUser)持久化到數據庫,狀態變為持久態,但是還沒有更新到數據庫,需要在進行flush()。
Session.Save(enUser);
enUser.name = "liuming";
Session.Save(enUser); //無效
//將session的緩存中的數據與數據庫同步,關閉Session
Session.Flush();
說明:當執行持久化操作時,持久化操作并沒有立即執行(更新到數據庫),而是被記錄下來,直到Session.Flush時才會實際更新到數據庫,這樣做的原因很容易理解,就是為了避免頻煩的數據庫連接操作。如果沒有調用Flush而關閉了會話,當前會話中的持久對象將不會持久化!并且對已經持久化的對象調用Save()或者Update()是沒有意義的。
持久態轉換成游離態就是一個清理Session的過程,通常不會手動去調用evict(),close(),clear()這些圖中列出的方法,而是由Nhibernate去管理,清理的時機:
1、commit() 方法被調用時。
2、查詢時會主動commit清理緩存,保證查詢結果能反映對象的最新狀態。
3、調用session.flush()方法。
以update()方法為例:
Session.Update(enUser);
如果enUser是持久化對象,那么不進行任何操作,即可以同步到數據庫。如果enUser是游離對象,那么就必須先轉為持久對象,然后再同步到數據庫。所以Update的時候也會發出select語句。
其他的方法不再一一說明,其實只要明白了這三種狀態以及轉換過程,結合我們以前通過sql語句的實現(因為Nhibernate的這些方法最終還是通過sql語句去操作數據庫的)的經驗去考慮,就很容易理解。
一個月的開發,在投訴系統中遇到最多的問題就是調用底層Save,Update,SaveOrUpdate方法,以及在級聯操作的過程中的問題,由于對這三個狀態的不了解,錯誤不斷,完全是一個方法一個方法的嘗試,也摸索到了一些規律,再加上這次的學習對Nhibernate的三態更清晰了。
本文也一直在出現一個詞Session,這個詞都不陌生,但Nhibernate的Session是我們之前用到Session嗎,在Nhibernate中的作用是什么,帶著問題進入下一篇(NHibernate 緩存機制)