Hibernate的fetch
hibernate抓取策略fetch详解
一、hibernate抓取策略(单端代理的批量抓取fetch=select(默认)/join)
测试用例:
Student student = (Student) session.get(Student.class, 43);
System.out.println("student name "+student.getName());
System.out.println("class name "+student.getClasses().getName());
1)保持默认,同fetch="select",如:
<many-to-one name="classes" column="classesid" fetch="select"/>
fetch="select"会另外发送一条select语句抓取当前对象关联实体或集合
执行结果:2条语句
Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.class_id as class3_1_0_ from student student0_ where student0_.id=?
student name ccc
Hibernate: select myclass0_.id as id0_0_, myclass0_.name as name0_0_ from class myclass0_ where myclass0_.id=?
class name 09002
2)设置fetch="join",如:
<many-to-one name="classes" column="classesid" fetch="join"/>
fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合,此时lazy会失效。
执行结果:一条join语句
Hibernate: select student0_.id as id1_1_, student0_.name as name1_1_, student0_.class_id as class3_1_1_, myclass1_.id as id0_0_, myclass1_.name as name0_0_ from student student0_ inner join class myclass1_ on student0_.class_id=myclass1_.id where student0_.id=?
student name ccc
class name 09002
二、hibernate抓取策略(集合代理的批量抓取,fetch=select(默认)/join/subselect)
测试用例:
MyClass class1 = (MyClass) session.load(MyClass.class, 28);
System.out.println("班级名:" + class1.getName());
Set<Student> students = class1.getStudents();
System.out.println("班级人数:" + students.size());
if (students != null && !students.isEmpty()) {
Iterator<Student> iterator = students.iterator();
System.out.print("学生姓名:");
while (iterator.hasNext()) {
Student student = iterator.next();
System.out.println(student.getName());
}
}
1)保持默认,同fetch="select",如:
<set name="students" inverse="true" fetch="select">
fetch="select",另外发送一条select语句抓取当前对象关联实体或集合
测试结果:2条独立的查询语句
Hibernate: select myclass0_.id as id0_0_, myclass0_.name as name0_0_ from class myclass0_ where myclass0_.id=?
班级名:09002
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
班级人数:3
学生姓名:ccc
bbb
aaa
(2)设置fetch="join",如:
<set name="students" inverse="true" fetch="join">
fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合,此时lazy会失效
测试结果:1条独立的join查询语句
Hibernate: select myclass0_.id as id0_1_, myclass0_.name as name0_1_, students1_.class_id as class3_0_3_, students1_.id as id3_, students1_.id as id1_0_, students1_.name as name1_0_, students1_.class_id as class3_1_0_ from class myclass0_ left outer join student students1_ on myclass0_.id=students1_.class_id where myclass0_.id=?
班级名:09002
班级人数:3
学生姓名:aaa
ccc
bbb
(3)设置fetch="subselect",如:用在查询语句中
<set name="students" inverse="true" fetch="subselect">
fetch="subselect",另外发送一条select语句抓取在前面查询到的所有实体对象的关联集合
测试用例:
List<MyClass> classes = session.createQuery("from MyClass where id in (27,28,29)").list();
Iterator<MyClass> iterator1 = classes.iterator();
while(iterator1.hasNext()){
MyClass class1 = iterator1.next();
System.out.println("班级名:" + class1.getName());
Set<Student> students = class1.getStudents();
System.out.println("班级人数:" + students.size());
if (students != null && !students.isEmpty()) {
Iterator<Student> iterator = students.iterator();
System.out.print("学生姓名:");
while (iterator.hasNext()) {
Student student = iterator.next();
System.out.println(student.getName());
}
}
}
当不设fetch="subselect" ,即::<set name="students" inverse="true">
结果如下:执行了4条查询语句,其中有3条关联查询语句。
Hibernate: select myclass0_.id as id0_, myclass0_.name as name0_ from class myclass0_ where myclass0_.id in (27 , 28 , 29)
班级名:09002
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
班级人数:0
班级名:09003
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
班级人数:3
学生姓名:ccc
aaa
bbb
班级名:09004
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
班级人数:3
学生姓名:ccc
bbb
aaa
当设fetch="subselect" ,即:<set name="students" inverse="true" fetch="subselect">,结果如下:
执行了2条查询语句,其中有1条子查询语句(嵌套子查询)
Hibernate: select myclass0_.id as id0_, myclass0_.name as name0_ from class myclass0_ where myclass0_.id in (27 , 28 , 29)
班级名:09002
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id in (select myclass0_.id from class myclass0_ where myclass0_.id in (27 , 28 , 29))
班级人数:0
班级名:09003
班级人数:3
学生姓名:ccc
aaa
bbb
班级名:09004
班级人数:3
学生姓名:bbb
ccc
aaa
总结:
hibernate抓取策略(单端代理的批量抓取) 保持默认,同fetch="select",如: fetch="select",另外发送一条select语句抓取当前对象关联实体或集合
2.hibernate抓取策略(单端代理的批量抓取) 设置fetch="join",如: fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合 此时lazy会失效
3.hibernate抓取策略(集合代理的批量抓取) 保持默认,同fetch="select",如: fetch="select",另外发送一条select语句抓取当前对象关联实体或集合
4.hibernate抓取策略(集合代理的批量抓取) 设置fetch="join",如: fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合 此时lazy会失效
5.hibernate抓取策略(集合代理的批量抓取) 设置fetch="subselect",如: fetch="subselect",另外发送一条select语句抓取在前面查询到的所有实体对象的关联集合
6.hibernate抓取策略,,batch-szie在<class>上的应用 batch-size属性,可以批量加载实体类,参见:Classes.hbm.xml 当查classes对象时发出9条hql语句配置过后batch-size=3后会之发9/3=3条hql语句,提高性能
7.hibernate抓取策略,batch-szie在集合上的应用
当查students对象时发出10条hql语句配置过后batch-size=5后会之发10/5=2条hql语句,提高性能
总体上分析:默认是fetch="select" 当配置fetch="join"时直接查询包含的对象或者集合lazy失效。 |
上一篇: 自定义分布式锁实现接口幂等性