1、显而易见的概念
懒加载——也被称为延迟加载,它在查询的时候不会立刻访问数据库,而是返回代理对象,当真正去使用对象的时候才会访问数据库。
急加载——就是只要我们实体做了关联,全部一次性执行完所有的SQL语句
2、@OneToMany
****默认为懒加载****
@Test
public void find(){
Session s= sessionFactory.openSession();
List teacher= s.createQuery("from TeacherEntity").list();
for(TeacherEntity t:teacher){
t.getTname();
List lists= t.getStuList();
for(StudentEntity stu:lists){
System.out.println(stu.getSname());
}
}
s.close();
}
懒加载结果:
Hibernate: select teacherent0_.t_id as t_id1_5_, teacherent0_.t_name as t_name2_5_ from t_teacher2 teacherent0_
Hibernate: select stulist0_.tid as tid3_4_0_, stulist0_.s_id as s_id1_4_0_, stulist0_.s_id as s_id1_4_1_, stulist0_.s_name as s_name2_4_1_, stulist0_.tid as tid3_4_1_ from t_student2 stulist0_ where stulist0_.tid=?
曹操
刘备
Hibernate: select stulist0_.tid as tid3_4_0_, stulist0_.s_id as s_id1_4_0_, stulist0_.s_id as s_id1_4_1_, stulist0_.s_name as s_name2_4_1_, stulist0_.tid as tid3_4_1_ from t_student2 stulist0_ where stulist0_.tid=?
孙权
急加载结果
Hibernate: select teacherent0_.t_id as t_id1_5_, teacherent0_.t_name as t_name2_5_ from t_teacher2 teacherent0_
Hibernate: select stulist0_.tid as tid3_4_0_, stulist0_.s_id as s_id1_4_0_, stulist0_.s_id as s_id1_4_1_, stulist0_.s_name as s_name2_4_1_, stulist0_.tid as tid3_4_1_ from t_student2 stulist0_ where stulist0_.tid=?
Hibernate: select stulist0_.tid as tid3_4_0_, stulist0_.s_id as s_id1_4_0_, stulist0_.s_id as s_id1_4_1_, stulist0_.s_name as s_name2_4_1_, stulist0_.tid as tid3_4_1_ from t_student2 stulist0_ where stulist0_.tid=?
曹操
刘备
孙权
@ManyToOne
**默认为急加载**
@Test
public void findManyToOne(){
//获得session
Session s= sessionFactory.openSession();
String hql="from StudentEntity";
List list=s.createQuery(hql).list();
for(StudentEntity stu:list){
System.out.println(stu.getSname());
}
}
**急加载结果:**
Hibernate: select studentent0_.s_id as s_id1_4_, studentent0_.s_name as s_name2_4_, studentent0_.tid as tid3_4_ from t_student2 studentent0_
Hibernate: select teacherent0_.t_id as t_id1_5_0_, teacherent0_.t_name as t_name2_5_0_, stulist1_.tid as tid3_4_1_, stulist1_.s_id as s_id1_4_1_, stulist1_.s_id as s_id1_4_2_, stulist1_.s_name as s_name2_4_2_, stulist1_.tid as tid3_4_2_ from t_teacher2 teacherent0_ left outer join t_student2 stulist1_ on teacherent0_.t_id=stulist1_.tid where teacherent0_.t_id=?
Hibernate: select teacherent0_.t_id as t_id1_5_0_, teacherent0_.t_name as t_name2_5_0_, stulist1_.tid as tid3_4_1_, stulist1_.s_id as s_id1_4_1_, stulist1_.s_id as s_id1_4_2_, stulist1_.s_name as s_name2_4_2_, stulist1_.tid as tid3_4_2_ from t_teacher2 teacherent0_ left outer join t_student2 stulist1_ on teacherent0_.t_id=stulist1_.tid where teacherent0_.t_id=?
曹操
刘备
孙权
**懒加载结果:**
Hibernate: select studentent0_.s_id as s_id1_4_, studentent0_.s_name as s_name2_4_, studentent0_.tid as tid3_4_ from t_student2 studentent0_
曹操
刘备
****修改代码,循环获取关联对象(One一方)****
` @Test
public void findManyToOne(){
//获得session
Session s=sessionFactory.openSession();
String hql="from StudentEntity";
List list=s.createQuery(hql).list();
for(StudentEntity stu:list){
System.out.println(stu.getSname());
//获取one方值
System.out.println(stu.getTeacher().getTname());
}
}
**结果如下:**
Hibernate: select studentent0_.s_id as s_id1_4_, studentent0_.s_name as s_name2_4_, studentent0_.tid as tid3_4_ from t_student2 studentent0_
曹操
Hibernate: select teacherent0_.t_id as t_id1_5_0_, teacherent0_.t_name as t_name2_5_0_, stulist1_.tid as tid3_4_1_, stulist1_.s_id as s_id1_4_1_, stulist1_.s_id as s_id1_4_2_, stulist1_.s_name as s_name2_4_2_, stulist1_.tid as tid3_4_2_ from t_teacher2 teacherent0_ left outer join t_student2 stulist1_ on teacherent0_.t_id=stulist1_.tid where teacherent0_.t_id=?
陈老师
刘备
陈老师
孙权
Hibernate: select teacherent0_.t_id as t_id1_5_0_, teacherent0_.t_name as t_name2_5_0_, stulist1_.tid as tid3_4_1_, stulist1_.s_id as s_id1_4_1_, stulist1_.s_id as s_id1_4_2_, stulist1_.s_name as s_name2_4_2_, stulist1_.tid as tid3_4_2_ from t_teacher2 teacherent0_ left outer join t_student2 stulist1_ on teacherent0_.t_id=stulist1_.tid where teacherent0_.t_id=?
张老师
改进代码:
@Test
public void findManyToOne(){
//获得session
Session s=sessionFactory.openSession();
//关联查询
String hql="select new com.lovo.hibernate.manytoone.StuDto(t.tname,s.sname) from StudentEntity s left join s.teacher t ";
//用DTO对象接收
List listObj=s.createQuery(hql).list();
//循环遍历出DTO的数据
for(StuDto dto:listObj){
System.out.println(dto.getSname()+"/"+dto.getTname());
}
}
输出结果:
Hibernate: select teacherent1_.t_name as col_0_0_, studentent0_.s_name as col_1_0_ from t_student2 studentent0_ left outer join t_teacher2 teacherent1_ on studentent0_.tid=teacherent1_.t_id
曹操/陈老师
刘备/陈老师
孙权/张老师
看你以上代码该给个了结的时候了。
1、急加载,在多对一的情况下默认是急加载,也就是查询多会一次性把一的一方全部查询出来。如果我们不想现在用关联对象里面的属性,可以选择懒加载。急加载会先查询出主对象然后根据主对象执行N条语句查询出关联对象。SQL会出现1+N查询的情况。
2、懒加载,在一对多的情况下默认是懒加载,不去运用关联对象属性时,不会进行SQL查询。但是如果是循环查询关联对象会出现调用一个属性执行一条SQL语句的情况,上面代码已经充分说明。如果不对关联对象进行循环查询不会出现N+1的情况,我相信大家也不会用懒加载时候,同一时间去查询出关联对象。
3、如果我们想同一时间查询出所有关联对象,而希望SQL语句不会出现N+1的悲剧发生,建议大家运用关联查询,把查询后的结果封装到自定义的DTO对象中。DTO作为数据传输对象可以传输到任何对象中去,当然包括VO.