`

open session in view 问题

阅读更多

     在没有使用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。


     OpenSessionInViewInterceptor配置


<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>

 


OpenSessionInViewFilter配置


<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)  
                   throws DataAccessResourceFailureException {   
        Session session = SessionFactoryUtils.getSession(sessionFactory, true);   
        session.setFlushMode(FlushMode.NEVER);   
        return session;  
}  
protected void closeSession(Session session,   
        SessionFactory sessionFactory)throws CleanupFailureDataAccessException {   
    SessionFactoryUtils.closeSessionIfNecessary(session, sessionFactory);  
}  

    

      在这个过程中,若HibernateTemplate 发现自当前session有不是readOnly的transaction,就会获取到FlushMode.AUTO Session,使方法拥有 权限。也即是,如果有不是readOnly的transaction就可以由Flush.NEVER转为 Flush.AUTO,拥有insert,update,delete操作权限,如果没有transaction,并且没有另外人为地设flush model的话,则doFilter的整个过程都是Flush.NEVER。所以受transaction保护的方法有写权限,没受保护的则没有。
     可能的解決方式有:
1、将singleSession设为false,这样只要改web.xml,缺点是Hibernate Session的Instance可能会大增,使用的JDBC Connection量也会大增,如果Connection Pool的maxPoolSize设得太小,很容易就出问题。
2、在控制器中自行管理Session的FlushMode,麻烦的是每个有Modify的Method都要多几行程式。     
session.setFlushMode(FlushMode.AUTO);      
session.update(user);      
session.flush();
3、Extend OpenSessionInViewFilter,Override protected Session getSession(SessionFactory sessionFactory),将FlushMode直接改为Auto。
4、让方法受Spring的事务控制。这就是常使用的方法: 采用spring的事务声明,使方法受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是个双刃剑,放在公网上内容多流量大的网站请慎用。   另外:这样会产生一点危险性,毕竟把数据库访问的环境放到了表现层。(:用VO)      


具体可参考:

http://www.iteye.com/topic/186068

http://www.iteye.com/topic/32001

 

分享到:
评论

相关推荐

    Open Session in View模式.PPT

    Open Session in View模式.PPT

    struts2+hibernate3 open session in view

    struts2+hibernate3 做的小项目 使用了struts2插件实现pen session in view

    Open_Session_In_View详解.doc

    在没有使用Spring提供的Open Session In View情况下,因需要在service(or Dao)层里把session关闭,所以lazy loading 为true的话,要在... Open Session In View提供了一种简便的方法,较好地解决了lazy loading问题. 

    使用Spring引起的错误

    使用Spring提供的Open Session In View而引起Write operations are not allowed in read-only mode (FlushMode.NEVER) 错误解决

    SSH整合 struts+hibernate+spring

    SSH整合概述 应用IoC进行整合 应用AOP进行整合 Open Session In View模式

    Struts Spring Hibernate 整合 OpenSessionInView 例子

    为了练手培训,给大家准备的 Open Session In View 的简单例子,纯代码,大家可以参考,其中主要说了六部分内容: 1.通过接口编程 2.通过spring注入dao到 action 3.通过 open session in view filter 支持 延迟加载...

    Android google io 2012 opensource已通过编译无错误

    View detailed session, code lab, and speaker information, including speaker bios, photos, and Google+ profiles +1 sessions right from the app Participate in public #io12 conversations on Google+ Guide...

    plug-In PHP- 100 Power Solutions

    Open Session; Close Session; Secure Session; Manage Cookie; Block User by Cookie; Create Google Chart; Curl Get Contents; Fetch Wiki Page; Fetch Flickr Stream; Get Yahoo! Answers; Search Yahoo!; Get ...

    JCreatorV4

    You can open multiple files in the Open dialogue box, by holding down the Shift or Ctrl key down as you select each file. You can press ESC to return from Full Screen mode to normal mode.

    UE(官方下载)

    In this tutorial, we'll cover some of the basics of Unicode-encoded text and Unicode files, and how to view and manipulate it in UltraEdit. Search and delete lines found UEStudio and UltraEdit provide...

    spring-jpa-wicket-bootstrap:使用 Spring、JPA、Hibernate、Wicket 和 Bootstrap 的 J2EE Web 模板。 在 Tomcat 和 Postgres DB 上测试

    它演示了MvC 、 SoC 、 IoC 、 DAO 、 Service layer和Open Session in View模式以及其他 J2EE 最佳实践。 该模板可以轻松扩展为功能齐全的基于 Wicket 的 Web 应用程序。 用法 该模板使用 maven 并在 Tomcat7 上...

    PLSQL Developer 8.0.3.1510 中文注册版下载

    * Describe Window now also shows the view comments in the header * Export Tables would change nls_date_format in single session mode and dual session mode * Auto Replace now supports Undo to continue...

    FastReport.v4.15 for.Delphi.BCB.Full.Source企业版含ClientServer中文修正版支持D4-XE5

    - fixed bug with URLs in Open Document Text and Open Document Spreadsheet exports - fixed format string in XLS OLE export - fixed format string in XLS BIFF8 export - fixed output of the check boxes ...

    servlet2.4doc

    Encodes the specified URL by including the session ID in it, or, if encoding is not needed, returns the URL unchanged. -------------------------------------------------------------------------------...

    Bloodshed Dev-C++

    * Multi-select files in project-view (when "double-click to open" is configured in Environment Settings) * Resource files are treated as ordinary files now * Updates in "Project Options/Files" code * ...

    MobaXterm 10.8最新professional版专业版

    更新的内容包含: Version 10.8 (2018-07-07) Bugfix: fixed the error message which occured when running the graphical package manager...引用地址:http://www.open-open.com/lib/view/open1437704662490.html

    BCGControlBarPro.v12.00

    It is stored in CBCGPGridCtrl::m_PrintParams::m_pageInfo member and in CPrintInfo::m_lpUserData member of the CPrintInfo object used while printing at the current print session. Added an option to ...

    Sublime Text Build 3124 x64 Setup.exe

    File encoding of open files is now stored in the session Build Systems may define a cancel command using the "cancel" key Syntax: Added clear_scopes directive, to give more control over the generated ...

    PLSQL.Developer v11.0.0.1762 主程序+ v10中文包+keygen

    Triggers can now be created in the context of a table or view Folders added for Primary, Unique and Foreign key constraints for views Search Bar enhancements A new Search in files option allows you ...

    CE中文版-启点CE过NP中文.exe

    Added a statusbar to the hexview in memoryview Pointerscan for value scans now add the results to the overflow queue Opening a file and changing bytes do not change them to the file anymore (you need ...

Global site tag (gtag.js) - Google Analytics