J2EE进阶(九)org.hibernate.LazyInitializationException: could not initialize proxy - no Session
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的更多相关文章
- 解决org.hibernate.LazyInitializationException: could not initialize proxy - no Session懒载入问题
问题描写叙述: Struts Problem Report Struts has detected an unhandled exception: Messages: could not initia ...
- Exception 07 : org.hibernate.LazyInitializationException: could not initialize proxy - no Session
异常名称: org.hibernate.LazyInitializationException: could not initialize proxy - no Session 异常截图: 异常详情: ...
- 解决方案,org.hibernate.LazyInitializationException: could not initialize proxy - no Session
org.hibernate.LazyInitializationException: could not initialize proxy - no Session org.hibernate.pro ...
- Hibernate和Spring整合出现懒加载异常:org.hibernate.LazyInitializationException: could not initialize proxy - no Session
出现问题: SSH整合项目里,项目目录结构如下: 在EmployeeAction.java的list()方法里将employees的list放入到request的Map中. EmployeeActi ...
- 【bug记录】jpa 解决org.hibernate.lazyinitializationexception could not initialize proxy - no session
前言 最近开发项目比较忙,Spring Cloud的笔记得稍稍放放了,下午出来个bug,恶心的不行,功能很简单,也没有什么级联或复杂的映射关系,就是一直在报三个异常 Caused by: com.fa ...
- dubbo序列化hibernate.LazyInitializationException could not initialize proxy - no Session懒加载异常的解决
dubbo序列化,hibernate.LazyInitializationException could not initialize proxy - no Session懒加载异常的解决 转载声明: ...
- 总结懒加载的解决方法(全)org.hibernate.LazyInitializationException: could not initialize proxy - no Session
如下错误:org.hibernate.LazyInitializationException: could not initialize proxy - no Session 原因是懒加载的问题,因为 ...
- jpa 解决org.hibernate.lazyinitializationexception could not initialize proxy - no session
org.hibernate.LazyInitializationException: could not initialize proxy [org.alan.entity.SysUser#1] - ...
- org.hibernate.LazyInitializationException: could not initialize proxy - no Session
原因:在延迟加载的状态下,使用某个属性时,但session已经关闭. 解决方法: 1.把load改成get,直接加载所有属性. 2.获取对象进行一次判断,如果对象没有初始化,就进行一次初始化. if ...
随机推荐
- 【linux】---常用命令整理
linux常用命令整理 一.ls命令 就是list的缩写,通过ls 命令不仅可以查看linux文件夹包含的文件,而且可以查看文件权限(包括目录.文件夹.文件权限)查看目录信息等等 常用参数搭配: l ...
- 构建纯TypeScript应用
构建纯TypeScript应用 现在只有命令行应用的例子. 前言 现在,应用开发的趋势是命令行接口应用和Web应用. node.js 和 typescript的崛起所以,这里讨论如何创建纯的TypeS ...
- 解决Spring Boot 使用RedisTemplate 存储键值出现乱码 \xac\xed\x00\x05t\x00
spring-data-redis的RedisTemplate<K, V>模板类在操作redis时默认使用JdkSerializationRedisSerializer来进行序列化解决方法 ...
- Linux下安装java的jdk和配置环境变量
每次感觉配这个超级简单 但是每次都要查下 记一下好了 Linux下安装jdk,步骤如下 1:下载jdk包:本章使用的为后缀为tar.gz的文件(不需要安装),如jdk-8u111-linux-x64. ...
- 打造适合你的ABP(1)---- 完善日志系统
最近使用Abp开发了一个项目,对abp有一个大概的了解,第一个小项目接近尾声,新的项目马上开始,针对开发第一个项目中发现的问题及不方便的地方,本人做一些修改,特此记录,请大家多多指正! 本人的开发环境 ...
- Java内存泄漏分析系列之四:jstack生成的Thread Dump日志线程状态
原文地址:http://www.javatang.com Thread Dump日志的线程信息 以下面的日志为例: "resin-22129" daemon prio=10 tid ...
- postgresql 登录查看表定义
su - postgres psql \connect database_name; \d table_name
- Spring Security 基础登录实例
1 新建Java Web项目 导入Jar: 2 修改web.xml <?xml version="1.0" encoding="UTF-8"?> & ...
- 《Java多线程编程核心技术》推荐
写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...
- 热烈庆祝自已厉精13年开发的 DB查询分析器 7.01(最新版本) 在中关村在线本月获得近6000次的下载量
中国本土程序员马根峰(CSDN专访马根峰:海量数据处理与分析大师的中国本土程序员)推出的个人作品----万能数据库查询分析器,中文版本 DB 查询分析器.英文版本DB Query Analyzer.它 ...