一.延遲載入的概念 當Hibernate從資料庫中載入某個對象時,不載入關聯的對象,而只是生成了代理對象,獲取使用session中的load的方法(在沒有改變lazy屬性為false的情況下)獲取到的也是代理對象,所以在上面這幾種場景下就是延遲載入。 二.理解立即載入的概念 當Hibernate從數 ...
一.延遲載入的概念
當Hibernate從資料庫中載入某個對象時,不載入關聯的對象,而只是生成了代理對象,獲取使用session中的load的方法(在沒有改變lazy屬性為false的情況下)獲取到的也是代理對象,所以在上面這幾種場景下就是延遲載入。
二.理解立即載入的概念
當Hibernate從資料庫中載入某個對象時,載入關聯的對象,生成的實際對象,獲取使用session中的get的方法獲取到的是實際對象。
三.為什麼要使用延遲載入
延遲載入策略能避免載入應用程式不需要訪問的關聯對象,以提高應用程式的性能。
四.立即載入的缺點
Hibernate在查詢某個對象時,立即查詢與之關聯的對象,我們可以看出這種載入策略存在兩大不足:
1.select的語句數目太多,需要頻繁的訪問資料庫,會影響查詢的性能。
2.在應用程式只需要訪問要的對象,而不需要訪問與他關聯的對象的場景下,載入與之關聯的對象完全是多餘的操作,這些多餘的操作是會占記憶體,這就造成了記憶體空間的浪費。
五.什麼時候使用延遲載入什麼時候使用立即載入
如果程式載入一個持久化對象的目的是為訪問他的屬性,則可以採用立即載入。如果程式載入一個持久化對象的目的僅僅是為了獲得他的引用,則可以採用延遲載入。
六.Hibernate在對象-關係映射問價中配置載入策略
I.類級別:
<class>元素中lazy屬性的可選值為true(延遲載入)和false(立即載入);
<class>元素中的lazy屬性的預設值為true
II.一對多關聯級別:
<set>元素中的lazy屬性的可選值為:true(延遲載入),extra(增強延遲載入)和false(立即載入);
<set>元素中的lazy屬性的預設值為true
III.多對一關聯級別:
<many-to-one>元素中lazy屬性的可選值為:proxy(延遲載入),no-proxy(無代理延遲載入)和false(立即載入)
<many-to-one>元素中的lazy屬性的預設值為proxy
在下麵的一些案例中都會以員工(Emp)的部門(Dept)的例子講解:
員工和部門是多對一的關係:
關於員工和部門的Hibernate配置就不啰嗦了:可以看我的這篇博客:http://www.cnblogs.com/heyongjun1997/p/5767187.html
I.1類級別的查詢策略:
01.立即載入案例:
需求:通過Session的load()方法載入Dept對象時:
首先在Dept.hbm.xml文件中配置lazy屬性為false,表示立即載入。
@Test public void loadDept() { // 獲取Session對象 Session session = HibernateUtil.currentSession(); // 如果通過load方式載入Dept對象 Dept dept=(Dept)session.load(Dept.class, 12); // 關閉session HibernateUtil.closeSession(); }
我們知道使用Load方法載入的是代理對象,只會在屬性里保存一個OID,但是如果在Dept映射文件中配置了類級別的lazy為false就代表載入該對象時立即載入,也就是立即檢索一道資料庫,發出sql:
02.延遲載入案例:
同樣是獲取Dept對象,但是要把Dept.hbm.xml配置文件的類級別的lazy屬性改為lazy=”true” 或者不寫,應為類級別的lazy屬性預設就是true,
@Test public void loadDept() { // 獲取Session對象 Session session = HibernateUtil.currentSession(); // 如果通過load方式載入Dept對象 session.load(Dept.class, 12); // 關閉session HibernateUtil.closeSession(); }
此時Dept.hbm.xml配置文件的類級別的lazy屬性為true,則是延遲載入,那麼load方法獲取的知識Dept的代理對象,所以他不會去檢索資料庫。
II.1一對多和多對多關聯的查詢策略
01.立即載入案例:
在獲取部門對象的時候同時獲取員工對象:
設置Dept.hbm.xml 類級別的lazy屬性為false;表示立即載入:
設置<set>元素的lazy屬性為false,表示在載入部門的同時立即載入員工:
@Test public void loadDept() { // 獲取Session對象 Session session = HibernateUtil.currentSession(); // 如果通過load方式載入Dept對象 Dept dept=(Dept)session.load(Dept.class, 12); // 關閉session HibernateUtil.closeSession(); }
控制台輸出結果:
當你想獲取一的一方(Dept)的對象同時,你也要載入多的一方(Emp)的對象,那麼你要在一的一方(Emp)的<set>的節點上加上lazy="false"表示立即載入,所以在使用Load方式載入Dept對象的時候,Emp對象也會不載入出來,所以程式在運行到Dept dept=(Dept)session.load(Dept.class, 12);會發出兩條sql語句:
第一條是查詢部門的信息,第二條sql是根據部門編號去資料庫中檢索員工信息。
02.延遲載入:
如果把上面的案例<set>節點的屬性lazy改為trur,或者預設不寫,那麼在載入Dept對象的時候,就不會再去載入Emp對象,而且只會發出一條sql,這條sql就是指檢索部門的信息。
03.增強延遲載入:
當<set>元素中配置lazy的屬性為extra,表明是增強延遲載入策略。
其實增強延遲載入策略與一般的延遲載入策略lazy="true"非常相似。他們主要區別在於,我們看到這個名詞增強延遲載入,顧名思義就是這個策略能在進一步的幫我延遲載入這個對象,也就是代理對象的初始化時機。
演示案例:
01. 當set節點的lazy屬性為true,或者不寫的話(取預設值),那麼執行以下語句:
@Test public void loadDept() { // 獲取Session對象 Session session = HibernateUtil.currentSession(); // 如果通過load方式載入Dept對象 Dept dept=(Dept)session.load(Dept.class, 12); //拿該部門下的員工的人數:也就是集合的大小 dept.getEmps().size(); // 關閉session HibernateUtil.closeSession(); }
輸出結果:
02. 當set節點的lazy屬性為extra那麼執行以下語句:
@Test public void loadDept() { // 獲取Session對象 Session session = HibernateUtil.currentSession(); // 如果通過load方式載入Dept對象 Dept dept=(Dept)session.load(Dept.class, 12); //拿該部門下的員工的人數:也就是集合的大小 dept.getEmps().size(); // 關閉session HibernateUtil.closeSession(); }
輸出結果:
III.1多對一關聯的查詢策略
在映射文件中,<many-to-one>元素用來設置多對一的關係,在Emp.hbm.xml文件中表明Emp類到Dept類的多對一的關聯關係:
01.延遲載入
需求:獲取Emp對象,但是並不去載入與之關聯的Dept對象。
首先要設置<many-to-one>節點的lazy屬性為proxy,表示延遲載入。
@Test public void loadEmp() { // 獲取Session對象 Session session = HibernateUtil.currentSession(); // 如果通過load方式載入Dept對象 Emp emp=(Emp)session.get(Emp.class, 1); //獲取Dept對象,因為此時的配置文件lazy是proxy,所以是代理對象 Dept dept=emp.getDept(); // 關閉session HibernateUtil.closeSession(); }
控制台輸出結果:
結果大家可想而知:<many-to-one>節點的lazy屬性為proxy,表示延遲載入。在載入Emp對象的時候會發出sql去查詢資料庫,但是在獲取Dept對象的時候延遲載入了,所以不會發出sql。
02.無代理延遲載入:
在<many-to-one>元素中配置lazy屬性為no-proxy,表示無代理延遲載入。
@Test public void loadEmp() { // 獲取Session對象 Session session = HibernateUtil.currentSession(); // 如果通過load方式載入Dept對象 Emp emp=(Emp)session.get(Emp.class, 1); //獲取Dept對象,因為此時的配置文件lazy是proxy,所以是代理對象 Dept dept=emp.getDept(); // 關閉session HibernateUtil.closeSession(); }
此程式在載入的Emp對象dept屬性為NULL,當程式運行到第3行的時候將觸發Hibernate執行查詢Dept表的select語句,,從而載入Dept對象,由此可見,當lazy屬性為proxy時,可以延長延遲載入Dept代理對象的時間,而lazy屬性為no-proxy時,則可以避免使用由Hibernate提供的Dept代理類實例,是Hibernate對程式提供更加透明的持久化服務。
03.立即載入:
首先要設置<many-to-one>節點的lazy屬性為false,表示立即載入。
@Test public void loadEmp() { // 獲取Session對象 Session session = HibernateUtil.currentSession(); // 如果通過load方式載入Dept對象 Emp emp=(Emp)session.get(Emp.class, 1); //獲取Dept對象,因為此時的配置文件lazy是false,所以是實際對象 Dept dept=emp.getDept(); // 關閉session HibernateUtil.closeSession(); }
控制台輸出結果:
轉:http://www.cnblogs.com/heyongjun1997/p/5775033.html
謝!