您的位置:首页 > 其它

Hibernate懒加载急加载我们需要注意的问题

2017-12-28 10:41 423 查看
1、显而易见的概念

懒加载——也被称为延迟加载,它在查询的时候不会立刻访问数据库,而是返回代理对象,当真正去使用对象的时候才会访问数据库。

急加载——就是只要我们实体做了关联,全部一次性执行完所有的SQL语句

2、@OneToMany

****默认为懒加载****


@Test
public void find(){
Session s=  sessionFactory.openSession();
List<TeacherEntity> teacher=    s.createQuery("from  TeacherEntity").list();
for(TeacherEntity t:teacher){
t.getTname();
List<StudentEntity> 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<StudentEntity> 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<StudentEntity> 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<StuDto> 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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate