1. 程式人生 > >Hibernate懶載入、關聯級別載入策略

Hibernate懶載入、關聯級別載入策略

Hibernate懶載入

對於hibernate.cfg.xml配置、Customer物件配置這裡就不貼程式碼了,在上篇筆記裡面有
Customer.hbm.xml配置如下 lazy=”true”是預設配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="cn.itcast.domain" >
<class name="Customer" table="cst_customer" lazy="true" > <id name="cust_id" > <generator class="native"></generator> </id> <property name="cust_name" column="cust_name" ></property> <property
name="cust_source" column="cust_source" >
</property> <property name="cust_industry" column="cust_industry" ></property> <property name="cust_level" column="cust_level" ></property> <property name="cust_linkman" column="cust_linkman" ></property
>
<property name="cust_phone" column="cust_phone" ></property> <property name="cust_mobile" column="cust_mobile" ></property> <!-- lazy屬性: 決定是否延遲載入 true(預設值): 延遲載入,懶載入 false: 立即載入 extra: 極其懶惰 fetch屬性: 決定載入策略.使用什麼型別的sql語句載入集合資料 select(預設值): 單表查詢載入 join: 使用多表查詢載入集合 subselect:使用子查詢載入集合 --> <!-- batch-size: 抓取集合的數量為3. 抓取客戶的集合時,一次抓取幾個客戶的聯絡人集合. --> <set name="linkMens" batch-size="3" > <key column="lkm_cust_id" ></key> <one-to-many class="LinkMan" /> </set> </class> </hibernate-mapping>

來看下測試程式碼

    @Test
    // get方法 : 立即載入.執行方法時立即傳送sql語句查詢結果
    public void fun1(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------

        Customer c = session.get(Customer.class, 2l);
        System.out.println("======fun1========");
        System.out.println(c);
        //----------------------------------------------------
        tx.commit();
        session.close();

    }

在fun1測試中是即時進行載入的,輸入的log如下:

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?
======fun1========
Customer [cust_id=2, cust_name=wyf]

通過log日誌就可以看出session.get(Customer.class, 2l);就輸出sql語句
我們接下來看load懶載入

    @Test
    // load方法(預設):是在執行時,不傳送任何sql語句.返回一個物件.使用該物件時,才執行查詢.
    // 延遲載入: 僅僅獲得沒有使用.不會查詢.在使用時才進行查詢.
    // 是否對類進行延遲載入: 可以通過在class元素上配置lazy屬性來控制.
        //lazy:true  載入時,不查詢.使用時才查詢b
        //lazy:false 載入時立即查詢.
    public void fun2(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------

        Customer c = session.load(Customer.class, 2l);
        System.out.println("=======fun2=======");
        //----------------------------------------------------
        tx.commit();
        System.out.println(c);
        session.close();


    }

通過懶載入我們看下log輸出

=======fun2=======
Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?
Customer [cust_id=2, cust_name=wyf]

通過輸出就可以看出來,僅僅獲得沒有使用.不會查詢.在使用時才進行查詢.

關聯級別策略-客戶表

fetch:select、lazy:true
<!-- 
        lazy屬性: 決定是否延遲載入
            true(預設值): 延遲載入,懶載入
            false: 立即載入
            extra: 極其懶惰
        fetch屬性: 決定載入策略.使用什麼型別的sql語句載入集合資料
            select(預設值): 單表查詢載入
            join: 使用多表查詢載入集合
            subselect:使用子查詢載入集合
     -->

我們將Customer.hbm.xml修改下配置檔案

    <set name="linkMens" lazy="true" fetch="select"  >
            <key column="lkm_cust_id" ></key>
            <one-to-many class="LinkMan" />
        </set>

LinkMan.hbm.xml配置預設策略

<many-to-one name="customer" column="lkm_cust_id" class="Customer"  >
        </many-to-one>

來進行測試下

    //集合級別的關聯
    //fetch:select 單表查詢
    //lazy:true 使用時才載入集合資料.
    @Test
    public void fun1(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------

        Customer c = session.get(Customer.class, 2l);
        System.out.println("------111--------");
        Set<LinkMan> linkMens = c.getLinkMens();//關聯級別
        System.out.println("-------222-------");
        System.out.println(linkMens);

        //----------------------------------------------------
        tx.commit();
        session.close();

    }

輸出log如下

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?
------111--------
-------222-------
Hibernate: 
    select
        linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_1_,
        linkmens0_.lkm_gender as lkm_gend2_1_1_,
        linkmens0_.lkm_name as lkm_name3_1_1_,
        linkmens0_.lkm_phone as lkm_phon4_1_1_,
        linkmens0_.lkm_email as lkm_emai5_1_1_,
        linkmens0_.lkm_qq as lkm_qq6_1_1_,
        linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
        linkmens0_.lkm_memo as lkm_memo8_1_1_,
        linkmens0_.lkm_position as lkm_posi9_1_1_,
        linkmens0_.lkm_cust_id as lkm_cus10_1_1_ 
    from
        cst_linkman linkmens0_ 
    where
        linkmens0_.lkm_cust_id=?
[cn.itcast.domain.LinkMan@29876704, cn.itcast.domain.LinkMan@455351c4]

通過fetch:select、lazy:true對客戶表進行配置執行,說明Set linkMens = c.getLinkMens();//關聯級別查詢不會輸出sql語句,只有在使用時才載入集合資料.

fetch:select、lazy:false

我們繼續看另外一種載入策略
將客戶的配置修改如下

    <set name="linkMens" lazy="false" fetch="select"  >
            <key column="lkm_cust_id" ></key>
            <one-to-many class="LinkMan" />
        </set>
        //集合級別的關聯
        //fetch:select 單表查詢
        //lazy:false 立即記載集合資料
        @Test
        public void fun2(){
            Session session = HibernateUtils.openSession();
            Transaction tx = session.beginTransaction();
            //----------------------------------------------------

            Customer c = session.get(Customer.class, 2l);
            System.out.println("------111--------");
            Set<LinkMan> linkMens = c.getLinkMens();//關聯級別
            System.out.println("------222--------");
            System.out.println(linkMens);

            //----------------------------------------------------
            tx.commit();
            session.close();

        }

log日誌如下:

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?
Hibernate: 
    select
        linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_1_,
        linkmens0_.lkm_gender as lkm_gend2_1_1_,
        linkmens0_.lkm_name as lkm_name3_1_1_,
        linkmens0_.lkm_phone as lkm_phon4_1_1_,
        linkmens0_.lkm_email as lkm_emai5_1_1_,
        linkmens0_.lkm_qq as lkm_qq6_1_1_,
        linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
        linkmens0_.lkm_memo as lkm_memo8_1_1_,
        linkmens0_.lkm_position as lkm_posi9_1_1_,
        linkmens0_.lkm_cust_id as lkm_cus10_1_1_ 
    from
        cst_linkman linkmens0_ 
    where
        linkmens0_.lkm_cust_id=?
------111--------
------222--------
[cn.itcast.domain.LinkMan@4816c290, cn.itcast.domain.LinkMan@4940809c]

fetch:select、lazy:false說明是2條單表語句,立刻查詢

fetch:join、lazy:true
<set name="linkMens" lazy="true" fetch="join"  >
            <key column="lkm_cust_id" ></key>
            <one-to-many class="LinkMan" />
        </set>
    //fetch:join    多表查詢
        //lazy:true|false|extra 失效.立即載入.
        @Test
        public void fun4(){
            Session session = HibernateUtils.openSession();
            Transaction tx = session.beginTransaction();
            //----------------------------------------------------

            Customer c = session.get(Customer.class, 2l);
            System.out.println("------111--------");
            Set<LinkMan> linkMens = c.getLinkMens();//關聯級別
            System.out.println("------222--------");
            System.out.println(linkMens.size());

            System.out.println(linkMens);

            //----------------------------------------------------
            tx.commit();
            session.close();

        }

日誌輸出如下:

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_,
        linkmens1_.lkm_cust_id as lkm_cus10_1_1_,
        linkmens1_.lkm_id as lkm_id1_1_1_,
        linkmens1_.lkm_id as lkm_id1_1_2_,
        linkmens1_.lkm_gender as lkm_gend2_1_2_,
        linkmens1_.lkm_name as lkm_name3_1_2_,
        linkmens1_.lkm_phone as lkm_phon4_1_2_,
        linkmens1_.lkm_email as lkm_emai5_1_2_,
        linkmens1_.lkm_qq as lkm_qq6_1_2_,
        linkmens1_.lkm_mobile as lkm_mobi7_1_2_,
        linkmens1_.lkm_memo as lkm_memo8_1_2_,
        linkmens1_.lkm_position as lkm_posi9_1_2_,
        linkmens1_.lkm_cust_id as lkm_cus10_1_2_ 
    from
        cst_customer customer0_ 
    left outer join
        cst_linkman linkmens1_ 
            on customer0_.cust_id=linkmens1_.lkm_cust_id 
    where
        customer0_.cust_id=?
------111--------
------222--------
2
[cn.itcast.domain.LinkMan@54107f42, cn.itcast.domain.LinkMan@64712be]

lazy:true屬性失效,因為是使用的多表查詢,直接就查詢出來了

關聯級別策略-聯絡人表

fetch:select、lazy:proxy、customer-true 懶載入
<!-- 
        lazy屬性: 決定是否延遲載入
            true(預設值): 延遲載入,懶載入
            false: 立即載入
            extra: 極其懶惰
        fetch屬性: 決定載入策略.使用什麼型別的sql語句載入集合資料
            select(預設值): 單表查詢載入
            join: 使用多表查詢載入集合
            subselect:使用子查詢載入集合
     -->
     <!-- batch-size: 抓取集合的數量為3.
            抓取客戶的集合時,一次抓取幾個客戶的聯絡人集合.
      -->
        <set name="linkMens" lazy="true">
            <key column="lkm_cust_id" ></key>
            <one-to-many class="LinkMan" />
        </set>
    <!-- 
        fetch 決定載入的sql語句
            select: 使用單表查詢
            join : 多表查詢
        lazy  決定載入時機
            false: 立即載入
            proxy: 由customer的類級別載入策略決定.
         -->
        <many-to-one name="customer" column="lkm_cust_id" class="Customer"  fetch="select" lazy="proxy" >
        </many-to-one>

來看下測試程式碼

    @Test
    //fetch:select  單表查詢
    //lazy:proxy  
        //customer-true 懶載入
    public void fun1(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------

        LinkMan lm = session.get(LinkMan.class, 3l);
        System.out.println("-------111-------");
        Customer customer = lm.getCustomer();
        System.out.println("-------222-------");
        System.out.println(customer);

        //----------------------------------------------------
        tx.commit();
        session.close();

    }

sql日誌如下:

Hibernate: 
    select
        linkman0_.lkm_id as lkm_id1_1_0_,
        linkman0_.lkm_gender as lkm_gend2_1_0_,
        linkman0_.lkm_name as lkm_name3_1_0_,
        linkman0_.lkm_phone as lkm_phon4_1_0_,
        linkman0_.lkm_email as lkm_emai5_1_0_,
        linkman0_.lkm_qq as lkm_qq6_1_0_,
        linkman0_.lkm_mobile as lkm_mobi7_1_0_,
        linkman0_.lkm_memo as lkm_memo8_1_0_,
        linkman0_.lkm_position as lkm_posi9_1_0_,
        linkman0_.lkm_cust_id as lkm_cus10_1_0_ 
    from
        cst_linkman linkman0_ 
    where
        linkman0_.lkm_id=?
-------111-------
-------222-------
Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?
Customer [cust_id=1, cust_name=創智]
fetch:select、lazy:proxy、customer-false懶載入
    <set name="linkMens" lazy="false">
            <key column="lkm_cust_id" ></key>
            <one-to-many class="LinkMan" />
        </set>
<many-to-one name="customer" column="lkm_cust_id" class="Customer"  fetch="select" lazy="proxy" >
        </many-to-one>
    @Test
    //fetch:select  單表查詢
    //lazy:proxy  
        //customer-false 立即載入
    public void fun2(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------

        LinkMan lm = session.get(LinkMan.class, 3l);

        System.out.println("-------111-------");
        Customer customer = lm.getCustomer();
        System.out.println("-------222-------");

        System.out.println(customer);

        //----------------------------------------------------
        tx.commit();
        session.close();

    }

sql日誌如下:

Hibernate: 
    select
        linkman0_.lkm_id as lkm_id1_1_0_,
        linkman0_.lkm_gender as lkm_gend2_1_0_,
        linkman0_.lkm_name as lkm_name3_1_0_,
        linkman0_.lkm_phone as lkm_phon4_1_0_,
        linkman0_.lkm_email as lkm_emai5_1_0_,
        linkman0_.lkm_qq as lkm_qq6_1_0_,
        linkman0_.lkm_mobile as lkm_mobi7_1_0_,
        linkman0_.lkm_memo as lkm_memo8_1_0_,
        linkman0_.lkm_position as lkm_posi9_1_0_,
        linkman0_.lkm_cust_id as lkm_cus10_1_0_ 
    from
        cst_linkman linkman0_ 
    where
        linkman0_.lkm_id=?
-------111-------
-------222-------
Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?
Hibernate: 
    select
        linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_1_,
        linkmens0_.lkm_gender as lkm_gend2_1_1_,
        linkmens0_.lkm_name as lkm_name3_1_1_,
        linkmens0_.lkm_phone as lkm_phon4_1_1_,
        linkmens0_.lkm_email as lkm_emai5_1_1_,
        linkmens0_.lkm_qq as lkm_qq6_1_1_,
        linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
        linkmens0_.lkm_memo as lkm_memo8_1_1_,
        linkmens0_.lkm_position as lkm_posi9_1_1_,
        linkmens0_.lkm_cust_id as lkm_cus10_1_1_ 
    from
        cst_linkman linkmens0_ 
    where
        linkmens0_.lkm_cust_id=?
fetch:join、lazy:proxy、customer-true 懶載入
    <set name="linkMens" lazy="true">
            <key column="lkm_cust_id" ></key>
            <one-to-many class="LinkMan" />
        </set>
<!-- 
        fetch 決定載入的sql語句
            select: 使用單表查詢
            join : 多表查詢
        lazy  決定載入時機
            false: 立即載入
            proxy: 由customer的類級別載入策略決定.
         -->
        <many-to-one name="customer" column="lkm_cust_id" class="Customer"  fetch="join" lazy="proxy" >
        </many-to-one>

來看下測試程式碼:

    @Test
    //fetch:join    多表
    //lazy: 失效  
    public void fun3(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------

        LinkMan lm = session.get(LinkMan.class, 3l);
        System.out.println("-------111-------");
        Customer customer = lm.getCustomer();
        System.out.println("-------222-------");
        System.out.println(customer);

        //----------------------------------------------------
        tx.commit();
        session.close();

    }

sql日誌輸出如下:

Hibernate: 
    select
        linkman0_.lkm_id as lkm_id1_1_0_,
        linkman0_.lkm_gender as lkm_gend2_1_0_,
        linkman0_.lkm_name as lkm_name3_1_0_,
        linkman0_.lkm_phone as lkm_phon4_1_0_,
        linkman0_.lkm_email as lkm_emai5_1_0_,
        linkman0_.lkm_qq as lkm_qq6_1_0_,
        linkman0_.lkm_mobile as lkm_mobi7_1_0_,
        linkman0_.lkm_memo as lkm_memo8_1_0_,
        linkman0_.lkm_position as lkm_posi9_1_0_,
        linkman0_.lkm_cust_id as lkm_cus10_1_0_,
        customer1_.cust_id as cust_id1_0_1_,
        customer1_.cust_name as cust_nam2_0_1_,
        customer1_.cust_source as cust_sou3_0_1_,
        customer1_.cust_industry as cust_ind4_0_1_,
        customer1_.cust_level as cust_lev5_0_1_,
        customer1_.cust_linkman as cust_lin6_0_1_,
        customer1_.cust_phone as cust_pho7_0_1_,
        customer1_.cust_mobile as cust_mob8_0_1_ 
    from
        cst_linkman linkman0_ 
    left outer join
        cst_customer customer1_ 
            on linkman0_.lkm_cust_id=customer1_.cust_id 
    where
        linkman0_.lkm_id=?
-------111-------
-------222-------
Customer [cust_id=1, cust_name=創智]