NHibernate 状态的概念 以及 小测试
在?NHibernate中有三種狀態。
?
- 臨時態(Transient):用new創建的對象,它沒有持久化,沒有納入Session中,隨時可以被垃圾回收,處于此狀態的對象叫臨時對象。特點:數據庫中沒有與之對應的記錄;
- 持久態(Persistent):已經持久化,加入到了Session緩存中。通過NHibernate保存的對象或通過Get/Load等方法獲取出的對象,其對象沒有脫離Session的管理,處于此狀態的對象叫持久對象;
- 游離態(Detached):持久化對象脫離了Session的對象。如Session緩存被清空的對象。特點:已經持久化,但不在Session緩存中。處于此狀態的對象叫游離對象;
?
?
?臨時態(Transient)到持久態(Persistent)
?
先new一個對象,該對象的狀態為Transient,然后調用Save()方法將該對象持久化到數據庫中,該對象的狀態變為Persistent。在未關閉Session前,修改該對象的屬性,最后提交事務。
?
1 /// <summary> 2 /// 臨時態-->持久態 3 /// </summary> 4 [Test] 5 public void TransientToPersistentTest() 6 { 7 using (ISession session = this.sessionFactory.OpenSession()) 8 { 9 using (ITransaction tran = session.BeginTransaction()) 10 { 11 //Transient 12 var product = new Product 13 { 14 ID = Guid.NewGuid(), 15 BuyPrice = 10M, 16 Code = "ABC123", 17 Name = "電腦", 18 QuantityPerUnit = "20x1", 19 SellPrice = 11M, 20 Unit = "臺" 21 22 }; 23 24 try 25 { 26 //Persistent 27 session.Save(product); 28 29 //保存記錄后修改數據,觀察數據庫中數據的變化 30 product.SellPrice = 12M; 31 32 tran.Commit(); 33 } 34 catch (Exception ex) 35 { 36 tran.Rollback(); 37 throw ex; 38 } 39 } 40 } 41 }?
這時,我們心里便產生了一個疑問:把Product的SellPrice屬性從“11M”修改為“12M”后,并沒有調用Save()或者Update()的方法,為什么數據庫中的數據會變呢?
這是因為,當對象處于Persistent狀態,并沒有脫離Session管理時,其屬性發生改變后,數據庫相對應的記錄會與之同步。
?
?
?
持久態(Persistent)到游離態(Detached),再到持久態(Persistent)
?
1 /// <summary> 2 /// 持久態-->游離態-->持久態 3 /// </summary> 4 [Test] 5 public void PersistentToTestDetached() 6 { 7 //Transient 8 var product = new Product 9 { 10 ID = Guid.NewGuid(), 11 BuyPrice = 10M, 12 Code = "ABC123", 13 Name = "電腦", 14 QuantityPerUnit = "20x1", 15 SellPrice = 11M, 16 Unit = "臺" 17 }; 18 19 using (ISession session = this.sessionFactory.OpenSession()) 20 { 21 using (ITransaction tran = session.BeginTransaction()) 22 { 23 try 24 { 25 //Persistent 26 session.Save(product); 27 product.SellPrice = 12M; 28 29 tran.Commit(); 30 } 31 catch (Exception ex) 32 { 33 tran.Rollback(); 34 throw ex; 35 } 36 } 37 } 38 39 //Detached 40 product.SellPrice = 13M; 41 42 using (ISession session = this.sessionFactory.OpenSession()) 43 { 44 using (ITransaction tran = session.BeginTransaction()) 45 { 46 try 47 { 48 //Persistent 49 session.Update(product); 50 tran.Commit(); 51 } 52 catch (Exception ex) 53 { 54 tran.Rollback(); 55 throw ex; 56 } 57 } 58 } 59 }?
?
?
當對象處于游離態(Detached)時,修改其屬性,是不會與數據庫發生同步的。調用Update()方法后,對象則變回持久態(Persistent)。
?
Get方法得到持久態(Persistent)
?
1 [Test] 2 public void PersistentToTestDetached() 3 { 4 //Transient 5 string ID1 = Guid.NewGuid().ToString(); 6 var product = new Product 7 { 8 ID = ID1, 9 BuyPrice = 10M, 10 Code = "ABC123", 11 Name = "電腦", 12 QuantityPerUnit = "20x1", 13 SellPrice = 11M, 14 Unit = "臺" 15 }; 16 17 using (ISession session = this.sessionFactory.OpenSession()) 18 { 19 using (ITransaction tran = session.BeginTransaction()) 20 { 21 try 22 { 23 //Persistent 24 session.Save(product); 25 product.SellPrice = 12M; 26 27 tran.Commit(); 28 } 29 catch (Exception ex) 30 { 31 tran.Rollback(); 32 throw ex; 33 } 34 } 35 } 36 37 //Detached 38 39 40 using (ISession session = this.sessionFactory.OpenSession()) 41 { 42 using (ITransaction tran = session.BeginTransaction()) 43 { 44 try 45 { 46 //Persistent 47 product=session.Get<Product>(ID1);//Get可與Load互換 48 product.SellPrice = 18M; 49 tran.Commit(); 50 } 51 catch (Exception ex) 52 { 53 tran.Rollback(); 54 throw ex; 55 } 56 } 57 } 58 }?
其中ID1為數據庫中已存在的一條數據的主鍵值。在得到持久化對象后,我們便可以更改數據庫的值。
?
?
?
?Get和Load()方法的區別
?
Load:
- Load方法可以對查詢進行優化。
- Load方法實際得到一proxy對象,并不立即查詢數據庫。當訪問對象的屬性的時候才查詢數據庫。在NHibernate里稱為Lazy Loding(延遲加載)。
- Load方法得到的對象,如果對象不存在,在訪問對象的屬性時將拋出異常。
- 當需要得到實體對象,但是不需要訪問對象屬性的時候,宜使用Load方法。比如Delete方法:
? ?調用Load()方法查詢數據庫中不存在的對象,返回值不為空;當調用Load()方法時,不立刻產生SQL語句,查看其屬性后才產生SQL語句,并且查看數據庫中不存在對象的屬性時會拋出異常。原因是調用Load()方法會返回一個“代理類”,這是NHibernate的一個重要的特性——延遲加載。
延遲加載(lazy load)也叫“懶加載”,是NHibernate關聯關系對象默認的加載方式,延遲加載機制是為了避免一些無謂的性能開銷而提出來的,所謂延遲加載就是當在真正需要數據的時候,才真正執行數據加載操作。可以簡單理解為,只有在使用的時候,才會發出SQL語句進行查詢。 延遲加載的有效期是在Session打開的情況下,當Session關閉后,會報異常。NHibernate的代理對象是由第三方組件“Antlr3.Runtime”提供的。
?
?
?
Get:
- Get方法立即查詢數據庫,如果對象不存在,返回null。
- 調用Get()方法后,數據庫中不存在的對象返回值為null,并且一但調用Get()方法,就會生成SQL語句。
?
?
?
?
?
Update()方法
?
先手動打造new一個數據庫中存在的游離態(Detached)對象,然后直接調用Update()方法將對象的狀態設置為持久態(Persistent)。
?
1 [Test] 2 public void UpdateTest() 3 { 4 Guid id = Guid.NewGuid(); 5 6 using (ISession session = this.sessionFactory.OpenSession()) 7 { 8 using (ITransaction tran = session.BeginTransaction()) 9 { 10 //Transient 11 var product = new Product 12 { 13 ID = id, 14 BuyPrice = 10M, 15 Code = "ABC123", 16 Name = "電腦", 17 QuantityPerUnit = "20x1", 18 SellPrice = 11M, 19 Unit = "臺" 20 21 }; 22 23 try 24 { 25 //Persistent 26 session.Save(product); 27 tran.Commit(); 28 } 29 catch (Exception ex) 30 { 31 tran.Rollback(); 32 throw ex; 33 } 34 } 35 } 36 37 using (ISession session = this.sessionFactory.OpenSession()) 38 { 39 using (ITransaction tran = session.BeginTransaction()) 40 { 41 //Detached 42 var product = new Product 43 { 44 ID = id, 45 Code = "ABC456", 46 }; 47 48 try 49 { 50 //Persistent 51 session.Update(product); 52 53 tran.Commit(); 54 } 55 catch (Exception ex) 56 { 57 tran.Rollback(); 58 throw ex; 59 } 60 } 61 } 62 }?
有的朋友就會問,為什么new的時候也能得到游離態(Detached)對象?因為判斷是否為游離態(Detached)對象,是根據數據庫中是否存在與之對應的記錄定奪的。
?
?Delete()方法
?
?
先得到一個持久態(Persistent)對象,然后調用Delete()方法刪除該對象,這時該對象變回臨時態(Transient)
?
1 [Test] 2 public void DeleteTest() 3 { 4 using (ISession session = this.sessionFactory.OpenSession()) 5 { 6 using (ITransaction tran = session.BeginTransaction()) 7 { 8 //Transient 9 var product = new Product 10 { 11 ID = Guid.NewGuid(), 12 BuyPrice = 10M, 13 Code = "ABC123", 14 Name = "電腦", 15 QuantityPerUnit = "20x1", 16 SellPrice = 11M, 17 Unit = "臺" 18 19 }; 20 21 try 22 { 23 //Persistent 24 session.Save(product); 25 26 //Transient 27 session.Delete(product); 28 29 tran.Commit(); 30 } 31 catch (Exception ex) 32 { 33 tran.Rollback(); 34 throw ex; 35 } 36 } 37 } 38 }?
?
?
?
?
學習于? ? ??http://www.cnblogs.com/GoodHelper/archive/2011/02/17/nhibernate_04.html
轉載于:https://www.cnblogs.com/cwmizlp/p/9208291.html
總結
以上是生活随笔為你收集整理的NHibernate 状态的概念 以及 小测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小例二
- 下一篇: window下tomcat的内存溢出问题