lazy概念:
只有真正使用该对象时,才会创建,对于hibernate而言,正真使用的时候才会发出sql语句,只对加载有效
hibernate lazy策略可以使用在:
* <class>标签上,可以取值:true/false( hibernate 3.x 代理默认打开)
* <property>标签上,可以取值:true/false需要类增强工具
* <set><list>标签上,可以取值:true/false/extra
* <one-to-one><many-to-one>单端关联上,可以取值:false/proxy/noproxy
Lazy的实现:
hibernate采用第三方的CGLIB库,它可以对我们的类生成代理类(控制原对象,并对原对象的功能进行增强)它继承原先的类,生成一个子类作为一个代理类,当真正调用代理类上的方法时,它会看一看目标对象是否加载,如果没加载它才会真正的访问。
1、类上的懒加载
- 默认开启,只对普通属性有效
- load支持类上的懒加载,但前提必须是懒加载开启
class上的Lazy策略例:
例:hibernate_lazy_for_class
- <class>标签上,可以取值:true/false( hibernate 3.x 代理默认打开)
- <class>标签上的lazy特性只对普通属性起作用
- hibernate支持lazy策略只有在session打开状态下有效
System.out.println("group.name=" + group.getName());
//不能正确输出,抛出LazyInitializationException 异常,因为session已经关闭(session线程不安全)
//hibernate支持lazy策略只有在session打开状态下有效
解决方法:
每个线程绑定自己的session,用到懒加载拦截器和ThreadLocal技术
解决懒加载的技术
配置openSessionInview拦截器,一直开启session 直到对象都输出完成
如何把当前线程绑定到session上?
采用ThreadLocal里的set方法,把当前线程作为key,传过来的session作为value
懒加载拦截器
<filter>
<filter-name>hibernateFilter</filter-name><filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
ThreadLocal的原理
ThreadLocal类主要由四个方法组成:initialValue(),get(),set(T),remove()
在ThreadLocal类中有一个线程安全的Map,用于存储每一个线程的变量的副本。
这个map在同一时刻只能有一个线程访问
public class ThreadLocal
{
private Map values = Collections.synchronizedMap(new HashMap());;//线程安全
// set方法—设置当前线程的局部变量
public void set(Object newValue) {
//key是当前线程
values.put(Thread.currentThread(), newValue);
}
//get方法—返回当前线程的局部变量
public Object get() {
Thread curThread = Thread.currentThread();
Object o=values.get(currentThread);
//判断Map中是否包含这样的key
if (o == null && !values.containsKey(curThread))
{ o = initialValue();
values.put(curThread, o);
}
return o;
}
// initialValue方法—返回当前线程的局部变量的初始值
protected Object initialValue()
{ return null;
}
// remove方法—移除当前线程的局部变量
public void remove() {
//通过key将键值对删除
values.remove(Thread.currentThread());
}
}
说明:当线程处于活动状态时它会持有该线程的局部变量的引用,当该线程运行结束后,该线程拥有的局部变量都会结束生命周期。
2、集合上的懒加载
只适用于one to many和many to many
类上的懒加载不会影响集合上的懒加载
可以取值:true/false/extra
(1)类上的懒加载true,集合上的懒加载true
(2)类上懒加载开启,集合上的懒加载关闭
(3)都关闭
(4)类关闭,集合开启。
(5)类开启。集合extra。
extra发sql语句更智能,效率高
extra和true的区别:如果为true,那么查找集合里的元素个数时,会查找数据库里的所有记录,生成对象设置到set集合,而extra只查找有多少记录,并不会把记录生成对象设置到set集合
3、单端上的懒加载
只用在one to one和many to one 上,指定一的一端如何加载
可以取值:false/proxy/noproxy
默认的取值是proxy
指定一的一方如何加载
有三种方式完成懒加载
网友评论