抓取策略应用的范围及作用:
主要用于set集合对象在提取数据时对hibernate底层的sql语句的操作,即由一个对象对关联对象查询,发出怎样的sql语句的机制。
以学生和班级为例:
抓取策略:
1、研究的主要是set集合如何提取数据
2、在Classes.hbm.xml文件中
<set fetch="join/select/subselect">
join 左外连接
如果把需求分析翻译sql语句,存在子查询,这个时候用该策略不起作用
select 默认
先查询一的一端,再查询多的一端
subselect 子查询
如果需要分析翻译成sql语句存在子查询,这个时候用该策略效率最高
例子示例:
/**
* 查询所有班级下的所有学生
* 解决问题的方案:子查询 fetch="subselect"
*/
//@Test
public void testAll_Classes(){
Session session = sessionFactory.openSession();
List<Classes> cList = session.createQuery("from Classes").list();
for(Classes classes:cList){
Set<Student> students = classes.getStudents();
for(Student student:students){
System.out.println(student.getSname());
}
}
session.close();
}
对应的class映射文件配置
<set name="students" cascade="save-update" inverse="true" fetch="join">
<!--
key是用来描述外键
-->
<key>
<column name="cid"></column>
</key>
<one-to-many class="cn.itcast.hiberate.sh.domain.Student"/>
</set>
对应的hibernate输出的sql语句
Hibernate:
select
classes0_.cid as cid0_,
classes0_.cname as cname0_,
classes0_.description as descript3_0_
from
Classes classes0_
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
students0_.sid as sid1_0_,
students0_.sname as sname1_0_,
students0_.description as descript3_1_0_,
students0_.cid as cid1_0_
from
Student students0_
where
students0_.cid=?
当配置文件改为
输出sql语句为:
Hibernate:
select
classes0_.cid as cid0_,
classes0_.cname as cname0_,
classes0_.description as descript3_0_
from
Classes classes0_
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
students0_.sid as sid1_0_,
students0_.sname as sname1_0_,
students0_.description as descript3_1_0_,
students0_.cid as cid1_0_
from
Student students0_
where
students0_.cid=?
不存在子查询的列子:
@Test
/**
* 查询班级号为1的所有学生
*/
public void testQueryClasses_Id(){
Session session = sessionFactory.openSession();
Classes classes = (Classes)session.get(Classes.class, 1L);
Set<Student> students = classes.getStudents();
for(Student student:students){
System.out.println(student.getSname());
}
session.close();
}
配置文件为:
输出sql语句为:
Hibernate:
select
classes0_.cid as cid0_0_,
classes0_.cname as cname0_0_,
classes0_.description as descript3_0_0_
from
Classes classes0_
where
classes0_.cid=?
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
students0_.sid as sid1_0_,
students0_.sname as sname1_0_,
students0_.description as descript3_1_0_,
students0_.cid as cid1_0_
from
Student students0_
where
students0_.cid=?
配置文件为: sql语句为:
Hibernate:
select
classes0_.cid as cid0_1_,
classes0_.cname as cname0_1_,
classes0_.description as descript3_0_1_,
students1_.cid as cid0_3_,
students1_.sid as sid3_,
students1_.sid as sid1_0_,
students1_.sname as sname1_0_,
students1_.description as descript3_1_0_,
students1_.cid as cid1_0_
from
Classes classes0_
left outer join
Student students1_
on classes0_.cid=students1_.cid
where
classes0_.cid=?
一般来讲,发出的sql语句越少性能越高。
关于懒加载:
当要取出的set集合中的数据量很大时,我们使用懒加载,即当我们需要用到该对象时,才从数据库里加载,即当出现使用student.getXxx()等方法时才加载session.get()方法是不加载。
懒加载
1、类的懒加载
1、利用session.load方法可以产生代理对象
2、在session.load方法执行的时候并不发出sql语句
3、在得到其一般属性的时候发出sql语句
4、只针对一般属性有效,针对标示符属性是无效的
5、默认情况就是懒加载
2、集合的懒加载
false 当session.get时,集合就被加载出来了
true 在遍历集合的时候才加载
extra
针对集合做count,min,max,sum等操作
3、单端关联的懒加载(多对一)
<many-to-one lazy="false/no-proxy/proxy"> no-porxy 默认值 true
根据多的一端加载一的一端,就一个数据,所以无所谓
总结:懒加载主要解决了一个问题:类、集合、many-to-one在时候发出SQL语句,加载数据