类级别检索策略
- 立即检索
在Classes.hbm.xml文件中,以下表示采用立即检索策略:
<class name="cn.itcast.hibernate0909.fetch.Classes" lazy="false">
- 延迟检索
在Classes.hbm.xml文件中,以下表示采用延迟检索策略:
<class name="cn.itcast.hibernate0909.fetch.Classes">
或者
<class name="cn.itcast.hibernate0909.fetch.Classes" lazy="true">
注意:不管SClasses.hbm.xml文件的<class>
元素的lazy属性是true还是false,Session的get()方法及Query的list()方法在School类级别总是使用立即检索策略。
默认的检索策略是立即检索。在Hibernate映射文件中,通过在<class>
上配置 lazy属性来确定检索策略。对于Session的检索方式,类级别检索策略仅适用于load方法;也就说,对于get、qurey检索,持久化对象都会被立即加载而不管lazy是false还是true.一般来说,我们检索对象就是要访问它,因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常(立即检索的情况下),因此我个人并不建议使用load检索;而由于<class>
中的lazy属性还影响到多对一及一对一的检索策略,因此使用load方法就更没必要了。
关联级别检索策略
在<set>
标签上或者在<many-to-one>
上设置两个属性值来控制其检索策略, fetch、lazy
fetch:代表检索时的语句的方式,比如左外连接等。
fetch:join、select 、subselect
lazy:是否延迟加载。
lazy:true、false、extra
分两种情况
1.一对多或多对多
<set fetch="",lazy="">
fetch = join时,采取迫切左外连接查询
lazy不管取什么值都失效,就是取默认值为false。
fetch=select时,生成多条简单sql查询语句
lazy=false:立即检索
lazy=true:延迟检索
lazy=extra:加强延迟检索,非常懒惰,比延迟检索更加延迟
fetch=subselect时,生成子查询
lazy=false:立即检索
lazy=true;延迟检索
lazy=extra:加强延迟检索,非常懒惰,比延迟检索更加延迟
fetch=select时,生成多条简单sql查询语句
可以发现发出了n+1条查询语句。
批量检索
什么叫批量检索,就是多条sql语句才能完成的查询,现在一条sql语句就能解决多条sql语句才能完成的事情。
重新测试
Hibernate: select classes0_.cid as cid0_, classes0_.cname as cname0_, classes0_.description as descript3_0_ from Classes classes0_
Hibernate: select students0_.cid as cid0_1_, students0_.sid as sid1_, students0_.sid as sid1_0_, students0_.sname as sname1_0_, students0_.description as descript3_1_0_, students0_.cid as cid1_0_ from Student students0_ where students0_.cid in (?, ?, ?, ?)
菜肉哥!
包子哥!
caicai
CCC
zxczxc
qweqwe
可以看结果,只发送两条sql语句,第一条是查询班级的,第二条是一看使用关键字 IN 来将所有的班级ID含括在内
这样就只需要发送一条sql语句,来达到发送5条sql语句才能完成的功能。 这就是批量检索
上面是从一查多,batch-size放在set中。从多查一呢,在many-to-one中并没有batch-size这个属性。注意了,此时batch-size放在一方的class中
疑问一:为什么从一到多,batch-size就放在set中,而从多到一,batch-size也是放在一方的class中?
这样去想:一方查多方,在一方的set中就代表着多方的对象,将batch-size放在set中,就可以理解查多方的时候,就使用批量检索了。
多方查一方,在一方的class中设置batch-size。可以理解,当多方查到一方时,在一方的映射文件中的class部分遇到了batch-size就知道查询一方时需要批量检索了
这样应该更好理解和记忆。
如果抓取策略改成join
从sql语句可以看出,join用的是左外连接.。join该需求变成一条sql语句
2.多对一或一对一时
fetch可以取值为:join,select
lazy:false,proxy,no-proxy
当fetch=join,lazy会失效,生成的sql是迫切左外连接
如果我们使用query时,hql是我们自己指定的,那么fetch=join是无效的,不会生成迫切左外连接,这时lazy重新启用
当fetch=select,lazy不失效,生成简单sql语句,
lazy=false:立即检索
lazy=proxy:这时关联对象采用什么样的检索策略取决于关联对象的类级别检索策略.就是说参考<class>上的lazy的值