初次使用spring3结合hibernate4做项目,迅速配置完成,测试,一切正常。
然而,当我在service层中另外开启一个线程,线程中的方法需要进行数据库操作,这个时候,悲催的抛出了异常:-org.hibernate.HibernateException: No Session found for current thread
当然,hibernate4的session是和当前线程绑定的,多线程中用sessionFactory.getCurrentSession()获取当前session自然不存在,不存在又不会自动创建,所以抛出了异常,无可厚非。
于是就想着怎么解决这个问题。
遍翻google、baidu,大部分都说如何如何配置,设置事务的传播属性propagation="REQUIRED",开启opensessioninview filter等等,无一对此问题有何解释(当然或许是我没翻到,有知道的麻烦告知)
在http://sishuok.com/forum/blogPost/list/2625.html#7523上看到相关配置,我就想作者这个项目该多线程运行正常吧,果断下载源码,修改测试,oh。。。跟我的错一模一样!
于是再想,多线程中调用了service方法,service方法里面的数据库操作方法无法开启事务,那如果在controller中开启多线程调用service会不会也不能开启事务呢?果断测试,一切正常!不过这当然得正常,在controll中的多线程调用service方法就和平常的一个请求调用service方法一模一样,不正常那才不正常了呢!
于是再想,如果把事务配置在service和dao上,那么service中开启多线程后,虽然多线程中的service没有事务,但是service中的dao有事务啊,当然多个数据库操作无法在一个事务中了,也不管那么多了,先测试,于是修改aop配置为:
<aop:config expose-proxy="true">
<aop:pointcut id="managerMethod" expression="execution(* com.news.service.*Service..*.*(..)) or execution(* com.news.dao.*Dao..*.*(..))" />
<aop:advisor pointcut-ref="managerMethod" advice-ref="txAdvice" />
</aop:config>
测试,成功运行!
以前事务管理类为org.springframework.orm.hibernate4.HibernateTransactionManager时项目无恙,换成hibernate4对应的org.springframework.orm.hibernate4.HibernateTransactionManager后就出现了这个问题,摸索了半天也没彻底解决,有高人知道完美解决方案麻烦赐教。
先这样配着吧,虽然有缺陷,也只有让它先跑着了。
项目事务相关配置如下所示:
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="change*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="get*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="query*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config expose-proxy="true">
<aop:pointcut id="managerMethod" expression="execution(* com.news.service.*Service..*.*(..)) or execution(* com.news.dao.*Dao..*.*(..))" />
<aop:advisor pointcut-ref="managerMethod" advice-ref="txAdvice" />
</aop:config>