Java程式員從笨鳥到菜鳥之(六十三)細談Hibernate(十四)Hibernate三種檢索方式詳解

來源:互聯網
上載者:User


Hibernate檢索機制中主要分為三種,他們各自有各自的好處和缺點,他主要分為以下三種:

1.立即檢索策略 

2.延遲檢索策略 

3.左外串連檢索策略 

立即載入:首先我們來看一下立即載入

                                             

List customerLists=session.createQuery("from Customer as c").list(); 

      運行以上方法時,Hibernate將先查詢CUSTOMERS表中所有的記錄,然後根據每條記錄的ID,到ORDERS表中查詢有參照關係的記錄,Hibernate將依次執行以下select語句: 

select * from CUSTOMERS; select * from ORDERS where CUSTOMER_ID=1; select * from ORDERS where CUSTOMER_ID=2; select * from ORDERS where CUSTOMER_ID=3; select * from ORDERS where CUSTOMER_ID=4; 

立即檢索缺點:

          select語句的數目太多,需要頻繁的訪問資料庫,會影響檢索效能。如果需要查詢n個Customer對象,那麼必須執行n+1次select查詢語句。這種檢索策略沒有利用SQL的串連查詢功能,例如以上5條select語句完全可以通過以下1條select語句來完成: 

select * from CUSTOMERS left outer join ORDERS on CUSTOMERS.ID=ORDERS.CUSTOMER_ID 

      以上select語句使用了SQL的左外串連查詢功能,能夠在一條select語句中查詢出CUSTOMERS表的所有記錄,以及匹配的ORDERS表的記錄。 在應用邏輯只需要訪問Customer對象,而不需要訪問Order對象的場合,載入Order對象完全是多餘的操作,這些多餘的Order對象白白浪費了許多記憶體空間。 

消極式載入:我們在一起來看一下消極式載入

一對多,對於<set>元素,應該優先考慮使用延遲檢索策略: 

<set name="orders" inverse="true" lazy="true" > 


此時運行: 

Customer customer=(Customer)session.get (Customer.class,new Long(1)); 

僅立即檢索Customer對象,執行以下select語句: 

select * from CUSTOMERS where ID=1; 

Customer對象的orders變數引用集合代理類執行個體,當應用程式第一次訪問它,例如調用customer.getOrders().iterator()方法時,Hibernate會初始化這個集合代理類執行個體,在初始化過程中到資料庫中檢索所有與Customer關聯的Order對象,執行以下select語句: 

select * from ORDERS where CUSTOMER_ID=1; 

訪問沒有被初始化的游離狀態的集合代理類執行個體

Session session=sessionFactory.openSession(); tx = session.beginTransaction(); Customer customer=(Customer)session.get(Customer.class,new Long(1)); tx.commit(); session.close(); //拋出異常 Iterator orderIterator=customer.getOrders().iterator(); 執行以上代碼,會拋出以下異常: ERROR LazyInitializer:63 - Exception initializing proxy 

優點 

由應用程式決定需要載入哪些對象,可以避免執行多餘的select語句,以及避免載入應用程式不需要訪問的對象。因此能提高檢索效能,並且能節省記憶體空間。 

缺點 

應用程式如果希望訪問游離狀態的代理類執行個體,必須保證它在持久化狀態時已經被初始化。 

適用範圍 

一對多或者多對多關聯。 

應用程式不需要立即訪問或者根本不會訪問的對象。 

左外串連檢索策略

預設情況下,多對一關聯使用左外串連檢索策略。 

如果把Order.hbm.xml檔案的<many-to-one>元素的outer-join屬性設為true,總是使用左外串連檢索策略。 

•對於以下程式碼: 

Order order=(Order)session.get(Order.class,new Long(1)); 

在運行session.get()方法時,Hibernate執行以下select語句: 

select * from ORDERS left outer join CUSTOMERS on ORDERS.CUSTOMER_ID=CUSTOMERS.ID where ORDERS.ID=1 

左外串連查詢優點 

1.對應用程式完全透明,不管對象處於持久化狀態,還是游離狀態,應用程式都可以方便的從一個對象導航到與它關聯的對象。 

2.使用了外串連,select語句數目少。 

左外串連查詢缺點 

1.可能會載入應用程式不需要訪問的對象,白白浪費許多記憶體空間。 

2.複雜的資料庫表串連也會影響檢索效能。 

左外串連查詢適用範圍 

1.多對一或者一對一關聯。 

2.應用程式需要立即訪問的對象。 

3.資料庫系統具有良好的表串連效能 

在對應檔中設定的檢索策略是固定的,要麼為延遲檢索,要麼為立即檢索,要麼為外串連檢索。 但應用邏輯是多種多樣的,有些情況下需要延遲檢索,而有些情況下需要外串連檢索。 Hibernate允許在應用程式中覆蓋對應檔中設定的檢索策略,由應用程式在運行時決定檢索對象圖的深度。 

以下Session的方法都用於檢索OID為1的Customer對象: 

session.createQuery("from Customer as c where c.id=1"); session.createQuery("from Customer as c left join fetch c.orders where c.id=1"); 

•在執行第一個方法時,將使用對應檔配置的檢索策略。 

•在執行第二個方法時,在HQL語句中顯式指定左外串連檢索關聯的Order對象,因此會覆蓋對應檔配置的檢索策略。不管在Customer.hbm.xml檔案中<set>元素的lazy屬性是true還是false,Hibernate都會執行以下select語句: 

select * from CUSTOMERS left outer join ORDERS on CUSTOMERS.ID =ORDERS.CUSTOMER_ID where CUSTOMERS.ID=1; 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.