来自公众号的SPRING(12)

来源:互联网 发布:公众号矩阵什么意思 编辑:程序博客网 时间:2024/05/18 21:49
Java程序员从笨鸟到菜鸟之(八十三)细谈Spring(十二)OpenSessionInView详解及用法                    
2016-09-09java那些事java那些事
java那些事

csh624366188

分享java开发中常用的技术,分享软件开发中各种新技术的应用方法。每天推送java技术相关或者互联网相关文章。关注“java那些事”,让自己做一个潮流的java技术人!《java程序员由笨鸟到菜鸟》系列文章火热更新中。

首先我们来看一下什么是OpenSessionInView?


    在hibernate中使用load方法时,并未把数据真正获取时就关闭了session,当我们真正想获取数据时会迫使load加载数据,而此时session已关闭,所以就会出现异常。 比较典型的是在MVC模式中,我们在M层调用持久层获取数据时(持久层用的是load方法加载数据),当这一调用结束时,session随之关闭,而我们希望在V层使用这些数据,这时才会迫使load加载数据,我们就希望这时的sessionopen着得,这就是所谓的Open Session In view 。 我们可以用filter来达到此目的。 这段话引至于百度百科,但确实很好的说明了OpenSessionInView这个过滤器的作用。

OpenSessionInViewFilterSpring提供的一个针对Hibernate的一个支持类,其主要意思是在发起一个页面请求时打开HibernateSession,一直保持这个Session,直到这个请求结束,具体是通过一个Filter来实现的。由于Hibernate引入了Lazy Load特性,使得脱离HibernateSession周期的对象如果再想通过getter方法取到其关联对象的值,Hibernate会抛出一个LazyLoadException。所以为了解决这个问题,Spring引入了这个Filter,使得HibernateSession的生命周期变长。 


首先分析一下它的源码,可以发现,它所实现的功能其实比较简单: 


[java] view plain copy print?

  1. SessionFactory sessionFactory = lookupSessionFactory(request); 

  2. Session session = null

  3. boolean participate =false

  4.  

  5. if (isSingleSession()) { 

  6.     // single session mode 

  7.     if (TransactionSynchronizationManager.hasResource(sessionFactory)) { 

  8.     // Do not modify the Session: just set the participate flag. 

  9.     participate = true

  10.        }    else

  11.     logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter"); 

  12.     session = getSession(sessionFactory); 

  13.     TransactionSynchronizationManager.bindResource(sessionFactory,new SessionHolder(session)); 

  14.     } 

  15. } else

  16.     // deferred close mode 

  17.     if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) { 

  18. // Do not modify deferred close: just set the participate flag. 

  19.     participate = true

  20.     } else

  21.     SessionFactoryUtils.initDeferredClose(sessionFactory); 

  22.     } 

  23.  

  24. try

  25.     filterChain.doFilter(request, response); 

  26. } finally

  27.     if (!participate) { 

  28.             if (isSingleSession()) { 

  29.                 // single session mode 

  30.         TransactionSynchronizationManager.unbindResource(sessionFactory); 

  31.         logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter"); 

  32.         closeSession(session, sessionFactory); 

  33.     }else

  34.         // deferred close mode 

  35.         SessionFactoryUtils.processDeferredClose(sessionFactory); 

  36.     } 


在上述代码中,首先获得SessionFactory,然后通过SessionFactory获得一个Session。然后执行真正的Action代码,最后根据情况将HibernateSession进行关闭。整个思路比较清晰。



下面我们来看一下他的具体配置,其实很简单,直接在web.xml中把他这个filter配置上就ok了:

[html] view plain copy print?

  1. <filter> 

  2. <filter-name>openSessionInView</filter-name> 

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

  4. <init-param> 

  5. <param-name>sessionFactoryBeanName</param-name> 

  6. <param-value>sf</param-value> 

  7. </init-param> 

  8. </filter> 

  9. <filter-mapping> 

  10. <filter-name>openSessionInView</filter-name> 

  11. <url-pattern>/*</url-pattern> 

  12. </filter-mapping> 


在上面配置中我们要注意以下几点:

1、这个filter一定要配置在struts的过滤器的前面,因为过滤器是“先进后出”原则,如果你配置在struts的后面的话,你的openSessionInView过滤器都执行完了,怎么在去在管理action的转向页面啊。

2Opensessioninview也需要sessionfactorybean的注入,他默认的去找beanidsessionfactorybean,如果sessionfactorybeanid不是这个名字的话,要记得给这个过滤器配置一个参数,参数名为sessionfactoryBeanName,把他的value设置为你的sessionfactorybeanid值。


3、在用opensessioninview的时候一定要注意,如果你不配置transaction的话,在用opensessioninview时,他默认的把事务配置为only-read只读,这样的话,如果你进行增删改的时候,他就会报一个在只读事务中不能进行增删改的操作。如果把opensessioninview去掉,他默认的事务的开始边界就锁定在dao层操作上,daohibernatetempt提供了事务的开始和提交


OpenSessionInView的副作用

         了解了上面几个问题之后,那么也就可以大概知道OpenSessionInView的副作用资源占用严重,配置不当,影响系统性能。使用OpenSessionInView后,在request发出和response返回的流程中,如果有任何一步被阻塞,那在这期间connection就会被一直占用而不释放。比如页面较大,显示需要时间 或者 网速太慢,服务器与用户间传输的时间太长,这都会导致资源占用,最直接的表现就是连接池连接不够用,而导致最终服务器无法提供服务。

0 0
原创粉丝点击