选择显示字体大小

hibernate 延迟初始化错误(error lazyinitializer)是如何产生的?

延迟初始化错误(error lazyinitializer)是如何产生的?

选自<<精通hibernatejava对象持久化技术详解>> 作者:孙卫琴 来源:www.javathinker.org

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

下面把customer.hbm.xml文件的<class>元素的lazy属性设为true,表示使用延迟检索策略:
<class name=&quot;mypack.customer&quot; table=&quot;customers&quot; lazy=&quot;true&quot;>
当执行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;


当<class>元素的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



 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons