`

Open Session In View

 
阅读更多
从昨天下午一直纠结到现在,原来是项目启用了Open Session In View

2.hibernate由于设置了延迟加载,在action中并没有真正地查询数据  
3.当跳到jsp页面上要显示数据时,hibernate中的session却已经关闭,导致数据无法显示 该过滤器的作用就是可以避免这种情况  

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

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

  1.<beans>

2.<bean name="openSessionInViewInterceptor" 

3.   class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"> 

4.   <property name="sessionFactory"> 

5.     <ref bean="sessionFactory"/> 

6.   </property> 

7.</bean>

8.<bean id="urlMapping"

9.   class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

10.   <property name="interceptors"> 

11.     <list>

12.       <ref bean="openSessionInViewInterceptor"/> 

13.     </list> 

14.   </property>

15.   <property name="mappings">

16.     ...

17.   </property> 

18.</bean>

19. ...

20.</beans>


OpenSessionInViewFilter配置

1.<web-app> 

2.  ... 

3.  <filter> 

4.     <filter-name>hibernateFilter</filter-name>

5.     <filter-class>

6.       org.springframework.orm.hibernate3.support.OpenSessionInViewFilter

7.     </filter-class>

8.     <!-- singleSession默认为true,若设为false则等于没用OpenSessionInView -->

9.     <init-param>

10.       <param-name>singleSession</param-name>

11.       <param-value>true</param-value> 

12.     </init-param> 

13.   </filter> 

14.   ...

15.   <filter-mapping>

16.     <filter-name>hibernateFilter</filter-name> 

17.     <url-pattern>*.do</url-pattern>

18.   </filter-mapping>

19.   ... 

20. </web-app>


 
重点来啦:
看看<SPAN style="COLOR: #0000ff">OpenSessionInViewFilter里的几个方法

</SPAN>


#

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;

} &nbsp;

protected void closeSession(Session session, SessionFactory sessionFactory)

   throws CleanupFailureDataAccessException {

  SessionFactoryUtils.closeSessionIfNecessary(session, sessionFactory);

}&nbsp;   

可以看到OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.NEVER。然后把该sessionFactory绑定到 TransactionSynchronizati

onManager,使request的整个过程都使用同一个session,在请求过后再接除该 sessionFactory的绑定,最后closeSessionIfNecessary根据该 session是否已和transaction绑定来决定是否关闭session。在这个过程中,若HibernateTemplate 发现自当前session有不是readOnly的transaction,就会获取到FlushMode.AUTO Session,使方法拥有写权限。



1.public static void closeSessionIfNecessary(Session session, SessionFactory  sessionFactory)

2. throws CleanupFailureDataAccessException {

3. if (session == null ||

    TransactionSynchronizationManager.hasResource(sessionFactory)) {

4.    return;

5.  }

6.  logger.debug("Closing Hibernate session");

7.  try {

8.    session.close();

9.  }

10.  catch (JDBCException ex) {

11.  // SQLException underneath

12.  throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex.getSQLException());

13.  }

14.  catch (HibernateException ex) {

15.  throw new CleanupFailureDataAccessException("Could not close Hibernate session",  ex);

16.  }

17.}

18.
19.
20.
21.
22.

尽 管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是个双刃剑,放在公网上内容多流量大的网站请慎用。

分享到:
评论

相关推荐

    Open Session in View模式.PPT

    Open Session in View (OSIV) 模式是一种在基于Hibernate的Web应用程序中处理持久化数据的策略,它允许在视图层(例如JSP页面)中安全地访问延迟加载的对象,而无需担心Session已关闭的问题。以下是关于这个模式及其...

    struts2+hibernate3 open session in view

    在这个小项目中,"Open Session in View"(OSIV)模式被采用,这是一种处理持久化数据的策略,以避免在Web应用中出现常见的并发问题,如数据不一致和懒加载异常。 Struts2是一个强大的MVC框架,它提供了一种灵活的...

    Open_Session_In_View详解.doc

    ### Open_Session_In_View详解 #### 一、背景与概念 在使用Hibernate进行对象持久化时,经常遇到的一个问题是关于懒加载(lazy loading)的处理。懒加载是一种优化技术,允许在真正需要某个关联对象的数据时才加载...

    使用Spring引起的错误

    当使用Open Session In View模式时,如果Session的Flush Mode被设置为NEVER,并且尝试执行写操作(如更新或删除),就会触发“Write operations are not allowed in read-only mode (FlushMode.NEVER)”这个异常。...

    Hibernate Session释放模式

    3. **Open Session in View(OSIV)模式** OSIV模式旨在解决Web应用中,由于用户请求可能会引发多次数据库操作,而这些操作可能跨多个HTTP请求。在这种模式下,Session在整个HTTP请求周期内保持打开状态,直到请求...

    hibernate中session的管理

    3. **Open Session in View (OSIV)**:在视图渲染阶段保持Session打开,以允许最后时刻的懒加载,但需要注意防止Session泄露。 总的来说,Hibernate中Session的管理是保证多线程环境下数据一致性的重要环节。...

    spring中lazy=“true”的正常读取关联表(用opensessioninview)

    为了解决这个问题,Spring提供了一个过滤器 `OpenSessionInViewFilter` 或者 `OpenSessionInViewInterceptor`,通常简称为OSIV(Open Session In View)模式。 OSIV模式的核心思想是在Controller层和View层之间保持...

    Hibernate事务管理.

    在没有Spring提供的Open Session In View(OSIV)模式下,事务处理和懒加载(lazy loading)可能会遇到挑战。 懒加载是一种优化策略,允许关联对象在需要时才从数据库加载,而不是在初始加载实体时就全部加载。这...

    Spring延迟加载和声明式事务处理最终解决方案(修正版)

    1. **Open Session in View Interceptor (OSIV)**:这是Spring MVC中的一个拦截器,它的作用是在整个视图渲染过程中保持Hibernate Session的开放,确保在需要的时候可以进行延迟加载。配置OSIV拦截器后,如在`spring...

    ssh中getCurrentSession的使用

    - 首先,需要配置Hibernate,让其知道如何初始化SessionFactory,并启用Open Session In View模式。 - 在业务逻辑代码中,通过SessionFactory实例调用`getCurrentSession()`,然后执行数据库操作。 - 为了处理...

    集成spring的hibernate懒加载

    在Spring整合Hibernate的情况下,Session通常通过Transaction Management进行管理,比如使用`Open Session in View`(OSIV)模式或者基于注解的事务管理。 当你尝试在Controller层或者视图层访问懒加载的属性时,...

    课程hibernate的事务和并发.pdf

    这种方式被称为ThreadLocal Session和Open Session in View模式,能够简化事务和Session的生命周期管理。 在实际应用中,需要确保正确地开启和结束Session及事务,并将其与数据访问操作结合。HibernateUtil类可以...

    ssh_inte2模板常用方法&延迟加载问题

    可以考虑将事务范围扩大,或者使用开放Session视图模式(Open Session In View,OSIV),让Session贯穿整个HTTP请求,但请注意,OSIV模式可能导致更多的并发问题,需要谨慎使用。 3. **使用Eager Loading**:如果...

    SpringBoot-SpringData-懒加载

    2. **启用Hibernate的开放 session in view**:在Spring Boot中,如果使用Hibernate作为JPA的实现,需要在配置文件(application.properties或application.yml)中开启Open Session In View(OSIV)过滤器,以解决懒...

    hibernate笔记

    Open Session in View(OSIV)模式是一种常见的Hibernate优化模式,主要用于提高读取操作的性能。在这种模式下,Session在整个HTTP请求周期内保持打开状态。 ##### OSIV 实现方式 - **Servlet Filter 方式**:最常见...

    SSH错误集中分析.

    确保在需要的地方启用Open Session in View或者在查询时一次性加载关联数据。 2. **SQL异常**:错误的HQL或Criteria查询可能导致SQL语法错误,检查并修正查询语句。 四、Spring的常见错误 1. **AOP配置**:如果...

    hibernate的lazy策略forClass

    2. 使用Open Session In View模式,将Session的生命周期扩展到整个HTTP请求,但此方法可能带来事务管理和性能问题。 3. 在需要访问懒加载属性时,确保在Session内进行操作,或者使用`Hibernate.initialize()`手动...

    【北大青鸟内部教程】jsp中关于Hibernate延时加载的问题

    为解决此问题,可以在Controller层或Service层提前加载关联数据,或者使用Hibernate的“开放Session视图”(Open Session in View)模式。 3. **事务管理**:延时加载需要在一个有效的Hibernate Session内进行。在...

    SSH常用面试题

    #### 十、Hibernate中的Open Session in View模式 1. **模式介绍:**Open Session in View模式是一种使用Hibernate时的高级技术,它通过在每个HTTP请求开始时打开一个Session,在请求结束时关闭这个Session,从而...

    一次hibernate的优化实践

    - 使用Open Session in View模式需谨慎,因为它可能导致事务边界不清,影响性能。 4. **实体设计与映射优化** - 调整懒加载(Lazy Loading)和急加载(Eager Loading)策略,避免因延迟加载引发的额外查询。 - ...

Global site tag (gtag.js) - Google Analytics