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