blogjava-凯发k8网页登录

blogjava-凯发k8网页登录http://www.blogjava.net/badboyryan/category/20400.html
在恰当的时间、地点以恰当的方式表达给恰当的人...  阅读的时候请注意分类,佛曰我日里面是谈笑文章,其他是各个分类的文章,积极的热情投入到写博的队伍中来,支持blogjava做大做强!向dudu站长致敬>> > (qq群侠客岛:26858781)
精品推荐:谈笑有鸿儒   资源整合,门户网站   java名人堂
zh-cnwed, 07 mar 2007 17:28:58 gmtwed, 07 mar 2007 17:28:58 gmt60 延迟初始化错误(error lazyinitializer)是如何产生的? http://www.blogjava.net/badboyryan/articles/102144.html坏男孩坏男孩tue, 06 mar 2007 06:08:00 gmthttp://www.blogjava.net/badboyryan/articles/102144.htmlhttp://www.blogjava.net/badboyryan/comments/102144.htmlhttp://www.blogjava.net/badboyryan/articles/102144.html#feedback0http://www.blogjava.net/badboyryan/comments/commentrss/102144.htmlhttp://www.blogjava.net/badboyryan/services/trackbacks/102144.html 选自<<精通hibernate:java对象持久化技术详解>> 作者: 来源:www.javathinker.org
如果转载,请标明出处,谢谢


延迟初始化错误是运用hibernate开发项目时最常见的错误。如果对一个类或者集合配置了延迟检索策略,那么必须当代理类实例或代理集合处于持久化状态(即处于session范围内)时,才能初始化它。如果在游离状态时才初始化它,就会产生延迟初始化错误。

下面把customer.hbm.xml文件的元素的lazy属性设为true,表示使用延迟检索策略:

当执行session的load()方法时,hibernate不会立即执行查询customers表的select语句,仅仅返回customer类的代理类的实例,这个代理类具由以下特征:

(1) 由hibernate在运行时动态生成,它扩展了customer类,因此它继承了customer类的所有属性和方法,但它的实现对于应用程序是透明的。
(2) 当hibernate创建customer代理类实例时,仅仅初始化了它的oid属性,其他属性都为null,因此这个代理类实例占用的内存很少。
(3) 当应用程序第一次访问customer代理类实例时(例如调用customer.getxxx()或customer.setxxx()方法), hibernate会初始化代理类实例,在初始化过程中执行select语句,真正从数据库中加载customer对象的所有数据。但有个例外,那就是当 应用程序访问customer代理类实例的getid()方法时,hibernate不会初始化代理类实例,因为在创建代理类实例时oid就存在了,不必 到数据库中去查询。

提 示:hibernate采用cglib工具来生成持久化类的代理类。cglib是一个功能强大的java字节码生成工具,它能够在程序运行时动态生成扩展 java类或者实现java接口的代理类。关于cglib的更多知识,请参考:http://cglib.sourceforge.net/。

以下代码先通过session的load()方法加载customer对象,然后访问它的name属性:

tx = session.begintransaction();
customer customer=(customer)session.load(customer.class,new long(1));
customer.getname();
tx.commit();

在 运行session.load()方法时hibernate不执行任何select语句,仅仅返回customer类的代理类的实例,它的oid为1,这 是由load()方法的第二个参数指定的。当应用程序调用customer.getname()方法时,hibernate会初始化customer代理 类实例,从数据库中加载customer对象的数据,执行以下select语句:

select * from customers where id=1;
select * from orders where customer_id=1;

元素的lazy属性为true,会影响session的load()方法的各种运行时行为,下面举例说明。

1.如果加载的customer对象在数据库中不存在,session的load()方法不会抛出异常,只有当运行customer.getname()方法时才会抛出以下异常:

error lazyinitializer:63 - exception initializing proxy
net.sf.hibernate.objectnotfoundexception: no row with the given identifier exists: 1, of class:
mypack.customer

2.如果在整个session范围内,应用程序没有访问过customer对象,那么customer代理类的实例一直不会被初始化,hibernate不会执行任何select语句。以下代码试图在关闭session后访问customer游离对象:

tx = session.begintransaction();
customer customer=(customer)session.load(customer.class,new long(1));
tx.commit();
session.close();
customer.getname();

由于引用变量customer引用的customer代理类的实例在session范围内始终没有被初始化,因此在执行customer.getname()方法时,hibernate会抛出以下异常:

error lazyinitializer:63 - exception initializing proxy
net.sf.hibernate.hibernateexception: could not initialize proxy - the owning session was closed

由此可见,customer代理类的实例只有在当前session范围内才能被初始化。

3.net.sf.hibernate.hibernate类的initialize()静态方法用于在session范围内显式初始化代理类实例,isinitialized()方法用于判断代理类实例是否已经被初始化。例如:

tx = session.begintransaction();
customer customer=(customer)session.load(customer.class,new long(1));
if(!hibernate.isinitialized(customer))
hibernate.initialize(customer);
tx.commit();
session.close();
customer.getname();

以上代码在session范围内通过hibernate类的initialize()方法显式初始化了customer代理类实例,因此当session关闭后,可以正常访问customer游离对象。

4.当应用程序访问代理类实例的getid()方法时,不会触发hibernate初始化代理类实例的行为,例如:

tx = session.begintransaction();
customer customer=(customer)session.load(customer.class,new long(1));
customer.getid();
tx.commit();
session.close();
customer.getname();

当 应用程序访问customer.getid()方法时,该方法直接返回customer代理类实例的oid值,无需查询数据库。由于引用变量 customer始终引用的是没有被初始化的customer代理类实例,因此当session关闭后再执行customer.getname()方法, hibernate会抛出以下异常:

error lazyinitializer:63 - exception initializing proxy
net.sf.hibernate.hibernateexception: could not initialize proxy - the owning session was closed

trackback: http://tb.blog.csdn.net/trackback.aspx?postid=656003



坏男孩 2007-03-06 14:08
]]>
网站地图