定义:通过一个对象,如何对关联对象发出sql语句,就是~。
研究的主要是 set 集合如何提取数据。
在Classes.hbm.xml 文件中<set name='' cascade='' inverse='' lazy='' fetch='join/select/subselect'>,其中:
join:左外连接,如果把需求分析翻译成sql语句存在子查询,这时候用join策略不起作用。
select:默认的,先查询一的一端,再查询多的一端。
subselect:子查询
懒加载:决定什么时候发出sql语句。
抓取策略:决定怎么样发出sql语句。
子查询:select *
from student
where cid in (select cid from classes)
1、项目 hibernante_sh_optimize
结论:如果需求分析翻译成sql 语句存在子查询,这时候用“子查询”效率最高。
结果:发出两条 sql 语句
同样的代码,修改<set name='' cascade='' inverse='' lazy='' fetch='join'>,结果只发出一条 sql 语句
注:抓取策略和懒加载只是优化策略的一种方式而已。HQL语句可以达到同样的效果,具体用哪个视情况而定。
研究的主要是 set 集合如何提取数据。
在Classes.hbm.xml 文件中<set name='' cascade='' inverse='' lazy='' fetch='join/select/subselect'>,其中:
join:左外连接,如果把需求分析翻译成sql语句存在子查询,这时候用join策略不起作用。
select:默认的,先查询一的一端,再查询多的一端。
subselect:子查询
懒加载:决定什么时候发出sql语句。
抓取策略:决定怎么样发出sql语句。
子查询:select *
from student
where cid in (select cid from classes)
1、项目 hibernante_sh_optimize
2、建包和类 cn.google.hibernate.sh.test.FetchTest
public class FetchTest extends HiberanteUtils{
static{
url = "hibernate.cfg.xml";
}
/**
* n+1 条查询
* 解决问题的方案:子查询
* 查询n个班级,再根据所有班级id,查询学生表(一共发出n+1条 sql 语句)
*/
@Test
public void testAll_Classes(){
Session session = factory.openSession();
List<Classes> cList = session.createQuery("from Classes").list();
for(Classes classes: cList){
Set<Student> students = classes.getStudents();
for(Student student: students){
s.o.p(student.getSname());
}
}
session.close();
}
/**
* 代码相同,但是把Classes.hbm.xml中的<set name='' cascade='' inverse='' lazy='' fetch='subselect'>
* 发出的sql 语句立刻变为“子查询”格式
*/
@Test
public void testAll_Classes(){
Session session = factory.openSession();
List<Classes> cList = session.createQuery("from Classes").list();
for(Classes classes: cList){
Set<Student> students = classes.getStudents();
for(Student student: students){
s.o.p(student.getSname());
}
}
session.close();
}
}
结论:如果需求分析翻译成sql 语句存在子查询,这时候用“子查询”效率最高。
------------------------------------------------------------------------------
需求:查询某一个班级所有学生
// <set name='' cascade='' inverse='' lazy='' fetch='subselect'> 子查询
@Test
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 语句
同样的代码,修改<set name='' cascade='' inverse='' lazy='' fetch='join'>,结果只发出一条 sql 语句
---------------------------------------------------------------------------------------------------------------------
结合懒加载和抓取策略:研究对象是set集合
fetch策略 | lazy | 有没有子查询 | 什么时候发出sql语句 | 说明 |
select | true/false | 发出n+1条sql |
如果lazy=true,在遍历集合时发出。 如果lazy=false ,在一开始发出 | |
subselect | true/false | 存在子查询 | 发出两条sql语句 | 同上 |
join | false | 存在子查询 | 当查询classes时,把 classes 和 student 全查询出来 | 此时 join没用 |
join | true | 存在子查询 | 当遍历student时发出查询student | join没用 |
join | true | 不是子查询 | 在session.get(classes)时全部查询出来 | 这时lazy没用 |
注:抓取策略和懒加载只是优化策略的一种方式而已。HQL语句可以达到同样的效果,具体用哪个视情况而定。