一、lazy概述
在ORM中,当应用程序需要对关联关系的实体进行查询时,hibernate提供了一种查询加载方案——Lazy:延迟加载。当我们通过一个实体可以查询到引用的关联实体时,并不是马上就读取这个实体或者集合,而是在真正调用的时候才会发出查询语句,进行读取,这样可以提高系统的性能。
lazy策略使用范围:
<class>标签上:可以取值true/false。
<property>标签上,属性延迟加载,可以取值true/false,这个特性需要类增强。对属性或返回单值的关联而言,当其实例变量被访问的时候进行抓取。需要编译期字节码强化,因此这一方法很少是必要的。
<set>/<list>等集合上,可以取值为true/false/extra。延迟集合抓取,对集合而言这是默认行为。
<one-to-one>/<many-to-one>等标签上,可以取值false/proxy/no-proxy
二、使用
1、Class的lazy:可以取值true/false
设置<class>标签中的lazy="true",或是保持默认(默认为true)。
那么在使用load方法加载数据时,只有确实用到数据的时候才会发出sql语句;这样有可能减少系统的开销。
2、collection的Lazy:可以取值true,false,extra
设置集合上的lazy=extra,此时的效果和lazy属性的默认值是基本一样的。但是推荐使用这个属性值,因为在统计时这种情况显得比较智能。当然延迟是有效果的。
true:默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其集合元素的数据。
false:取消懒加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据。
extra:一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据。
三、Lazy的有效期
Lazy的有效期:只有在session打开的时候才有效;session关闭后lazy就没效了。
例如如下访问就会出现问题:
可以看到在session关闭之后,再访问user.getName().就会报错,可以看一下访问的过程:
那有没有解决的方法的呢?答案是必须的,那就是使用threadlocal。我这里只提供方法,具体实现就不一一到来了。
四、load/get方法
1、查找时,都会优先从session的缓存中查找。
2、Load返回的是代理对象,等到真正要用到对象的内容时才发起SQL语句.get直接发起SQL语句从数据库中取出,所以,get不支持延迟加载,而load支持。
3、当查询特定的数据库中不存在的数据时,get会返回null,而load则抛出异常。
这就是关于lazy的一些相关知识,lazy只是hibernate抓取策略中的一种,hibernate的四大原生抓取策略在下篇博客中介绍。