一对多 、多对多 的检索策略

在映射文件中, 用 <set> 元素来配置一对多关联及多对多关联关系. <set> 元素有 lazy 和 fetch 属性
lazy: 主要决定 orders 集合被初始化的时机. 即到底是在加载 Customer 对象时就被初始化, 还是在程序访问                   orders 集合时被初始化
fetch: 取值为 “select” 或 “subselect” 时, 决定初始化 orders 的查询语句的形式;  若取值为”join”, 则决定 orders            集合被初始化的时机若把 fetch 设置为 “join”, lazy 属性将被忽略

<set> 元素的 batch-size 属性:用来为延迟检索策略或立即检索策略设定批量检索的数量. 批量检索能减少                                                                SELECT 语句的数目, 提高延迟检索或立即检索的运行性能. 


Clazz 类 的对象关系映射,之一中的set 属性中的配置

<hibernate-mapping package="com.baidu.setStrategy">
			<!-- lazy 类级别的懒加载 -->
    <class name="Clazz" table="CLAZZS" >
    
        <id name="clazzId" type="java.lang.Integer">
            <column name="CLAZZ_ID" />
            <generator class="native" />
        </id>
        
        <property name="clazzName" type="java.lang.String">
            <column name="CLAZZ_NAME" />
        </property>
        
        <set name="stus" table="STUDENTS" lazy="true">
            <key>
                <column name="CLAZZ_ID" />
            </key>
            <one-to-many class="Student" />
        </set>
        
    </class>
    
</hibernate-mapping>

	/**
	 * Set 的 lazy 属性
	 * 	1.  1-n 或n-n 的集合属性默认使用懒加载检索策略
	 *  2.  可以通过设置set 的lazy 属性来修改默认的检索策略,默认为true
	 *  	并不建议设置为false
	 *  3.  lazy 还可以设置为extra,增强的延迟检索。该取值会尽可能的延迟集合初始化的时机
	 * 	4.	Hibernate.initialize() 静态方法显式初始化
	 */

Lazy 属性:默认值是true

① 当取true 时, 

	@Test
	public void testOne2ManyLevelStrategy() {
		Clazz clazz =(Clazz) session.get(Clazz.class, 1); 
		System.out.println(clazz.getClass());
		
		System.out.println(clazz.getStus().size());
	
	}
运行的SQL

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_0_ 
    from
        CLAZZS clazz0_ 
    where
        clazz0_.CLAZZ_ID=?
class com.baidu.setStrategy.Clazz
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID=?
2

② 当取fasle 时,
运行的SQL

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_0_ 
    from
        CLAZZS clazz0_ 
    where
        clazz0_.CLAZZ_ID=?
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID=?
class com.baidu.setStrategy.Clazz
2

③ 当取extra 时,

运行的SQL

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_0_ 
    from
        CLAZZS clazz0_ 
    where
        clazz0_.CLAZZ_ID=?
class com.baidu.setStrategy.Clazz
Hibernate: 
    select
        count(STU_ID) 
    from
        STUDENTS 
    where
        CLAZZ_ID =?
2
在添加测试方法中添加代码

	@Test
	public void testOne2ManyLevelStrategy() {
		Clazz clazz =(Clazz) session.get(Clazz.class, 1); 
		System.out.println(clazz.getClass());
		System.out.println(clazz.getStus().size());
		
	
		Student student = new Student();
		
		student.setStuId(1);
		System.out.println(clazz.getStus().contains(student));
		
	}
运行的SQL

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_0_ 
    from
        CLAZZS clazz0_ 
    where
        clazz0_.CLAZZ_ID=?
class com.baidu.setStrategy.Clazz
Hibernate: 
    select
        count(STU_ID) 
    from
        STUDENTS 
    where
        CLAZZ_ID =?
2
Hibernate: 
    select
        1 
    from
        STUDENTS 
    where
        CLAZZ_ID =? 
        and STU_ID =?
true
④ 当使用Hibernate.initialize() 静态方法 时

	@Test
	public void testOne2ManyLevelStrategy() {
		Clazz clazz =(Clazz) session.get(Clazz.class, 1); 
		System.out.println(clazz.getClass());
		System.out.println(clazz.getStus().size());
		
	
		Student student = new Student();
		
		student.setStuId(1);
		System.out.println(clazz.getStus().contains(student));
		
		Hibernate.initialize(clazz.getStus());
		
	}
运行的SQL

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_0_ 
    from
        CLAZZS clazz0_ 
    where
        clazz0_.CLAZZ_ID=?
class com.baidu.setStrategy.Clazz
Hibernate: 
    select
        count(STU_ID) 
    from
        STUDENTS 
    where
        CLAZZ_ID =?
2
Hibernate: 
    select
        1 
    from
        STUDENTS 
    where
        CLAZZ_ID =? 
        and STU_ID =?
true
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID=?


	/**
	 * Set 的 batch-size 属性: 设定一次初始化 set 集合的数量
	 */
 batch-size 属性

	@Test
	public void testSetBatchSize() {
		List<Clazz> clazzs = session.createQuery("FROM Clazz").list();
		System.out.println(clazzs.size());
		
		for(Clazz clazz:clazzs ){
			if(clazz.getStus() != null)
				System.out.println(clazz.getStus().size());
		}
	}
① 当没有使用batch-size 属性时,

运行的SQL

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_ 
    from
        CLAZZS clazz0_
3
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID=?
2
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID=?
2
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID=?
2
当在clazz的配置文件的set属性中添加 batch-size = "5" :表示一次初始化5条记录

        <set name="stus" table="STUDENTS" lazy="true" batch-size="5">
            <key>
                <column name="CLAZZ_ID" />
            </key>
            <one-to-many class="Student" />
        </set>

运行的SQL

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_ 
    from
        CLAZZS clazz0_
3
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID in (
            ?, ?, ?
        )
2
2
2

fetch属性: 取值为 “select” 或 “subselect” 时, 决定初始化 students 的查询语句的形式;  

                   若取值为”join”, 则决定orders 集合被初始化的时机

	/**
	 * Set 的 fetch 属性: 
	 * 	1. 默认值为select:通过正常的方式来初始化set元素
	 *  2. 可以取值subselect: 
	 *  	① 通过子查询的方式来初始化所有的 set 集合。子查询作为where 子句的 in的条件出现,
	 *  		子查询查询所有1 的一端的ID
	 *      ② 此时lazy 有效,但是batch-size 属性将被忽略,不再起作用。
	 */

	/**
	 * Set 的 fetch 属性: 
	 * 	3. 可以取值为join:  batch-size有效
	 * 		① 在加载 1 的一端的对象时,使用迫切左外连接的方式检索 n 的一端的集合属性
	 * 
	 * 		② 会忽略lazy 属性
	 * 		
	 * 		③ 使用HQL 查询时,会 忽略fetch=join
	 * 		
	 * 		
	 * 迫切左外连接:使用左外连接进行查询,且把集合属性进行初始化
	 */

fetch: 
         ①取值为 select

        <set name="stus" table="STUDENTS" 
        lazy="true" batch-size="2" fetch="subselect">
            <key>
                <column name="CLAZZ_ID" />
            </key>
            <one-to-many class="Student" />
        </set>

	@Test
	public void testSetFetchSelectOrSubselect() {
		
		List<Clazz> clazzs = session.createQuery("FROM Clazz").list();
		System.out.println(clazzs.size());
		
		for(Clazz clazz:clazzs ){
			if(clazz.getStus() != null)
				System.out.println(clazz.getStus().size());
		}
	}
运行的SQL

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_ 
    from
        CLAZZS clazz0_
3
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID in (
            ?, ?
        )
2
2
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID=?
2

        ② 取值为usubselect

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_ 
    from
        CLAZZS clazz0_
3
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID in (
            select
                clazz0_.CLAZZ_ID 
            from
                CLAZZS clazz0_
        )
2
2
2
         ③ 取值为 join
        <set name="stus" table="STUDENTS" 
        lazy="true" batch-size="2" fetch="join">
            <key>
                <column name="CLAZZ_ID" />
            </key>
            <one-to-many class="Student" />
        </set>
	@Test
	public void testSetFetchJoin() {
		
		Clazz clazz = (Clazz) session.get(Clazz.class, 1);
		System.out.println(clazz.getStus().size());
		
		
	}


运行的SQL

使用HQL 查询时,batch-size有效, 会 忽略fetch=join ,

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_ 
    from
        CLAZZS clazz0_
3
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID in (
            ?, ?
        )
2
2
Hibernate: 
    select
        stus0_.CLAZZ_ID as CLAZZ_ID3_0_1_,
        stus0_.STU_ID as STU_ID1_1_1_,
        stus0_.STU_ID as STU_ID1_1_0_,
        stus0_.STU_NAME as STU_NAME2_1_0_ 
    from
        STUDENTS stus0_ 
    where
        stus0_.CLAZZ_ID=?
2

	@Test
	public void testSetFetchJoin() {
		
		Clazz clazz = (Clazz) session.get(Clazz.class, 1);
		System.out.println(clazz.getStus().size());
		
		
	}

运行的SQL

Hibernate: 
    select
        clazz0_.CLAZZ_ID as CLAZZ_ID1_0_1_,
        clazz0_.CLAZZ_NAME as CLAZZ_NA2_0_1_,
        stus1_.CLAZZ_ID as CLAZZ_ID3_0_3_,
        stus1_.STU_ID as STU_ID1_1_3_,
        stus1_.STU_ID as STU_ID1_1_0_,
        stus1_.STU_NAME as STU_NAME2_1_0_ 
    from
        CLAZZS clazz0_ 
    left outer join
        STUDENTS stus1_ 
            on clazz0_.CLAZZ_ID=stus1_.CLAZZ_ID 
    where
        clazz0_.CLAZZ_ID=?
2




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值