最近在来到一个新公司,使用新的spring3,hibernate4框架,在使用注解事务总是不起作用。

首先看配置文件,然后再讲解。

首先是springmvc-servlet.xml,这个配置文件是servlet的加载文件,

引用这个文件的位置是在web.xml里

  1. <!-- 定义 springmvcServlet -->
  2. <servlet>
  3. <servlet-name>springmvc</servlet-name>
  4. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  5. <init-param>
  6. <!-- 默认/WEB-INF/[servlet名字]-servlet.xml加载上下文,
  7. 如果配置了contextConfigLocation参数,
  8. 将使用classpath:/springmvc-servlet.xml加载上下文
  9. -->
  10. <param-name>contextConfigLocation</param-name>
  11. <param-value>classpath:/springmvc-servlet.xml</param-value>
  12. </init-param>
  13. <load-on-startup>1</load-on-startup>
  14. </servlet>
  15. <!-- 拦截匹配的请求,这里所有请求采用名字为mvc-dispatcher的DispatcherServlet处理 -->
  16. <servlet-mapping>
  17. <servlet-name>springmvc</servlet-name>
  18. <url-pattern>/</url-pattern>
  19. </servlet-mapping>
  1. <!-- 启动自动扫描该包下所有的Bean(例如@Controller) 这块很重要,会影响到事务-->
  2. <context:component-scan base-package="com.bpz.demo" use-default-filters="false">
  3. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:include-filter>
  4. </context:component-scan>
  5.  
  6. <!-- 定义视图解析器 -->
  7. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  8. <property name="prefix">
  9. <value>/jsp/</value>
  10. </property>
  11. <property name="suffix">
  12. <value>.jsp</value>
  13. </property>
  14. </bean>

然后是applicationcontext.xml

  1. <!-- 启动自动扫描该包下所有的Bean 注意这块,也非常重要 -->
  2. <context:component-scan base-package="com.bpz.demo" use-default-filters="false">
  3. <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"></context:include-filter>
  4. <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"></context:include-filter>
  5. </context:component-scan>
  6. <!-- Hibernate4 -->
  7. <!-- 加载资源文件 其中包含变量信息,必须在Spring配置文件的最前面加载,即第一个加载-->
  8. <context:property-placeholder location="classpath:mysql.properties" />
  9.  
  10. <bean id="sessionFactory"
  11. class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
  12. <property name="dataSource" ref="dataSource" />
  13. <property name="packagesToScan">
  14. <list>
  15. <!-- 可以加多个包 -->
  16. <value>com.bpz.demo.entity</value>
  17. </list>
  18. </property>
  19. <property name="hibernateProperties">
  20. <props>
  21. <prop key="hibernate.dialect">${hibernate.dialect}</prop>
  22. <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
  23. </props>
  24. </property>
  25. </bean>
  26.  
  27. <!-- 数据库映射 -->
  28. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  29. <property name="driverClassName" value="${jdbc.driverClassName}" />
  30. <property name="url" value="${jdbc.url}" />
  31. <property name="username" value="${jdbc.user}" />
  32. <property name="password" value="${jdbc.pass}" />
  33. </bean>
  34. <!-- 基于注释的事务,当注释中发现@Transactional时,使用id为“transactionManager”的事务管理器 -->
  35. <!-- 如果没有设置transaction-manager的值,则spring以缺省默认的事务管理器来处理事务,默认事务管理器为第一个加载的事务管理器 -->
  36. <tx:annotation-driven transaction-manager="transactionManager"/>
  37. <!-- 配置Hibernate事务管理器 -->
  38. <bean id="transactionManager"
  39. class="org.springframework.orm.hibernate4.HibernateTransactionManager">
  40. <property name="sessionFactory" ref="sessionFactory" />
  41. </bean>

引用位置是在web.xml里的

  1. <context-param>
  2. <param-name>contextConfigLocation</param-name>
  3. <param-value>classpath:/applicationcontext.xml</param-value>
  4. </context-param>
  5. <listener>
  6. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  7. </listener>

以上是一个正确的配置方式,事务起作用完全没有问题。现在说说为什么很多时候配置的事务未起作用呢。

1.如果事务未起作用还未报错或异常,那应该是使用了sessionFactory.openSession(),在hibernate4里,如果使用spring来管理事务,需要使用

Session session = sessionFactory.getCurrentSession();来获取session。

2.如果使用了Session session = sessionFactory.getCurrentSession();来获取session有可能会报一个异常:

  1. No Session found for current thread

为什么会出现这种情况呢,这和上面的配置就有关系了。一般情况下很多人为了省事,在servlet配置文件里直接

  1. <context:component-scan base-package="com.bpz.demo">
  2. </context:component-scan>

这样配置,对全部代码扫描,但是在servlet里并没有配置事务,所以事务完全不起作用.

不起作用的原因,在另一篇转载的文章里可以看到。

web.xml 中的listener、 filter、servlet 加载顺序及其详解

servlet是最后加载的,在最后使用

  1. context:component-scan

扫描的时候,也会发现在有@Service,@Reposity等注解并进行实例化,由于在servlet配置文件里未配置事务,所以造成了事务不起作用,

看下面的源代码:

  1. public Session currentSession() throws HibernateException {
  2. Object value = TransactionSynchronizationManager.getResource(this.sessionFactory);
  3. if(value instanceof Session) {
  4. return (Session)value;
  5. } else if(value instanceof SessionHolder) {
  6. SessionHolder session2 = (SessionHolder)value;
  7. Session session1 = session2.getSession();
  8. if(TransactionSynchronizationManager.isSynchronizationActive() && !session2.isSynchronizedWithTransaction()) {
  9. TransactionSynchronizationManager.registerSynchronization(new SpringSessionSynchronization(session2, this.sessionFactory));
  10. session2.setSynchronizedWithTransaction(true);
  11. FlushMode flushMode = session1.getFlushMode();
  12. if(flushMode.equals(FlushMode.MANUAL) && !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
  13. session1.setFlushMode(FlushMode.AUTO);
  14. session2.setPreviousFlushMode(flushMode);
  15. }
  16. }
  17.  
  18. return session1;
  19. } else if(this.jtaSessionContext != null) {
  20. Session session = this.jtaSessionContext.currentSession();
  21. if(TransactionSynchronizationManager.isSynchronizationActive()) {
  22. TransactionSynchronizationManager.registerSynchronization(new SpringFlushSynchronization(session));
  23. }
  24.  
  25. return session;
  26. } else {
  27. throw new HibernateException("No Session found for current thread");
  28. }
  29. }

1:@Transactional声明的方法执行时,Spring的TransactionManager会自动Open Session,自动开启事务,并且将此Sesion绑定到SpringSessionContext(实际上是TransactionSynchronizationManager的ThreadLocal的Map)中..而@Transactional的声明只有

  1. tx:annotation-driven配置才会处理这个声明

2:SessionFactory.getCurrentSession()方法执行时,调用SpringSessionContext.currentSession()从TransactionSynchronizationManager的上下文中查找 当前的Session

3:找到后返回当前的Session,找不到,则返回HibernateException("No Session found for current thread")

对上面源代码的理解。

so:处理事务不起作用的办法就是servlet里做好自己的事,扫描@controller就可以了,这不但能加快启动速度,而且最主要的就是不会  画蛇添足。

  1.  

画蛇添足-记spring3 hibernate4整合时遇到问题的处理办法的更多相关文章

  1. Struts2,Spring3,Hibernate4整合--SSH框架

    Struts2,Spring3,Hibernate4整合--SSH框架(学习中) 一.包的导入 1.Spring包 2.Hibernate 包 3.struts 包 (还欠 struts2-sprin ...

  2. spring3 hibernate4整合后无法查询数据库

    spring3和hibernate4整合后无法查询数据库,一方面是因为已经spring3中没有对hibernate4 HibernateTemplate的支持,另外一个就是需要在hibernate的配 ...

  3. hibernate4整合spring3事务问题

    本文是作者在对hibernate4+spring3+struts2整合中遇到的一个问题.对s2sh进行了基本的整合搭建以后,就是对事务的控制管理,将hibernate的事务交由spring管理.根据网 ...

  4. 使用Maven搭建Struts2+Spring3+Hibernate4的整合开发环境

    做了三年多的JavaEE开发了,在平时的JavaEE开发中,为了能够用最快的速度开发项目,一般都会选择使用Struts2,SpringMVC,Spring,Hibernate,MyBatis这些开源框 ...

  5. springmvc+spring3+hibernate4框架简单整合,简单实现增删改查功能

    转自:https://blog.csdn.net/thinkingcao/article/details/52472252 C 所用到的jar包     数据库表 数据库表就不用教大家了,一张表,很简 ...

  6. hibernate4整合spring3.1的过程中的异常问题

    (1)hibernate4整合spring3.1的过程中,发现了java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider异常 ...

  7. spring3+structs2整合hibernate4时报org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void sy.dao.impl.UserDaoImpl.setSessionFactory(org.hibernate.SessionFactory);

    今天在spring3+structs2整合hibernate4时报如下错误,一直找不到原因: org.springframework.beans.factory.BeanCreationExcepti ...

  8. Maven搭建Struts2+Spring3+Hibernate4框架

    做了三年多的JavaEE开发了,在平时的JavaEE开发中,为了能够用最快的速度开发项目,一般都会选择使用Struts2,SpringMVC,Spring,Hibernate,MyBatis这些开源框 ...

  9. mybatis和spring3.1整合

    因spring3发布时mybatis还没有出正式版本,所以spring没有整合最新的mybatis.不过社区倒是开发了一个中间件. 需要的jar包 mybatis-3.0.6.jar mybatis- ...

随机推荐

  1. TypeScript 0.9.1 发布,新增 typeof 关键字

    TypeScript 0.9.1 发布了,该版本提升了编译器和语言的性能,增加新的语言特性 typeof ,更好的 this 处理等.详细介绍请看发行说明. TypeScript 是微软新推出的一种语 ...

  2. Dynamic CRM 2013学习笔记(八)过滤查找控件 (类似省市联动)

    我们经常要实现类似省市联动一样的功能,常见的就是二个查找控件,一个选择了省后,另一个市的查找控件就自动过滤了,只显示当前省下的市,而不是所有的市.当然这是最简单的,实际工作中还有更复杂的功能要通过过滤 ...

  3. 谷歌(Chrome)浏览器调试JavaScript小技巧

    谷歌浏览器不仅仅可以用来上网,对于开发人员来说,它更像是一款强大的开发辅助工具. 工欲善其事必先利其器,接下来笔者给大家分享一些Chrome的使用方法. 假如读者了解如何在Chrome中添加JavaS ...

  4. JavaScript 函数惰性载入

    最近看JavaScript高级程序设计,大有收获,接下来几天写一下读书笔记.之前写了一篇Ajax初步理解的随笔,里面有个函数用来创建XmlHttpRequest对象,浏览器兼容性原因,写出的代码通过大 ...

  5. 深入浅出OOP(六): 理解C#的Enums

    MSDN定义:枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法.  例如,假设您必须定义一个变量,该变量的值表示一周中的一天. 该变量只能存储七个有意义的值. 若要定义这 ...

  6. ASP.NET 5系列教程 (二):Hello World

    本篇文章内容比较基础,主要是向大家展示如何创建一个 ASP.NET 5 工程,主要包含内容如下: 创建ASP.NET 5 工程 添加 Todo 控制器 安装 K Version Manager 执行 ...

  7. Atitit.信息论原理概论attilax总结

    Atitit.信息论原理概论attilax总结 1. <信息论基础(原书第2版)>((美)科弗(Cover...)[简介_书评_在线阅读] - 当当图书.html1 2. <信息论- ...

  8. atitit.设计模式(2) -----查表模式/ command 总结

    atitit.设计模式(2) -----查表模式/ command 总结 1. 应用场景: 1 1. 取代一瓦if else 1 2. 建设api rpc风格的时候儿. 1 3. 菜单是Command ...

  9. iOS开发-迭代器模式

    迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示.开发过程中,我们可能需要针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但是我们不希望 ...

  10. js 生成笛卡尔积

    其实生成 笛卡尔积的方法原本很简单,for循环就可以了, function discarts() { //笛卡尔积 var twodDscartes = function (a, b) { var r ...