您的位置:首页 > 运维架构

解决OpenSessionInViewFilter无法增删改的问题

2013-07-03 18:25 260 查看
我们在使用hibernate的时候,经常会碰到lazy属性,而在实际应用中,我们系统分为三层,对结果处理往往在service层,此时如果想对lazy加载的属性进行操作的时候,hibernate便会报错。

解决办法:1、lazy=false,不推荐,每次加载的时候会多加载很多无用的SQL;

2、使用spring OpenSessionInViewFilter;

OpenSessionInViewFilter所起的作用是,Spring拦截每次请求,并为每次绑定一个session,请求结束后,关闭session。

我在使用OpenSessionInViewFilter,发现添加了这个类之后,之前的增删改操作失效了。

经过长时间折腾,发现是由于事务的缘故。

具体过程如下:spring有一个很强大的功能,便是事务管理, 这个功能使我们少编写了很多代码。一般情况下,我们是将事务管理配置在业务层,即service层。关于spring事务请参照其他资料。

我的spring事务配置如下

<!-- SPRING会在程序抛出unchecked异常的时候回滚,对于try{}cache的异常则不处理 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 需要由交给spring的aop来进行代理的方法的集合,如果应用有自己的方法需有由spring来进行事务控制必须添加方法-->
<!-- 读取数据方法,一般采用只读事务-->
<tx:method name="get*" isolation="DEFAULT" propagation="SUPPORTS"
read-only="true" />
<tx:method name="load*" isolation="DEFAULT" propagation="SUPPORTS"
read-only="true" />
<tx:method name="select*" isolation="DEFAULT" propagation="SUPPORTS"
read-only="true" />
<tx:method name="find*" isolation="DEFAULT" propagation="SUPPORTS"
read-only="true" />
<!-- 查询的日志隔离级别 为DEFAULT,默认也是DEFAULT,事务的传播行为,SUPPORTS,如果之前开启过事务,就加入那个事务,没有就非事务的方式运行 -->
<tx:method name="query*" isolation="DEFAULT" propagation="SUPPORTS"
read-only="true" />
<!-- 除开以上定义的方法,其他方法的事务传播行为为REQUIRED,即有事务就加入事务,没有事务就新建一个事务 -->
<tx:method name="*"  read-only="false"/>
</tx:attributes>
</tx:advice>

<!--
Spring采用AOP进行事务控制,这里指定了凡是实现了以com打头的包及其子包里以service.impl所有类的所有方法需要由事务进行控制
-->
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceOperation" expression="execution(* com..*.service.impl.*.*(..))" />
<aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
</aop:config>

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

说回主题,为什么不能增删改,

那是因为你运行的方法没有开启事务,而hibernate的增删改操作是需要开启事务,所以不能增删改。

运行的方法没有开启事务最直接的原因是配置出了问题,我的问题就是出在这里。

最后说一下OpenSessionInViewFilter的弊;

从它的作用范围我们知道,session会被用户持有整个请求过程,造成的问题便是session过多的被持有,造成连接数不够。

其中的一种情况,业务处理耗费时间过长,访问用户过多都会造成这个问题。

我采用的方法,lazy设为true,如果你有需求使用实例里面lazy属性,就请使用Hibernate.initialize方法强制实例化。

补充:纠正一下上面说的OpenSessionInViewFilter,这个方法并不会造成连接数不够的情况发生,Hibernate获取连接数的行为发生在事务开始的时候,而OpenSessionInViewFilter只是把session绑定至当前请求,并不会开启事务,连接数不够的情况并不会发生。

连接数不够的情况发生在一个事务的执行时间很长的情况,如上面我们说的将service层的所有方法让spring事务管理,如果其中一个业务过程处理时间较长,如上传文件,那么同时多个用户在上传超过连接池的连接数,此时便会出现连接数不够的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐