1、Hibernate檢索策略sql
一、Hibernate提供了三種檢索策略:當即檢索策略、延遲檢索策略(懶加載機制)、迫切左外鏈接檢索策略。Hibernate在3.x之前lazy屬性默認爲false,Session的get()方法、load()方法默認都使用的是當即檢索策略。從3.x之後,lazy屬性爲true,get()方法使用的是當即檢索策略,load()方法默認使用的延遲檢索策略。數據庫
之前默認的當即檢索策略存在兩大不足:性能
①、select語句的數據太多,須要頻繁的訪問數據庫,會影響檢索性能。若是須要檢索查詢n個Customer對象,那麼必須執行n+1次select查詢語句。這種檢索策略沒有利用sql的連接查詢功能,例如,以上5條select語句徹底能夠經過如下一條select語句完成:select * from customer left outer join Orders on customers.id=orders.customer_id代理
②、在應用邏輯只須要訪問Customer對象,而不須要訪問Order對象的場合,加載Order對象徹底是多餘的操做,這些多餘的Order對象白白浪費了許多內存空間。xml
而HIbernate提供的延遲檢索策略能避免多餘加載應用程序不須要訪問的關聯對象,迫切左外鏈接檢索策略則充分利用了sql的外鏈接查詢功能,可以減小select語句的數目。對象
二、類級別和關聯級別的檢索策略繼承
檢索策略的做用域 | 可選的檢索策略 | 默認的檢索策略 | 運行時行爲受影響的Session的檢索方法 |
類級別接口 |
當即檢索內存 延遲檢索作用域 |
當即檢索 | 僅影響load()方法 |
關聯級別 | 當即檢索 延遲檢索 迫切左外鏈接檢索 |
多對一和一對一關聯爲外鏈接檢索 一對多和多對多關聯爲當即檢索 |
影響Load()、get()和find()方法 |
在類級別中,可選的檢索策略包括當即檢索和延遲檢索策略,可是它僅影響load()方法,在關聯級別中,可選的檢索策略包括當即檢索、延遲檢索和迫切左外鏈接檢索。
三種檢索策略的運行機制:
檢索策略類型 | 類級別 | 關聯級別 |
當即檢索 | 當即加載檢索方法指定的對象 | 當即加載與檢索方法指定的對象關聯的對象。 |
延遲檢索 | 延遲加載檢索方法指定的對象 | 延遲加載與檢索方法指定的對象關聯的對象。 |
迫切左外鏈接檢索 | 不適用 | 經過左外鏈接加載與檢索方法指定的對象關聯的對象 |
2、類級別的檢索策略:
一、類級別可選的檢索策略包括當即檢索和延遲檢索,默認爲當即檢索。若是<class>元素的lazy屬性爲true,表示採用延遲檢索。若是lazy屬性爲false,表示採用當即檢索。從Hibernate3.x之後,類級別的lazy默認爲true,表示load()方法採用延遲檢索策略。當執行Session的load()方法時,Hibernate不會當即執行查詢CUSTOMER表的select語句,僅僅返回Customer類的代理類的實例,這個代理類有如下特徵:
①、由Hibernate在運行時動態生成,它擴展了Customer類,所以它繼承了Customer類的全部屬性和方法,但它的實現對於應用程序時透明的。
②、當HIbernate建立Customer代理類實例時,僅僅初始化了它的OID屬性,其餘屬性全爲null,所以這個代理類實例佔用內存不多。
③、當應用程序第一次訪問Customer代理類實例時,例如調用Customer.getName()方法,HIbernate會初始化代理類實例,在初始化過程當中執行select語句,真正從數據庫加載 Customer對象的全部數據。但有個例外,那就是當應用程序訪問Customer代理類實例的getId()方法,HIbernate不會初始化代理類實例。
Hibernate類的initialize()靜態方法用於在Session範圍內顯式初始化代理類實例,isInitialize()方法用於判斷代理類實例是否已經被初始化。
3、一對多和多對多檢索策略
在映射文件中,用<set>元素來配置一對多關聯及多對多關聯關係。<set>元素有lazy和outer-join屬性,
lazy屬性 | outer-join屬性 | 檢索策略 |
false | false | 採用當即檢索,這是默認的檢索策略 |
false | true | 採用迫切左外鏈接檢索策略 |
true | false | 採用延遲檢索策略 |
true | true | 毫無心義 |
HIbernate爲Set集合也提供了代理類,它擴展了Set接口,但它的實現對應用程序時透明大的。
<set>元素有一個batch-size屬性,用於爲延遲檢索或當即檢索策略設定批量檢索數量。批量檢索可以減小select語句,提升延遲檢索檢索或當即檢索的性能。
當<set .....batch-size=3>時,HIbernate的select語句,會變爲:select * from orders where customer_id=1 or customer_id=2 or customer_id=3。必須根據實際狀況肯定批量檢索數目,合理的批量檢索數目應該控制在3到10之間。
outer-join=true屬性,設置迫切左外鏈接檢索策略。
4、多對一和一對一關聯的檢索策略
一、<many-to-one>元素有一個outer-join屬性,他有三個可選值:
①、auto:這是默認值,若是Customer.hbm.xml文件的class元素的lazy屬性爲true,那麼對於Order關聯的Customer對象採用延遲檢索策略。不然採用迫切左外鏈接檢索策略。
②、true。無論Customer.hbm.xml文件的class元素的lazy屬性爲true仍是false,對於Order關聯的Customer對象都採用迫切左外鏈接檢索策略。
③、false:始終不會對於ORder關聯的Customer對象採用迫切左外鏈接檢索策略。
對於多對一或一對一關聯,應該優先考慮使用外鏈接檢索策略,由於它比當即檢索策略使用的select數據少,假如應用程序僅僅但願訪問ORder對象,並不須要當即訪問與ORder對象關聯的Customer對象,也能夠考慮使用延遲檢索策略。
在<one-to-one>一對一關聯中,若是使用懶加載機制,必須把<one-to-one>元素中的constrained屬性設爲true,(constrained屬性只能用在一對一關聯中)。
5、Hibernate對迫切左外鏈接檢索的限制
假如select語句包含多個一對多關聯的外鏈接,會致使一次檢索出大批量的數據,從而影響檢索性能,所以Hibernate對迫切左外鏈接作了限制:
①、在一個select語句中只容許包含一個一對多或多對多關聯的迫切左外鏈接。
②、在一個select語句中容許包含多個多對一或一對一關聯的迫切左外鏈接。