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

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.

你可能感兴趣的:(JAVA,web)