spring3+hibernate4 service 中多线程事务异常及解决

初次使用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>

Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.