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=创智] 
相关文章

相关标签/搜索