標籤:
一、什麼是消極式載入?
消極式載入是指當應用程式想要從資料庫擷取對象時(在沒有設定lazy屬性值為false),Hibernate只是從資料庫擷取合格對象的OId從而組建代理程式對象,並沒有載入出對象訪問該對象的屬性時才會載入出相應的值。簡答來說就是儘可能的減少查詢的資料量。簡言之,是當在真正需要資料時,才執行Sql語句進行查詢。
二、如何配置消極式載入
在Hibernate中通過.hbm設定檔中的lazy屬性來配置,並且lazy屬性出現的位置不同其作用和取值也不同。下面來詳細介紹其在不同位置的不同取值和作用。
消極式載入分類:
01.類層級的查詢策略
02.一對多和多對多關聯的查詢策略
03.多對一關聯的查詢策略
①類層級的查詢策略
類層級可選的載入策略包括立即載入和消極式載入。預設為消極式載入。如果<class>元素的lazy屬性為true。表示採用消極式載入;如果lazy屬性為false,表示採用立即載入
以Emp和Dept為例:
在Dept.hbm.xml中的<Set>元素中添加屬性 lazy="false" 表示立即載入
測試類別:
@Test public void oneTest(){ Dept dept=(Dept)session.load(Dept.class, 1); //lazy true/false 類層級 System.out.println(dept.getDeptName());
load()方法在Id屬性和getClass(),不去請求資料庫,其他屬性需請求資料庫
② 一對多和多對多關聯的查詢策略
lazy屬性的另一個屬性extra 加強消極式載入
表明採用增強消極式載入策略:在<set>元素配置lazy屬性為"extra"。增強消極式載入策略與一般的消極式載入策略(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(); }
輸出結果如下:
③ 多對一關聯的查詢策略
<many-to-one>元素用來設定多對一關聯關係。
lazy屬性 預設值為proxy
proxy:消極式載入
no-proxy:無代理消極式載入
false:立即載入
例子:
/* * 多對一消極式載入 */ @Test public void manytoTest(){ Emp emp=(Emp)session.get(Emp.class, 2); //擷取Dept對象,因為此時的設定檔lazy是proxy,所以是代理對象 Dept dept=emp.getDept(); System.out.println(dept.getDeptName()); }
輸出結果:
無代理延遲物件:
在<many-to-one>元素中配置lazy屬性為no-proxy,表示無代理消極式載入。
@Testpublic void loadEmp() {// 擷取Session對象Session session = HibernateUtil.currentSession();// 如果通過load方式載入Dept對象Emp emp=(Emp)session.get(Emp.class, 1);//擷取Dept對象,因為此時的設定檔lazy是proxy,所以是代理對象Dept dept=emp.getDept();// 關閉sessionHibernateUtil.closeSession();}
此程式在載入的Emp對象dept屬性為null,當程式運行到第3行的時候將觸發Hibernate執行查詢Dept表的select語句,從而載入Dept對象,由此可見,當lazy屬性為proxy時,可以延長消極式載入Dept代理對象的時間,而lazy屬性為no-proxy時,則可以避免使用由Hibernate提供的Dept代理類執行個體,是Hibernate對程式提供更加透明的持久化服務。
Hibernate消極式載入