延迟初始化错误(error lazyinitializer)是如何产生的?
选自<<精通hibernate:java对象持久化技术详解>> 作者:孙卫琴 来源:www.javathinker.org
延迟初始化错误是运用hibernate开发项目时最常见的错误。如果对一个类或者集合配置了延迟检索策略,那么必须当代理类实例或代理集合处于持久化状态(即处于session范围内)时,才能初始化它。如果在游离状态时才初始化它,就会产生延迟初始化错误。
下面把customer.hbm.xml文件的<class>元素的lazy属性设为true,表示使用延迟检索策略:
<class name="mypack.customer" table="customers" 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();
select * from customers where id=1;
select * from orders where customer_id=1;
error lazyinitializer:63 - exception initializing proxy
.net.sf.hibernate.objectnotfoundexception: no row with the given identifier exists: 1, of class:
mypack.customer
tx = session.begintransaction();
customer customer=(customer)session.load(customer.class,new long(1));
tx.commit();
session.close();
customer.getname();
error lazyinitializer:63 - exception initializing proxy
.net.sf.hibernate.hibernateexception: could not initialize proxy - the owning session was closed
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();
tx = session.begintransaction();
customer customer=(customer)session.load(customer.class,new long(1));
customer.getid();
tx.commit();
session.close();
customer.getname();
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 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器