org.hibernate.LazyInitializationException: could not initialize proxy - no Session

前言

在<many-to-on>中这错误很常见,字面意义就是不能被初始化,因为session已经关闭了。

简单理解就是因为,你使用了lazy=true,这样hibernate在从数据库中调数据的时候是不会把关联的对象查出来的,而是保存一个获取值的方法,在你使用getXXX()调用的时候,hiberante会利用这个保存的方法去从数据库中取数据。而往往我们在jsp页面中使用getXXX()准备展示数据的时候,session早已经在dao中就关闭了,我们该如何解决这种异常呢?

简单的说有三种:

1.把lazy设成false,最2的办法,但是最简单,简单就是美嘛,也依然会有很多再使用这个方式再解决类似问题。

2.我没试过,但听说过,应该可行.

在web.xml中加入

<filter>
     <filter-name>hibernateFilter</filter-name>
     <filter-class>
     org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
     </filter-class>
</filter
<filter-mapping>
     <filter-name>hibernateFilter</filter-name>
     <url-pattern>*.do</url-pattern>
</filter-mapping>

3.我用的方法,也是我认为比较不错的方法,灵活性更好。用left join fetch或inner join fetch语法。

例如:from Item i left join fetch i.parentItem ii

解释一下Item表是一个自关联的表,它的关联关系在hbm.xml中配置好了。

如下:

<many-to-one name="parentItem" lazy="false" fetch="join" class="cn.sports.matchs.model.Item">
<column name="PARENT_ID"></column>
</many-to-one>

在Item类中

private Item parentItem;

利用left join fetch可以完美的解决这个问题。

关于lazy机制

延迟初始化错误是运用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();

在运行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 thegiven 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

解决方法:

由于hibernate默认采用了lazy=true,这样当你用hibernate查询时,返回实际为利用cglib增强的代理类,但其并没有实际填充;当你在前端,利用它来取值(getXXX)时,这时Hibernate才会到数据库执行查询,并填充对象,但此时如果和这个代理类相关的session已关闭掉,就会产生种错误.

在做一对多时,有时会出现"could  not  initialize  proxy - the owning Session was sed,这个好像是hibernate的缓存问题.问题解决:需要在<many-to-one>里设置lazy="false". 但有可能会引发另一个异常叫

failed  to lazily initialize a collection of role: XXXXXXXX, no session or session was closed

解决方法:在web.xml中加入

<filter>
     <filter-name>hibernateFilter</filter-name>
     <filter-class>
     org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
     </filter-class>
</filter
<filter-mapping>
     <filter-name>hibernateFilter</filter-name>
     <url-pattern>*.do</url-pattern>
</filter-mapping>

就可以了;

美文美图

J2EE进阶(九)org.hibernate.LazyInitializationException: could not initialize proxy - no Session的更多相关文章

  1. 解决org.hibernate.LazyInitializationException: could not initialize proxy - no Session懒载入问题

    问题描写叙述: Struts Problem Report Struts has detected an unhandled exception: Messages: could not initia ...

  2. Exception 07 : org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    异常名称: org.hibernate.LazyInitializationException: could not initialize proxy - no Session 异常截图: 异常详情: ...

  3. 解决方案,org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    org.hibernate.LazyInitializationException: could not initialize proxy - no Session org.hibernate.pro ...

  4. Hibernate和Spring整合出现懒加载异常:org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    出现问题:  SSH整合项目里,项目目录结构如下: 在EmployeeAction.java的list()方法里将employees的list放入到request的Map中. EmployeeActi ...

  5. 【bug记录】jpa 解决org.hibernate.lazyinitializationexception could not initialize proxy - no session

    前言 最近开发项目比较忙,Spring Cloud的笔记得稍稍放放了,下午出来个bug,恶心的不行,功能很简单,也没有什么级联或复杂的映射关系,就是一直在报三个异常 Caused by: com.fa ...

  6. dubbo序列化hibernate.LazyInitializationException could not initialize proxy - no Session懒加载异常的解决

    dubbo序列化,hibernate.LazyInitializationException could not initialize proxy - no Session懒加载异常的解决 转载声明: ...

  7. 总结懒加载的解决方法(全)org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    如下错误:org.hibernate.LazyInitializationException: could not initialize proxy - no Session 原因是懒加载的问题,因为 ...

  8. jpa 解决org.hibernate.lazyinitializationexception could not initialize proxy - no session

    org.hibernate.LazyInitializationException: could not initialize proxy [org.alan.entity.SysUser#1] - ...

  9. org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    原因:在延迟加载的状态下,使用某个属性时,但session已经关闭. 解决方法: 1.把load改成get,直接加载所有属性. 2.获取对象进行一次判断,如果对象没有初始化,就进行一次初始化. if ...

随机推荐

  1. qemu 模拟-arm-mini2440开发板-启动u-boot,kernel和nfs文件系统【转】

    转自:http://www.cnblogs.com/riskyer/p/3366001.html qemu 本文介绍了如何编译u-boot.linux kernel,然后用qemu启动u-boot和l ...

  2. if(/专线$/.test(name))讲解

    如图: 这条语句的意思是:匹配以"专线"结尾的name字符串,满足条件的返回true,否则返回false

  3. Python的IO编程

    原文传送门:请点击 原文传送门:请点击

  4. vrn:基于直接体积回归的单幅图像大姿态三维人脸重建

    3D面部重建是一个非常困难的基本计算机视觉问题.目前的系统通常假设多个面部图像(有时来自同一主题)作为输入的可用性,并且必须解决许多方法学挑战,例如在大的面部姿势,表情和不均匀照明之间建立密集的对应. ...

  5. Vegas Pro 15软件界面对比

    大家都知道Vegas是一款专业的视频制作软件,而新版的VEGAS Pro 15更是专业性十足.好了,废话不多说,接下来小编就带大家具体的看一下Vegas 15界面都有哪些更新吧! 一.软件图标 图1: ...

  6. js求和运算在可变参数的情况下ES3、ES5和ES6的写法区别

    //ES3.ES5的写法 function foo(){ var arr = Array.prototype.slice.call(arguments); var sum = 0; arr.forEa ...

  7. 简介JSP与FreeMarker及Volicity区别

    FreeMarker FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个 ...

  8. R语言集合操作

    熟练运用R语言的集合操作在很多时候可以省去for循环,从而提升数据处理效率.废话不多说,集合操作相对简单,贴一段代码就懂了! > A<-: > A [] > B<-,,) ...

  9. 02_版本控制工具SVN

    SubVersion: 安装:根据电脑版本选择安装64或32位的subversion,尽量不要选择中文或者有空格的目录安装 版本控制仓库: 创建命令:SVNadmin create 目录 启动SVN服 ...

  10. PHP 实例 AJAX RSS 阅读器

    RSS 是一种描述和同步网站内容的格式,是目前使用最广泛的XML应用. RSS 搭建了信息迅速传播的一个技术平台,使得每个人都成为潜在的信息提供者. RSS 阅读器用于阅读 RSS Feed. AJA ...