OpenSessionInViewFilter的作用
Spring为我们解决Hibernate的Session的关闭与开启问题。
Hibernate 允许对关联对象、属性进行延迟加载,但是必须保证延迟加载的操作限于同一个 Hibernate Session 范围之内进行。如果 Service 层返回一个启用了延迟加载功能的领域对象给 Web 层,当 Web 层访问到那些需要延迟加载的数据时,由于加载领域对象的 Hibernate Session 已经关闭,这些导致延迟加载数据的访问异常
(eg: org.hibernate.LazyInitializationException:(LazyInitializationException.java:42)
- failed to lazily initialize a collection of role: cn.easyjava.bean.product.ProductType.childtypes, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: cn.easyjava.bean.product.ProductType.childtypes, no session or session was closed)。
用来把一个Hibernate Session和一次完整的请求过程对应的线程相绑定。目的是为了实现"Open Session in View"的模式。例如: 它允许在事务提交之后延迟加载显示所需要的对象。
而Spring为我们提供的OpenSessionInViewFilter过滤器为我们很好的解决了这个问题。OpenSessionInViewFilter的主要功能是用来把一个Hibernate Session和一次完整的请求过程对应的线程相绑定。目的是为了实现"Open Session in View"的模式。例如:它允许在事务提交之后延迟加载显示所需要的对象。
OpenSessionInViewFilter 过滤器将 Hibernate Session 绑定到请求线程中,它将自动被 Spring 的事务管理器探测到。所以 OpenSessionInViewFilter 适用于 Service 层使用HibernateTransactionManager 或 JtaTransactionManager 进行事务管理的环境,也可以用于非事务只读的数据操作中。
<filter>
<filter-name>Spring OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<!--
指定org.springframework.orm.hibernate3.LocalSessionFactoryBean在spring配置文件中的名称,默认值为sessionFactory
如果LocalSessionFactoryBean在spring中的名称不是sessionFactory,该参数一定要指定,否则会出现找不到sessionFactory的例外
-->
<param-name>sessionFactoryBean</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Spring OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sunsea08/archive/2009/09/12/4545186.aspx
------------------------------------------------- 错误问题解决1 ----------------------------------------------------------------------------------------
web.xml原始配置:
<!-- 过滤spring中对于hibernate的session关闭管理 -->
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
自己写的serviceImpl.java文件中的保存更新方法(我所出现问题的位置是:多行提交的方法),在运行时总报错。如下:
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
后来在网上狂搜解决方案,将web.xml文件改为如下:
<!-- 过滤spring中对于hibernate的session关闭管理 -->
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value>
</init-param>
</filter>
上面的异常解决了,但又报出新的异常,如下:
org.hibernate.HibernateException: Illegal attempt to associate a collection
with two open sessions
解决这个问题的办法就是要把singleSession的值改为true
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
我无奈了,这两个错误就好像是相互的,只能解决一个。。。
从网上搜。。还真我出现的这咱情况。。结果如下:
说明一下Open Session in View的作用,就是允许在每次的整个request的过程中使用同一个hibernate session,可以在这个request任何时期lazy loading数据。
如果是singleSession=false的话,就不会在每次的整个request的过程中使用同一个hibernate session,而是每个数据访问都会产生各自的seesion,等于没有Open Session in View。
OpenSessionInViewFilter默认是不会对session 进行flush的,并且flush mode 是 never
代码:
protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
session.setFlushMode(FlushMode.NEVER);
return session;
}
看getSession的方式就知道,把flush mode 设为FlushMode.NEVER,这样就算是commit的时候也不会session flush,
如果想在完成request过程中更新数据的话, 那就需要先把flush model设为FlushMode.AUTO,再在更新完数据后flush.
OpenSessionInView默认的FlushMode为
代码:
FlushMode.NEVER
可以采用在写保存更新删除代码的时候手动更改FlushMode
代码:
this.getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
session.setFlushMode(FlushMode.AUTO);
session.save(user);
session.flush();
return null;
}
});
但是这样做太繁琐了,第二种方式是采用spring的事务声明
代码:
<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="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>
太巧了,我们的框架就采用了这位前辈所说的第二种方案,但是为什么我把配置文件改成他说的样式还是不行呢?
郁闷中惊奇发现,不是我所有的多行提交都出问题,而只是个别的。经过一翻考虑后,确定自己写的方法体没有
问题了,那么就是方法名了,才发现,还真是方法名的问题。
原来自己写的serviceImpl.java文件的方法名要用“load”“save”“add”“update”“remove”这些词开头,这个就好像是通过这个bean-service.xml文件管理方法名一样,超出这个范围了,hibernate自身的作用就发挥不出来了。
----------------------------------------------------- 错误问题解决 2------------------------------------------------------------------------------
同时使用ContextLoaderListener和ContextLoaderPlugIn,不要在ContextLoaderPlugIn里面加入applicationContext.xml,只要加入action-servlet.xml,OpenSessionInView可生效。
因为 ContextLoaderListener保存的对象的是key WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE!而 ContextLoaderPlugIn保存的对象的是key是attrName,这个attrName和 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值是不一样的,而 OpenSessionInViewFilter是从 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE获取spring配置信息的,所以如果将applicationContext.xml以插件的形式配置,则OpenSessionInViewFilter获取不到spring 的配置信息,OpenSessionInViewFilter可能会失效。
分享到:
相关推荐
`OpenSessionInViewFilter`是Spring为配合Hibernate设计的一个过滤器,其主要作用是在Web请求处理过程中打开并维持一个Hibernate Session,直到视图渲染完成。这样做的好处在于能够确保在整个请求处理过程中Session...
为了练手培训,给大家准备的 Open Session In View 的简单例子,纯代码,大家可以参考,其中主要说了六部分内容: 1.通过接口编程 2.通过spring注入dao到 action 3.通过 open session in view filter 支持 延迟加载...
2. **启用OpenSessionInView过滤器**:在web.xml中配置OpenSessionInViewFilter,该过滤器会在HTTP请求开始时开启一个新的Hibernate Session,并在请求结束时提交或回滚事务并关闭Session。 3. **编写业务逻辑**:在...
`Open Session In View`的主要作用是在Web请求的开始阶段打开`Hibernate session`,并在请求结束时自动关闭该session。这样做的好处在于,可以确保在整个请求处理过程中session始终处于可用状态,使得在视图(View)层...
同时,需要注意的是,OpenSessionInView模式虽然方便,但也会带来潜在的问题,如事务边界不清晰和会话泄漏。因此,在实际应用中,应结合具体需求谨慎使用,并考虑使用更现代的解决方案,如Spring Data JPA的...
配置OpenSessionInView过滤器**: 为了确保在一个请求生命周期内只开启一次Session,可以使用Spring提供的`OpenSessionInViewFilter`。其配置如下: ```xml <filter-name>openSessionInView <filter-class>org....
`CharacterEncodingFilter`的作用就是确保请求和响应的字符编码统一为指定的格式,通常设置为UTF-8,避免因为编码问题导致的数据丢失或显示错误。通过在Web应用的配置文件(如web.xml)中添加该过滤器,可以全局设定...
OpenSessionInView(OSIV)模式是SSH整合中常见的一种优化策略,它在用户的一次HTTP请求过程中保持Hibernate Session,避免了多次打开和关闭Session,减少了N+1查询问题,提高了性能。 **Spring** 是一个全面的企业...
- 配置OpenSessionInView过滤器以实现懒加载: ```xml <filter-name>openSessionInView <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter <filter-name>...
- **配置延迟加载时使用OpenSessionInView**: OpenSessionInView是一种技术,用于解决Hibernate在多线程环境下的一级缓存问题。通过在web.xml中配置`OpenSessionInViewFilter`,可以实现持久化层的事务与视图渲染...
OpenSessionInViewFilter是Spring框架中一个非常重要的组件,主要用于解决数据访问...这个文档应该包含了OpenSessionInViewFilter的源码分析、配置示例以及常见问题的解答,对理解该过滤器的功能和工作原理非常有帮助。
在整合JSF、Spring和Hibernate时,通常会使用Spring的OpenSessionInView模式来处理数据库会话。这能确保在HTTP请求的整个生命周期内保持有效的Hibernate Session,从而避免可能出现的数据访问问题。 至于压缩包中的...
8. **配置OpenSessionInView过滤器**: - Spring提供了一个名为`OpenSessionInViewFilter`的过滤器,用于解决在Web应用中处理请求时的事务边界问题。它确保每个HTTP请求都有一个开启的Hibernate Session。 - 配置...
`数据库.txt` 可能包含了关于数据库设计、SQL查询优化或其他数据库管理方面的内容,而 `osiv` 文件则可能详细阐述了OSIV的工作原理或如何在项目中配置和使用。 总结来说,`lazy="true"` 是一种有效的性能优化策略,...
**表格13**: web.xml配置文件OpenSessionInView设置(必需设置) ```xml <filter-name>openSessionInViewFilter <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter ...
7. **配置OpenSessionInView模式**:在`web.xml`中配置`OpenSessionInViewFilter`,目的是解决在HTTP请求结束后才提交事务导致的懒加载问题。通过在视图渲染阶段保持数据库会话,可以确保所有延迟加载的数据都能正确...
本方案主要探讨如何在基于Hibernate和Spring框架的环境中实现多数据库的管理,特别是在`OpenSessionInView`模式下的配置。 首先,我们看到在`applicationContext.xml`配置文件中定义了两个数据源,一个用于读操作...