標籤:style c class blog code java
相關資料:
http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html
問題的提出:
1.消極式載入,可能會引起session已經關閉的異常,例如:
當實現消極式載入,當需要Orders時,會通過session去查詢,session。但此時,由於session已經關閉,
所以會拋出異常:
{"Initializing[Model.Customer#336]-failed to lazily initialize a collection of role: Model.Customer.Orders, no session or session was closed"}
解決方案是,使用強制立即載入:
方法一:為類添加一個方法專門用於載入Orders
public Orders LoadOrders(int customerId){ using (ISession _session = new SessionManager().GetSession()) { return _session.Get<Customer>(customerId).Orders; }}
方法二:用NHibernateUtil.Initialize()進行強立即遲載入
public Customer Get(int customerId) { Customer customer = null; ISession session = _sessionManager.GetSession(); ITransaction transaction = session.BeginTransaction(); try { customer = session.Get<Customer>(customerId); //強制立即載入 NHibernateUtil.Initialize(customer.Orders); transaction.Commit(); } catch (Exception) { transaction.Rollback(); throw; } finally { session.Close(); } return customer; } public Customer Load(int customerId) { Customer customer = null; using (_session) { customer = _session.Load<Customer>(customerId); //強制立即載入 NHibernateUtil.Initialize(customer.Orders); return customer; } }
問題的提出:
2.消極式載入,當關聯的表很多,例如:
Customer--》Orders--》Product--》Company--》。。。
可能會引起連帶載入過多其他實體物件,照成資源消耗。
解決方案:fetch的HQL查詢:
【1】如果沒有用關鍵fetch的HQL查詢是對Orders進行消極式載入的,如下所示:
public IList<Customer> GetByHQL() { using (_session) { //注意;如果沒有用關鍵fetch的HQL查詢是對Orders進行消極式載入的, return _session.CreateQuery("select DISTINCT c from Customer c join c.Orders ") .List<Customer>(); } }測試代碼: [TestMethod] public void TestGetByHQL() { CustomerService customerService = new CustomerService(); IList<Customer> customersList = customerService.GetByHQL(); //foreach (var customer in customersList) //{ // Console.WriteLine("{0}的Order數量:{1}", // customer.CustomerId, customer.Orders.Count()); //} }從下面輸出的SQL語句,可以看出,沒用載入OrdersNHibernate: select distinct customer0_.CustomerId as CustomerId0_, customer0_.Version as Version0_, customer0_.Firstname as Firstname0_, customer0_.Lastname as Lastname0_, customer0_.Age as Age0_ from Customer customer0_ inner join [ Order] orders1_ on customer0_.CustomerId=orders1_.CustomerId
【2】在HQL查詢中加入fetch進行強制立即載入
public IList<Customer> GetByHQLAndFetch() { using (_session) { //注意;如果沒喲關鍵fetch,HQL是對Orders進行消極式載入的, //就是通過fetch進行強制立即載入 return _session.CreateQuery("select DISTINCT c from Customer c join fetch c.Orders ") .List<Customer>(); } }測試代碼: [TestMethod] public void TestGetByHQLAndFetch() { CustomerService customerService = new CustomerService(); IList<Customer> customersList = customerService.GetByHQLAndFetch(); //foreach (var customer in customersList) //{ // Console.WriteLine("{0}的Order數量:{1}", // customer.CustomerId, customer.Orders.Count()); //} }從下面輸出的SQL語句,可以看出,添加了fetch的HQL對Orders進行了強制立即載入NHibernate: select distinct customer0_.CustomerId as CustomerId0_0_, orders1_.OrderId as OrderId1_1_, customer0_.Version as Version0_0_, customer0_.Firstname as Firstname0_0_, customer0_.Lastname as Lastname0_0_, customer0_.Age as Age0_0_, orders1_.OrderDate as OrderDate1_1_, orders1_.CustomerId as CustomerId1_1_, orders1_.CustomerId as CustomerId0__, orders1_.OrderId as OrderId0__ from Customer customer0_ inner join [ Order] orders1_ on customer0_.CustomerId=orders1_.CustomerId
fetch的缺陷,來自
http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html
使用HQL查詢方法也可以立即載入。HQL語句支援的連線類型為:inner join(內串連)、left outer join(左外串連)、right outer join(右外串連)、full join(全串連,不常用)。
“抓取fetch”串連允許僅僅使用一個選擇語句就將相關聯的對象隨著他們的父物件的初始化而被初始化,可以有效代替了對應檔中的外聯結與延遲屬性聲明。
幾點注意:
- fetch不與setMaxResults() 或setFirstResult()共用,因為這些操作是基於結果集的,而在預先抓取集合時可能包含重複的資料,也就是說無法預Crowdsourced Security Testing道精確的行數。
- fetch還不能與獨立的with條件一起使用。通過在一次查詢中fetch多個集合,可以製造出笛卡爾積,因此請多加註意。對多對多映射來說,同時join fetch多個集合角色可能在某些情況下給出並非預期的結果,也請小心。
- 使用full join fetch 與 right join fetch是沒有意義的。 如果你使用屬性層級的延遲擷取,在第一個查詢中可以使用 fetch all properties 來強制NHibernate立即取得那些原本需要消極式載入的屬性。