(3) 预先抓取
预先抓取指的是Hibernate通过select语句使用outer join(外连接,一般是左外连接left outer join)来获得对象的关联实例或者关联集合(集合被初始化了,这是重点)。分两种情况来讨论
情况一:对象之间全都是立即加载
假设对象之间全都是立即加载,有三张表:班级(Team)、学生(Student)和身份证(Certificate),有如下代码:
-----//打开Session,开启事务
Team team = (Team)session.get(Team.class,1);
-----//提交事务,关闭Session
上述程序运行后控制台的显示结果如下:
Hibernate:select t.* from team t where t.id=?
Hibernate:select s.* from student s where team.id=?
Hibernate:select c.* fromcertificate c where c.id=?
Hibernate:select c.* fromcertificate c where c.id=?
可见通过取得班级对象,从而递归的取得了学生和身份证对象。Hibernate共发送4条sql语句来得到这些数据,如果关联的对象很多(如果有100个学生,则要发送100条sql语句去取得100个身份证),使用立即检索方式是不适合的。
情况二:对象之间全都是预先抓取
假设对象之间全都是预先抓取,同样运行上面的代码,控制台显示结果如下:
Hibernate:select t.*,s.*,c.* from team t
left outer join student s on t.id = s.team_id
left outer join certificate c on s.id = c.id where team0_id=?
只用一条sql语句就把使用立即检索时用的4条sql语句包括了。使用预先抓取不用理会有多少个学生,都是上面一条语句就可以把所有学生的身份证资料取出来,而是用立即加载的话,有100个学生就需要发送100条sql语句。但是使用1条sql语句来完成原先要100条才能完成的功能,给这一条语句带来的负担也是比较重的。可以使用hibernate.max_fetch_depth来控制。该值为1表示只允许外连接1个表,为0则表示不允许外连接,即外连接失效。
实际使用时,一对多和多对多关系推荐使用延迟加载,而一对一和多对一关系推荐使用预先加载。