springMvc4+hibernate4的一个奇葩的网上众说纷纭的错误

springMvc4+hibernate4项目运行报错如下:


org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)


Dao层session的获取的方式如下

@Autowired
    private SessionFactory sessionFactory;

    protected Session session() {
        return sessionFactory.getCurrentSession();
    }

spring-context.xml中配置的是注解事务

<!-- 配置 Annotation 驱动,扫描@Transactional注解的类定义事务  -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

网上居然有人说hibernate4不支持hibernate3的 getcurrentSession,建议你用openSession。
的确使用openSession就不会报错了,但这种说法显然是误导大众了。hibernate4 也支持getcurrentSession 会自动关闭session,如果使用openSession 要自己手动关闭。并且自己openSession就不属于hibernate4管理了,每查一次就手动关一次。

使用 hibernate4,在不使用OpenSessionInView模式时,在使用getCurrentSession()时会有如下问题:

当有一个方法list 传播行为为Supports,当在另一个方法getPage()(无事务)调用list方法时会抛出org.hibernate.HibernateException: No Session found for current thread 异常。
这是因为getCurrentSession()在没有session的情况下不会自动创建一个,不知道这是不是Spring3.1实现的bug,欢迎大家讨论下。

<!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到-->

<!-- 定义事务规则 -->
   <tx:advice id="txAdvice" transaction-manager="transactionManager">
       <tx:attributes>
           <tx:method name="save*" propagation="REQUIRED" />
           <tx:method name="add*" propagation="REQUIRED" />
           <tx:method name="create*" propagation="REQUIRED" />
           <tx:method name="insert*" propagation="REQUIRED" />
           <tx:method name="update*" propagation="REQUIRED" />
           <tx:method name="merge*" propagation="REQUIRED" />
           <tx:method name="del*" propagation="REQUIRED" />
           <tx:method name="remove*" propagation="REQUIRED" />
           <tx:method name="put*" propagation="REQUIRED" />
           <tx:method name="gen*" propagation="REQUIRED" />
           <tx:method name="complete*" propagation="REQUIRED" />
           <tx:method name="import*" propagation="REQUIRED" />
           <tx:method name="open*" propagation="REQUIRED" />
           <tx:method name="publish*" propagation="REQUIRED" />
           <tx:method name="init*" propagation="REQUIRED" />
           <tx:method name="change*" propagation="REQUIRED" />
           <tx:method name="*Change*" propagation="REQUIRED" />
           <!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到-->  
           <tx:method name="*" propagation="REQUIRED" read-only="true" />
       </tx:attributes>
   </tx:advice>
   <!-- 定义事务入口 -->
   <aop:config>
       <aop:pointcut id="txPointcut" expression="execution(* com.acts.web.modules.*.service.*.*(..))" />
       <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
   </aop:config>
qrcode_for_gh_bf7a27ade681_258.jpg

作者: 小柒

出处: https://blog.52itstyle.com

分享是快乐的,也见证了个人成长历程,文章大多都是工作经验总结以及平时学习积累,基于自身认知不足之处在所难免,也请大家指正,共同进步。

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 如有问题, 可邮件(345849402@qq.com)咨询。