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;