Google Code Prettify

2016年2月11日 星期四

Hibernate: get、load、lazy 討論

繼續前兩篇的討論 ...


Source Code: https://bitbucket.org/twleader59/orm

前兩篇討論的是 insert,對於許多 xml tag 的屬性也沒有多作說明,這一篇開始逐項的補充。(在開始說明前,先為每個 class 加上 toString(),以輸出欄位值。)

在之前 xml 設定中 set tag 有個屬性 lazy,通常我們會將它設定為 true,表示會延遲下載,那麼有沒有延遲下載有什麼差別? 看一下下面這段程式:
 1 Customer c = session.load(Customer.class, "2000000025");
 2 
 3 if (c == null) {
 4     System.out.println("customer is null");
 5 }
 6 else {
 7     System.out.println(c.toString());
 8     //System.out.println(c.getSales().toString());
 9     //System.out.println(c.getGoods().toString());
10 }
這段程式執行後,Hibernate 會如我們期待的產生以下 sql,由 CUSTOMER table 中取出我們要的資料。
(在 hibernate.cfg.xml 中加入 <property name="show_sql">true</property> 即可輸出 sql)
Hibernate: 
    select
        customer0_.CID as CID1_0_0_,
        customer0_.NAME as NAME2_0_0_,
        customer0_.EMNO as EMNO3_0_0_ 
    from
        STEVEN.CUSTOMER customer0_ 
    where
        customer0_.CID=?
接著把 Customer.hbm.xml 中的 lazy 屬性設定為 false,再重新執行一次,這次不只 select CUSTOMER,還 select GOODS,Hibernate 預設 lazy 值為 true,如果設定為 false 不延遲載入,Hibernate 就會把相關的資料也一併查詢出來。資料少的時候這樣是很方便,不過,資料多的話,很可能會因為這些不一定需要的 select 動作,讓系統效能變得很差!
Hibernate: 
    select
        customer0_.CID as CID1_0_0_,
        customer0_.NAME as NAME2_0_0_,
        customer0_.EMNO as EMNO3_0_0_ 
    from
        STEVEN.CUSTOMER customer0_ 
    where
        customer0_.CID=?
Hibernate: 
    select
        goods0_.CID as CID1_2_0_,
        goods0_.GID as GID2_2_0_,
        goods1_.GID as GID1_1_1_,
        goods1_.NAME as NAME2_1_1_ 
    from
        STEVEN.ORDERS goods0_ 
    inner join
        STEVEN.GOODS goods1_ 
            on goods0_.GID=goods1_.GID 
    where
        goods0_.CID=?
接下來把測試程式的第 8、9 行的註解 // 拿掉,同時輸出三項看看會有什麼結果? 結果不管 lazy 是 true 或 false,CUSTOMER、SALES、ORDERS 三個 table 都會 select 一次,如下,當然啦~ 因為程式本來就是三個資料都需要,不過,lazy 為 true 和 false 時,產生 sql 的時機還是會不同,lazy 為 true 時是真的需要時才 select,為 false 時則會先 select 出相關的資料,強烈建議,沒有特別的需求的話,lazy 都應該是設定為 true。
Hibernate: 
    select
        customer0_.CID as CID1_0_0_,
        customer0_.NAME as NAME2_0_0_,
        customer0_.EMNO as EMNO3_0_0_ 
    from
        STEVEN.CUSTOMER customer0_ 
    where
        customer0_.CID=?
Hibernate: 
    select
        goods0_.CID as CID1_2_0_,
        goods0_.GID as GID2_2_0_,
        goods1_.GID as GID1_1_1_,
        goods1_.NAME as NAME2_1_1_ 
    from
        STEVEN.ORDERS goods0_ 
    inner join
        STEVEN.GOODS goods1_ 
            on goods0_.GID=goods1_.GID 
    where
        goods0_.CID=?
Hibernate: 
    select
        sales0_.EMNO as EMNO1_3_0_,
        sales0_.NAME as NAME2_3_0_ 
    from
        STEVEN.SALES sales0_ 
    where
        sales0_.EMNO=?
上面的程式是用 load 來查詢出資料,Hibernate 另外提供有 get 這個 method,用法都一樣,差別在於是否延遲下載! 使用 get 時,Hibernate 是立即的到資料庫查詢,而使用 load 則可能會延遲到真的需要使用時才查詢。



沒有留言:

張貼留言