细说OpenSessionInView问题

细说OpenSessionInView问题

【环境参数】

  环境:SSH框架

 

【问题描述】

   NoSession问题

  HibernateTemplate对象提供的方法如果使用“延迟加载”,Session对象的管理不受开发者控制,此时如果在表现层获取延迟加载的数据,

则会抛出“LazyInitializationException”异常,如下图所示。

 

【原因分析】

       原因总结:Session的存活期太短,在Session已经关闭的情况下,App读取持久化对象中的非OID的属性从而报错。

       假设load()方法获得的对象是User对象。

       “延迟加载”的特点:

       在Hibernate没有关闭Session时,App可以随时去读取“延迟数据(通过让Hibernate重新加载去获得数据)”。

load()方法获得的User对象是一个“只有ID属性”的对象,只要App不去使用User对象中的“非ID属性”,则User对象中永远都只有ID属性,这样可以提高性能。

当App去调用对象X中的非ID属性时,比如name和age属性,正常情况下,Hibernate会去加载name和age属性,然后JVM再调用toString()方法,并且成功地完成打印。

 

       但若在Hibernate去加载name和age属性时,Session已经关闭了,则Hibernate就无法去加载得到非ID属性了,此时就会抛出异常“LazyInitializationException”。

       Session为什么会关闭呢?

   

  当我们提交事务时,就会自动把Session给关闭了。

 

【解决方案】

  该解决方案由Spring提供:OpenSessionInView。

(1)主要思路

  将Session的存活期延长,绑定Session。

 

(2)产生该方案的思路

  客户端发一个请求,则位于服务器端的Spring创造一个Session,当请求结束了,才会把Session关闭,这样,就将Session与请求绑定在一起了。

从发送请求到请求结束,这整个流程都位于一个线程,在此,将Session对象绑定到该线程上,在Hibernate知识体系中,就有一个关于“当前线程绑定Session”的专题,讲的也就是这个概念。

客户端每次发送请求时,都要去将Session绑定到线程上,这样比较麻烦,能否有简化途经呢?比如Spring的AOP。

 

  1)可选方案一:利用Spring的AOP。

  方案一可行性:不靠谱。

  为什么方案一不行?

  因为在客户端发送的请求在到达服务器的过程中,Spring还没有开始工作。Spring若想绑定东西,要绑定的东西必须是“代码”,

请求对象和响应对象的创建”是由服务器端的HTTPD守护程序完成的。而Spring是位于Web容器中的,而且Spring容器随着某个WebApp的启动而创建的。此时Spring还没有开始工作,而请求对象已经被HTTPD守护程序创建了,此时,Spring是不可能将Request对象同Session对象进行绑定的,因此,AOP是不能完成该功能的。

 

  2)可选方案二:利用监听器

  方案二可行性:不靠谱。

  <listener>监听器:监听器是启动服务器时一次性运行的。

 

  3)可选方案三:利用过滤器

  <filter>过滤器:过滤器是每当用户的请求Request对象到达WebApp时以及Response对象出WebApp时使用的。

 

(3)终极解决方案

1)简述:OpenSessionInView翻译过来就是:在表现层打开Session。

2)作用:

将Session对象的创建交给当前线程管理,当前线程维护着一个“Session的连接池”。每当用户发送一个请求,filter在接收到用户的请求Request后,就会将Session对象绑

定到该请求上。

       当请求被处理完毕,返回响应Response时,Response会再次经过filter的处理,Response之前被绑定的Session会被filter回收,然后放入到“Session的连接池”中。

       当下次用户再次发送请求时,仍然重复上述过程。

3)代码:

在web.xml中设置过滤器OpenSessionInViewFilter。

1

2

3

4

5

6

7

8

9

<!-- 配置OpenSessionInView --> 

<filter>

<filter-name>openSessionInView</filter-name>

    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>openSessionInView</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

 

 

读者如要转载,请标明出处和作者名,谢谢。

地址01:http://space.itpub.net/25851087

地址02:http://www.cnblogs.com/zjrodger

作者名:zjrodger 

  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值