转载地址来源于 https://blog.csdn.net/u010167086/article/details/17029831
异常:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:57)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
在做一个项目的时候遇到了这个问题,大概的意思是不能 初始化,session 关闭了的,于是就想到可能是session关闭了 而程序某个地方还在从数据库中读取数据
于是就上网百度了一下, 说的是在用多对一或者是多对多的时候懒加载的问题
下面先看下 hibernate里lazy 的内容(上面出错的解决办法,我会在下面给出)
lazy,延迟加载
Lazy的有效期:只有在session打开的时候才有效;session关闭后lazy就没效了。
lazy策略可以用在:
-
标签上:可以取值true/false
-
标签上,可以取值true/false,这个特性需要类增强
-
/等集合上,可以取值为true/false/extra
-
/等标签上,可以取值false/proxy/no-proxy
1 get和load的区别:
-
get不支持延迟加载,而load支持。
-
当查询特定的数据库中不存在的数据时,get会返回null,而load则抛出异常。
2 类(Class)的延迟加载:
-
设置标签中的lazy=“true”,或是保持默认(即不配置lazy属性)
-
如果lazy的属性值为true,那么在使用load方法加载数据时,只有确实用到数据的时候才会发出sql语句;这样有可能减少系统的开销。
-
//不会发出查询sql
System.out.println("group id=" + group.getId());
这里有一个问题,为什么加载主键的时候不需要发出sql语句。
3 集合(collection)的延迟加载:可以取值true,false,extra
-
保持集合上的lazy的默认值,此时的效果和lazy="extra"是基本一样的。
- 设置集合上的lazy=extra,此时的效果和lazy属性的默认值是基本一样的。但是推荐使用这个属性值,因为在统计时这种情况显得比较智能。当然延迟是有效果的。
-
设置集合上的lazy=false
true:默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其集合元素的数据
false:取消懒加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据
extra:一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate
并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据
4 Hibernate单端关联懒加载策略:即在/标签上可以配置
懒加载策略。可以取值为:false/proxy/no-proxy
false:取消懒加载策略,即在加载对象的同时,发出查询语句,加载其关联对象
proxy:这是hibernate对单端关联的默认懒加载策略,即只有在调用到其关联对象的方法的时候才真正发出查询语句查询其对象数据,其关联对象是代理类
no-proxy:这种懒加载特性需要对类进行增强,使用no-proxy,其关联对象不是代理类
看了上面的lazy的内容之后 你可能自己就有了解决办法 (我的项目问题就是默认了lazy为true 然而我在后面有用到了懒加载)
出现问题的原因:
在Hibernate中,<many-to-one…/>中的lazy默认为proxy。这样hibernate在数据库中查询数据时事不会把关联的
对象查出来的,而是保存一个获得该值得方法:getXxxx()。当我们需要使用这个值的时候,也就是使用getXxx()方法来
调用的时候,Hibernate就会利用这个方法从数据库中获取相应的数据。但是很不幸,我们的session早就关闭了。
这是因为Hibernate的懒加载策略,在Hibernate中是使用sessionFactory来管理session,我们每进行一次数据库操作时
都会新建一个session对象,当我们操作完成后,hibernate就会在dao层立即关闭该session。这样做就可以严格控制
session,避免出现低级错误。
下面给出三种解决办法,个人认为第二种比较好
1、把lazy设成false。这个是最简单的办法,个人认为也是比较笨的方法。因为这是在用效率作为代价。
2、使用OpenSessionInViewFilter。这种方法是将session交给servlet filter来管理,每当一个请求来之后就会开
启一个session,只有当响应结束后才会关闭。如下:
[html] view plaincopy
hibernateFilter
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter
hibernateFilter
/*
上面的配置文件时在web.xml中配置的。
3、将hibernate的抓起策略改为join。也就是是left join fetch或inner join fetch语法。就是在<many-to-one../>中配
置lazy=“false” fetch="join"即可。如:
[html] view plaincopy
<column name="positionId"></column>
</many-to-one>