Hibernate 批量加载(立即、延迟)

一、批量立即加载

以上面的例子为例:

Team对学生采取的是立即加载

 

客户端:

Session session = SessionUtil.getSession();
  Transaction tran = session.beginTransaction();
  Query query = session.createQuery("from Team");
  List list = query.list();
  tran.commit();
  session.close();

 

数据库中有5个TEAM,对应每个TEAM都有学生,那么打印语句:

Hibernate: select team0_.ID as ID0_, team0_.Name as Name0_ from test.team team0_

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID=?

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID=?

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID=?

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID=?

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID=?

对于以上语句,首先查询TEAM的值,因为采取的是立即加载,对有多少个班级就发出多少条SQL语句。如果有100个班级,那么就会发出100条的查询语句,性能可以想象!!所以一定要改变这种情况。

我们可以在一对多的一的这端的:

 <set name="students" inverse="true" cascade="all" lazy="false" batch-size="2">
            <key column="teamID"></key>
            <one-to-many class="com.vo.Student"></one-to-many>
        </set>

 

设置batch-size的值,首先来看看采用这种策略以后的语句:

Hibernate: select team0_.ID as ID0_, team0_.Name as Name0_ from test.team team0_

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID in (?, ?)

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID in (?, ?)

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID=?

 

发现采取的查询策略改变了,SQL的条件是where id in(?,?)

因为设置了批量加载为2,假如有100个班级,那么只要加载50次,如果设置为3,那么就是加载100/3=33次,剩余的一次采用立即加载的方式,所以这也是为什么上面例子的最后一句是立即加载的原因。

 

没有用batch_size的SQL采用ID=?的形式

采用batch_size的SQL采用ID in()的形式。

这就是为什么SQL语句会减少的原因。

二、批量延迟加载

首先在TEAM的配置文件中更改对学生的加载策略为延迟加载。并且设置批量加载为2.

客户端:

Session session = SessionUtil.getSession();
  Transaction tran = session.beginTransaction();
  Query query = session.createQuery("from Team");
  List list = query.list();
  Team team = (Team)list.get(0);
  System.out.println(team.getName()+" 学生数量:"+team.getStudents().size());
  
   team = (Team)list.get(2);
  System.out.println(team.getName()+" 学生数量:"+team.getStudents().size());
  
   team = (Team)list.get(4);
  System.out.println(team.getName()+" 学生数量:"+team.getStudents().size());
  tran.commit();
  session.close();

 

打印语句:

Hibernate: select team0_.ID as ID0_, team0_.Name as Name0_ from test.team team0_

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID in (?, ?)

二中 学生数量:2

一职 学生数量:1

Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID in (?, ?)

十一中 学生数量:1

 

第1条的解释:首先去查询TEAM的集合对象。

第2条的解释:因为采用的是延迟加载,只有当用到对象的属性的时候才发送SQL去数据库取值,所以发出第2条语句,因为设置了批量加载为2,所以发出的该条SQL语句将把班级序号为1和2的班级都查出来,所以当我们去取得班级为2的时候就不再发送查询语句了。

第3条SQL解释:因为打印的是第4个班级,所以要再发送一条查询语句。

 

对于批量加载也不是设置的batch_size越大越好。

例如,对于A-B(有5个B对象),我们设置的batch_size=5,当我们只要查询中间的一条数据,系统会发出5条SQL语句去查询。反而增加了系统的开销。

 

你可能感兴趣的:(sql,Hibernate)