首先说明一下,hibernate的延迟加载特性(lazy)。所谓的延迟加载就是当真正须要查询数据时才执行数据加载操做。由于hibernate当中支持实体对象,外键会与实体对象关联起来。若是没有这一特性,当查询某一个含有外键的实体对象时,hibernate会把其余实体对象的数据都查询出来。简单的来讲,当你想查询某个对象时,实际上调用了多条查询语句。有了延迟加载特性,就避免了这种状况的发生,当你真正的使用get另一个实体对象时,才再执行下面一条查询语句。
但有些时候,这个特性却会给咱们应用中带来一些问题。
这个问题相信你们并不陌生了,hibernate的延迟加载(lazy)特性的确不错的优势,若是没了这个特性,我相信你们在处理一些外键的对象时会头大起来,由于效率十分的低。甚至不少人都以为使用jdbc要比hibernate要高效甚至方便得多,而迫使不去使用hibernate。
我想说,没错,使用jdbc在效率上的确可能要快许多,但差距也不会太大的,由于hibernate自己就支持多种查询方式,SQL、HQL、 DetachedCriteria等。而相反的,hibernate在维护性上比jdbc强不少,由于是实体对象的关系。我相信若是您使用过jdbc来实现注册功能的话,会深有体会。
提示session已关闭(no session or session was closed) 触发这个问题的缘由在于,hibernate在查询操做完毕的时候会自动的把session关闭掉,为了下降使用的资源。但问题也这样产生了,不要忘了以前所说的hibernate特性,此时再调用get实体方法的时候就会有可能出现这个错误。由于session已经关闭而不能继续执行查询了。
解决思路:
一、关闭延迟加载特性。
操做起来比较简单,由于hibernate的延迟加载特性是在hbm配置里面可控制的。默认lazy="true",在many-to-one中添加属性lazy="false",就不详细叙述了。
<many-to-one name="category" lazy="false" class="com.penglei.onlineshop.category.vo.Category" column="cid"></many-to-one>
|
但使用这个解决办法带来的隐患是十分大的。
首先,出现no session or session was closed就证实了您已经在使用外键关联表,若是去掉延迟加载的话,则表示每次查询的开销都会变得十分的大,若是关联表越多,后果也能够想象获得。因此不建议使用这个方法解决。
二、在session关闭以前把咱们想要查询的数据先获取了。
然而有时会出现一种状况就是使用第一种方法并不能解决问题。这时咱们须要了解一下session何时关闭,也就是它的生命周期。一般状况下hibernate会在查询数据关闭session,而使用getHibernateTemplate().get方法查询后会延迟关闭的时间。会在事务结束后才关闭。
使用拦截器(Interceptor)或过滤器(Filter)控制session。
spring为解决hibernate这一特性提供的解决方案,能够有效的控制session生命周期。
在web.xml添加一个拦截器:
<!-- 用于解决懒加载的问题 -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
|
重要:网上有不少文档说加入这段代码便可解决懒加载的问题,可是对于不少新手来讲,有不少疑问,为何把这段代码粘贴进去了好像仍是没有什么用。
因此须要注意的是这段代码必定要放在web.xml文件的最开始,如此方可解决问题。