Spring Open Session In View
- session.setFlushMode(FlushMode.AUTO);
- session.save(user);
- session.flush();
在没有使用Spring提供的Open Session In View情况下,因需要在service(or Dao)层里把session关闭,所以lazy loading为true的话,要在应用层内把关系集合都初始化,如 company.getEmployees(),否则Hibernate抛session already closed Exception; Open Session In View提供了一种简便的方法,较好地解决了lazy loading问题.
它有两种配置方式OpenSessionInViewInterceptor和OpenSessionInViewFilter(具体参看SpringSide),功能相同,只是一个在web.xml配置,另一个在application.xml配置而已。
Open Session In View在request把session绑定到当前thread期间一直保持hibernate session在open状态,使session在request的整个期间都可以使用,如在View层里PO也可以lazy loading数据,如 ${ company.employees }。当View 层逻辑完成后,才会通过Filter的doFilter方法或Interceptor的postHandle方法自动关闭session。
- <beans>
- <bean name="openSessionInViewInterceptor"
- class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
- <property name="sessionFactory">
- <ref bean="sessionFactory"/>
- </property>
- </bean>
- <bean id="urlMapping"
- class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
- <property name="interceptors">
- <list>
- <ref bean="openSessionInViewInterceptor"/>
- </list>
- </property>
- <property name="mappings">
- ...
- </property>
- </bean>
- ...
- </beans>
- <web-app>
- ...
- <filter>
- <filter-name>hibernateFilter</filter-name>
- <filter-class>
- org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
- </filter-class>
- <!-- singleSession默认为true,若设为false则等于没用OpenSessionInView -->
- <init-param>
- <param-name>singleSession</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
- ...
- <filter-mapping>
- <filter-name>hibernateFilter</filter-name>
- <url-pattern>*.do</url-pattern>
- </filter-mapping>
- ...
- </web-app>
很多人在使用OpenSessionInView过程中提及一个错误:
- org.springframework.dao.InvalidDataAccessApiUsageException: Write operations
- are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into
- FlushMode.AUTO or remove 'readOnly' marker from transaction definition
看看OpenSessionInViewFilter里的几个方法
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException { SessionFactory sessionFactory = lookupSessionFactory(); logger.debug("Opening Hibernate Session in OpenSessionInViewFilter"); Session session = getSession(sessionFactory); TransactionSynchronizationManager.bindResource( sessionFactory, new SessionHolder(session)); try { filterChain.doFilter(request, response); } finally { TransactionSynchronizationManager.unbindResource(sessionFactory); logger.debug("Closing Hibernate Session in OpenSessionInViewFilter"); closeSession(session, sessionFactory); } }
- protected Session getSession(SessionFactory sessionFactory) throwsDataAccessResourceFailureException { Session session = SessionFactoryUtils.getSession(sessionFactory, true); session.setFlushMode(FlushMode.NEVER); return session; }
- protected void closeSession(Session session, SessionFactory sessionFactory) throwsCleanupFailureDataAccessException { SessionFactoryUtils.closeSessionIfNecessary(session, sessionFactory); }
可以看到OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.NEVER。然后把该sessionFactory绑定到TransactionSynchronizationManager,使request的整个过程都使用同一个session,在请求过后再接除该sessionFactory的绑定,最后closeSessionIfNecessary根据该session是否已和transaction绑定来决定是否关闭session。在这个过程中,若HibernateTemplate 发现自当前session有不是readOnly的transaction,就会获取到FlushMode.AUTO Session,使方法拥有写权限。
- public static void closeSessionIfNecessary(Session session, SessionFactory sessionFactory)
- throws CleanupFailureDataAccessException {
- if (session == null || TransactionSynchronizationManager.hasResource(sessionFactory)) {
- return;
- }
- logger.debug("Closing Hibernate session");
- try {
- session.close();
- }
- catch (JDBCException ex) {
- // SQLException underneath
- throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex.getSQLException());
- }
- catch (HibernateException ex) {
- throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex);
- }
- }
也即是,如果有不是readOnly的transaction就可以由Flush.NEVER转为Flush.AUTO,拥有insert,update,delete操作权限,如果没有transaction,并且没有另外人为地设flush model的话,则doFilter的整个过程都是Flush.NEVER。所以受transaction保护的方法有写权限,没受保护的则没有。
- <bean id="baseTransaction" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager" ref="transactionManager"/> <property name="proxyTargetClass" value="true"/> <property name="transactionAttributes"> <props> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="remove*">PROPAGATION_REQUIRED</prop> </props> </property> </bean>
- <bean id="userService" parent="baseTransaction"> <property name="target"> <bean class="com.phopesoft.security.service.impl.UserServiceImpl"/> </property> </bean>
对于上例,则以save,add,update,remove开头的方法拥有可写的事务,如果当前有某个方法,如命名为importExcel(),则因没有transaction而没有写权限,这时若方法内有insert,update,delete操作的话,则需要手动设置flush model为Flush.AUTO,如
- session.setFlushMode(FlushMode.AUTO);
- session.save(user);
- session.flush();
尽管Open Session In View看起来还不错,其实副作用不少。看回上面OpenSessionInViewFilter的doFilterInternal方法代码,这个方法实际上是被父类的doFilter调用的,因此,我们可以大约了解的OpenSessionInViewFilter调用流程: request(请求)->open session并开始transaction->controller->View(Jsp)->结束transaction并close session.
一切看起来很正确,尤其是在本地开发测试的时候没出现问题,但试想下如果流程中的某一步被阻塞的话,那在这期间connection就一直被占用而不释放。最有可能被阻塞的就是在写Jsp这步,一方面可能是页面内容大,response.write的时间长,另一方面可能是网速慢,服务器与用户间传输时间久。当大量这样的情况出现时,就有连接池连接不足,造成页面假死现象。
Open Session In View是个双刃剑,放在公网上内容多流量大的网站请慎用
Spring Open Session In View的更多相关文章
- Hibernate Open Session In View模式【转】
来源:http://www.yybean.com/opensessioninviewfilter-role-and-configuration 一.作用 Spring为我们解决Hibernate的Se ...
- open Session In View和过滤器配置
Open Session In View模式的主要思想是:当Web Request(浏览器请求)开始时,自动打开Session,当Web Request结束时,自动关闭Session.也就是说,Ses ...
- open Session In View模式
首先看图说话: ****Open Session In View模式的主要思想是:在用户的每一次请求过程始终保持一个Session对象打开着*** 接下来就是代码: +++++++++++++++++ ...
- Open Session In View
Open Session In View模式的主要思想是:在用户的每一次请求过程始终保持一个Session对象打开着 实现步骤: 步骤一.创建一个Web项目,创建包cn.happy.util,创建Hi ...
- 【原创】大叔问题定位分享(35)spring中session失效时间
spring项目中将sessionid对应的cookie过期时间设置很长,但是实际session还是在半个小时后失效,跟了一下代码,spring中session实现接口为 org.springfram ...
- Spring Mvc session拦截器实现
Spring Mvc拦截器实现session过期跳转到登录页面 配置拦截器 <mvc:interceptors> <mvc:interceptor> <mvc:mappi ...
- 使用高性能xml序列化框架jibx作为spring mvc的xml view
package org.springframework.web.servlet.view.xml; import java.io.ByteArrayOutputStream; import java. ...
- Spring Security 入门(1-7)Spring Security - Session管理
参考链接:https://xueliang.org/article/detail/20170302232815082 session 管理 Spring Security 通过 http 元素下的子元 ...
- Spring Security Session并发控制原理解析
当使用spring security 的标签,如下,其中<sec:session-management>对应的SessionManagementFilter.从名字可以看出,这是一个管理S ...
随机推荐
- Python 字符编码问题的处理
python中的字符编码问题往往是初学者容易弄不明白的问题, 要想将这个问题搞清楚,需要先弄明白以下的概念 decode 和 encode 函数的作用 字符串字面量的编码格式 decode(str) ...
- config文件声明非系统节点的方法
有一些自定义节点如果不声明会报出无法识别的节点 XXX 这时候要声明该节点 写法如下 <configSections> <!--声明一个节点组--> <sectionGr ...
- (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合
http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...
- 在Solr中配置中文分词IKAnalyzer
李克华 云计算高级群: 292870151 交流:Hadoop.NoSQL.分布式.lucene.solr.nutch 在Solr中配置中文分词IKAnalyzer 1.在配置文件schema.xml ...
- 几个不错的APP网站。
http://www.yunshipei.com/yunshipei.html http://www.appcan.cn/
- ulrlib案例-爬取百度贴吧
1.任务需求 百度贴吧有很多主题,每个主题下的网页存在很多分页.爬取不同的主题,并下载每个主题下的多页网页. 输入贴吧名称,下载相应贴吧的多页网页,设置最多下载50页. 2.分析网页 访问不同的百度贴 ...
- thinkphp 结合phpexcel实现excel导入
控制器文件: class ExcelAction extends Action { public function __construct() { import('ORG.Util.ExcelToAr ...
- shell脚本,对MySQL数据库进行分库加分表备份
[root@localhost wyb]# cat table_backup.sh #!/bin/bash flag= user=root pass=test mysql -u$user -p&quo ...
- 【求助】NdisSend,自定义数据包发送失败?
做ndis hook的时候,自定义了一个数据包,包结构应该没有问题,填充NDIS_PACKET结构是这样的,先初始化: NdisAllocatePacketPool(&nStat ...
- PLAYGROUND 可视化
PLAYGROUND 可视化 由 王巍 (@ONEVCAT) 发布于 2015/09/23 在程序界,很多小伙伴都会对研究排序算法情有独钟,并且试图将排序执行的过程可视化,以便让大家更清晰直观地了解算 ...