Hibernate的关联关系中lazy和fetch的设置

php中文网
发布: 2016-06-07 17:10:05
原创
1016人浏览过

Hibernate的关联关系中lazy和fetch的设置会影响到对数据进行查询时候SQL语句的操作,fetch的设置相对于lazy的优先级更高,而且在cl

Hibernate的关联关系中lazy和fetch的设置会影响到对数据进行查询时候SQL语句的操作,fetch的设置相对于lazy的优先级更高,而且在class标签上配置的lazy属性不会影响到关联对象.(本例用的版本是Hibernate3)

本例假设有一个主表为MASTTB,有一个子表为DETAILTB.

主表端的fetch可以取 'join','select'和'subselect'(select为默认值):

join:外连接一次查询.

select:1+n 条select语句,第一条查主表,第n条查第n条主表记录对应的子表记录.

subselect: 以 id in(...)的方式做第二条查询,(如果查询主表的是返回单条记录,subselect和select没有区别,如果查询主表的是返回多条记录的话,对子表查询会以id in 的方式).具体见例4.

lazy可以取'true','extra'以及 'false'(true为默认值):

true:默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其集合元素的数据.
false:取消延迟加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据.
extra:一种比较聪明的延迟加载策略,即调用集合的size/contains等方法的时候,hibernate并不会去加载整个集合的数据,而是发出一条"聪明"的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据.
比如看集合的size:

会发出下面的SQL语句

    select
        count(DTID)
    from
        DETAILTB
    where
        MTID =?


1,对主表进行findById查询的测试,当fetch设为join的时候, 不管lazy是true还是false,都是一次以主表左外连接子表的方式把关联的数据全部查出来.SQL如下:

    select
        masttb0_.MID as MID1_1_,
        masttb0_.MASTINFO as MASTINFO1_1_,
        detailtbs1_.MTID as MTID3_,
        detailtbs1_.DTID as DTID3_,
        detailtbs1_.DTID as DTID2_0_,
        detailtbs1_.MTID as MTID2_0_,
        detailtbs1_.DETAILINFO as DETAILINFO2_0_
    from
        MASTTB masttb0_
    left outer join
        DETAILTB detailtbs1_
            on masttb0_.MID=detailtbs1_.MTID
    where
        masttb0_.MID=?

2,对主表进行findById查询的测试,当fetch设为select的时候,lazy 是true的时候,hibernate先用一条SQL将主表的数据查出来,然后在取子表数据的时候(在访问set的iterator的时候),再以子表的外键作为条件,用SQL语句取子表的数据.
JAVA代码如下:
            tx = sessionFactory.getCurrentSession().beginTransaction();
            MasttbHome masttbHome = new MasttbHome();
          
            Masttb masttb  = masttbHome.findById(new BigDecimal(1));
            System.out.println("before getting detai set");
          
            Set set = masttb.getDetailtbs();
          
            System.out.println("after getting detai set");
            Iterator itr = set.iterator();
            System.out.println("after getting detai set iterator");
            while(itr.hasNext()){
                Detailtb detailtb = (Detailtb)itr.next();
                System.out.println("after getting detai info " + detailtb.getDtid());
            }

            tx.commit();
运行结果如下:
Hibernate:
    select
        masttb0_.MID as MID1_0_,
        masttb0_.MASTINFO as MASTINFO1_0_
    from
        MASTTB masttb0_
    where
        masttb0_.MID=?
before getting detai set
after getting detai set
Hibernate:
    select
        detailtbs0_.MTID as MTID1_,
        detailtbs0_.DTID as DTID1_,
        detailtbs0_.DTID as DTID2_0_,
        detailtbs0_.MTID as MTID2_0_,
        detailtbs0_.DETAILINFO as DETAILINFO2_0_
    from
        DETAILTB detailtbs0_
    where
        detailtbs0_.MTID=?
after getting detai set iterator
after getting detai info 2
after getting detai info 1

3,对主表进行findById查询的测试,当fetch设为select的时候,lazy是false的时候,hibernate先用一条SQL将主表的数据查出来,然后马上再以子表的外键作为条件,用SQL语句取子表的数据.
上面例2的代码会打印:
Hibernate:
    select
        masttb0_.MID as MID1_0_,
        masttb0_.MASTINFO as MASTINFO1_0_
    from
        MASTTB masttb0_
    where
        masttb0_.MID=?
Hibernate:
    select
        detailtbs0_.MTID as MTID1_,
        detailtbs0_.DTID as DTID1_,
        detailtbs0_.DTID as DTID2_0_,
        detailtbs0_.MTID as MTID2_0_,
        detailtbs0_.DETAILINFO as DETAILINFO2_0_
    from
        DETAILTB detailtbs0_
    where
        detailtbs0_.MTID=?
before getting detai set
after getting detai set
after getting detai set iterator
after getting detai info 2
after getting detai info 1


*如果将lazy设为true,fetch设为 select,在session关闭后在去访问set里的值,会出异常.
 org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.test.hb.Masttb.detailtbs, no session or session was closed

 

贞龙网店商城电子商务系统java版
贞龙网店商城电子商务系统java版

BIZOSS-B2C是脱胎于贞龙B2B大型平台的网上商城系统、网上商店系统、网上购物系统的企业级B2C电子商务解决方案。系统设置:这里包含了网店的常用功能和全局配置的开关。包括 商店设置 、支付方式和配送方式 、邮件服务器设置、地区列表、友情链接、自定义导航栏、站点地图。商品管理:网店展示商品的核心。其中包括了 商品分类、商品类型、商品品牌、商品回收站、商品上下架等一些设置。促销管理:这个是我们网

贞龙网店商城电子商务系统java版 0
查看详情 贞龙网店商城电子商务系统java版

4,对主表进行多条记录查询的测试,当fetch设为subselect的时候,lazy是true的时候,hibernate先用一条SQL将主表的数据查出来,然后用id in 方式的SQL语句取子表的数据.

JAVA代码:

            tx = sessionFactory.getCurrentSession().beginTransaction();
           
            List mstlist = sessionFactory.getCurrentSession().createQuery("from com.test.hb.Masttb where id in (1,2)").list();

            //下面的hql和上面的hql有同样的效果

           //List mstlist = sessionFactory.getCurrentSession().createQuery("from com.test.hb.Masttb where id             for (Iterator iter = mstlist.iterator(); iter.hasNext();) {
                Masttb masttb = (Masttb) iter.next();
                System.out.println("masttb.getMastinfo=" + masttb.getMastinfo());
                Set set = masttb.getDetailtbs();
                System.out.println(set.size());
                if (set != null && !set.isEmpty()) {
                    for (Iterator itr = set.iterator(); itr.hasNext();) {
                        Detailtb detailtb = (Detailtb) itr.next();
                        System.out.println("detailtb.name=" + detailtb.getDetailinfo());
                    }
                }
            }

            tx.commit();

运行结果:

Hibernate:
    select
        masttb0_.MID as MID1_,
        masttb0_.MASTINFO as MASTINFO1_
    from
        MASTTB masttb0_
    where
        masttb0_.MID in (
            1 , 2
        )
masttb.getMastinfo=mastinfo
Hibernate:
    select
        detailtbs0_.MTID as MTID1_,
        detailtbs0_.DTID as DTID1_,
        detailtbs0_.DTID as DTID2_0_,
        detailtbs0_.MTID as MTID2_0_,
        detailtbs0_.DETAILINFO as DETAILINFO2_0_
    from
        DETAILTB detailtbs0_
    where
        detailtbs0_.MTID in (
            select
                masttb0_.MID
            from
                MASTTB masttb0_
            where
                masttb0_.MID in (
                    1 , 2
                )
        )
number in detail table: 2
detailtb.name=aaaa
detailtb.name=detailinfo2
masttb.getMastinfo=aaa
number in detail table: 1
detailtb.name=adfasdfa

如果fetch=select,lazy=true的话,运行结果为 1 + 2条SQL语句:

Hibernate:
    select
        masttb0_.MID as MID1_,
        masttb0_.MASTINFO as MASTINFO1_
    from
        MASTTB masttb0_
    where
        masttb0_.MID in (
            1 , 2
        )
masttb.getMastinfo=mastinfo
Hibernate:
    select
        detailtbs0_.MTID as MTID1_,
        detailtbs0_.DTID as DTID1_,
        detailtbs0_.DTID as DTID2_0_,
        detailtbs0_.MTID as MTID2_0_,
        detailtbs0_.DETAILINFO as DETAILINFO2_0_
    from
        DETAILTB detailtbs0_
    where
        detailtbs0_.MTID=?
number in detail table: 2
detailtb.name=aaaa
detailtb.name=detailinfo2
masttb.getMastinfo=aaa
Hibernate:
    select
        detailtbs0_.MTID as MTID1_,
        detailtbs0_.DTID as DTID1_,
        detailtbs0_.DTID as DTID2_0_,
        detailtbs0_.MTID as MTID2_0_,
        detailtbs0_.DETAILINFO as DETAILINFO2_0_
    from
        DETAILTB detailtbs0_
    where
        detailtbs0_.MTID=?
number in detail table: 1
detailtb.name=adfasdfa

linux

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号