`

转载SPRING解决事务

阅读更多
 

Spring MVC @Transactional注解方式事务失效的解决办法

分类: Java 378人阅读 评论(0) 收藏 举报

前文提到,最新换了框架,新项目用SpringMVC + Spring JdbcTemplate。搭框架时,发现了一个事务无法正常回滚的问题,记录如下:

首先展示问题:

Spring applicationContext.xml配置:

 

[html] view plaincopy
 
  1.          
  2. <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">  
  3.     <property name="jndiName">  
  4.         <value>java:comp/env/jdbc/will</value>  
  5.     </property>  
  6. </bean>   
  7.       
  8. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
  9.     <property name="dataSource" ref="dataSource" />  
  10. </bean>  
  11.   
  12. <bean id="txManager"  
  13.     class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  14.     <property name="dataSource" ref="dataSource" />  
  15. </bean>  
  16.   
  17. <!-- 事务控制   -->  
  18. <tx:annotation-driven transaction-manager="txManager" />  

 

Spring mvc.dispatcher.xml配置:

 

[html] view plaincopy
 
  1. <!-- 自动扫描的包名 -->    
  2. <context:component-scan base-package="com.will" >   
  3. </context:component-scan>  
  4.   
  5. <!-- 默认的注解映射的支持 -->  
  6. <mvc:annotation-driven />  
  7.   
  8. <!-- 对静态资源文件的访问  -->    
  9. <mvc:default-servlet-handler/>    
  10.     
  11.       
  12. <!-- 拦截器    
  13. <mvc:interceptors>    
  14.     <bean class="com.will.mvc.MyInteceptor" />    
  15. </mvc:interceptors>   
  16. -->   
  17.   
  18. <!-- 视图解释类 -->   
  19. <bean id="viewResolver"    
  20.     class="org.springframework.web.servlet.view.UrlBasedViewResolver">    
  21.     <property name="viewClass"  value="org.springframework.web.servlet.view.JstlView" />    
  22.     <property name="prefix" value="/WEB-INF/pages/" />    
  23.     <property name="suffix" value=".jsp" />    
  24. </bean>     

然后在Service层模拟了一个事务回滚的method case:

 

 

[java] view plaincopy
 
  1. @Transactional  
  2. public boolean save(Person person)  
  3. {  
  4.    for(int id: new int[]{2,3})  
  5.     {  
  6.         personDao.del(id);  
  7.         int j = 1/0;  
  8.     }                  
  9.      
  10.     return false;  
  11. }  

本以为大功告成,在运行save方法时,由于1/0 抛出 java.lang.ArithmeticException: / by zero  RuntimeException,导致事务回归。However,no way! So crazy~

查了下,发现Spring MVC对于事务配置比较讲究,需要额外的配置。解决办法如下:

 

需要在 applicationContext.xml增加:

 

[html] view plaincopy
 
  1. <context:component-scan base-package="com.will">   
  2.     <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />   
  3. </context:component-scan>  

在 Spring mvc.dispatcher.xml增加:

 

 

[html] view plaincopy
 
  1. <context:component-scan base-package="com.will" >   
  2.     <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />   
  3.     <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />    
  4. </context:component-scan>  

 

由于web.xml中配置:

 

[html] view plaincopy
 
  1. <context-param>  
  2.     <param-name>contextConfigLocation</param-name>  
  3.     <param-value>  
  4.              classpath:applicationContext.xml  
  5.     </param-value>  
  6. </context-param>  
  7. <listener>  
  8.     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  9. </listener>  
  10. <servlet>  
  11.     <servlet-name>dispatcher</servlet-name>  
  12.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  13.     <init-param>  
  14.          <param-name>contextConfigLocation</param-name>  
  15.          <param-value>classpath*:/mvc_dispatcher_servlet.xml</param-value>  
  16.     </init-param>  
  17.     <load-on-startup>1</load-on-startup>  
  18. </servlet>  
  19. <servlet-mapping>  
  20.     <servlet-name>dispatcher</servlet-name>  
  21.     <url-pattern>*.do</url-pattern>  
  22. </servlet-mapping>  

 

 

Spring容器优先加载由ServletContextListener(对应applicationContext.xml)产生的父容器,而SpringMVC(对应mvc_dispatcher_servlet.xml)产生的是子容器。子容器Controller进行扫描装配时装配的@Service注解的实例是没有经过事务加强处理,即没有事务处理能力的Service,而父容器进行初始化的Service是保证事务的增强处理能力的。如果不在子容器中将Service exclude掉,此时得到的将是原样的无事务处理能力的Service。

 

经过以上分析,故可以优化上述配置

 

在 applicationContext.xml增加:

 

[html] view plaincopy
 
  1. <context:component-scan base-package="com.will">   
  2. </context:component-scan>  

在 Spring mvc.dispatcher.xml增加:

 

 

[html] view plaincopy
 
  1. <context:component-scan base-package="com.will" >      
  2.     <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />    
  3. </context:component-scan>  
 

经过如上配置,可以发现事务控制部分的日志如下:

 

[html] view plaincopy
 
  1. 2013-09-25 09:53:13,031 [http-8080-2] DEBUG [org.springframework.transaction.annotation.AnnotationTransactionAttributeSource] - Adding transactional method 'save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''  
  2. 2013-09-25 09:53:13,037 [http-8080-2] DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'txManager'  
  3. 2013-09-25 09:53:13,050 [http-8080-2] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Creating new transaction with name [com.will.service.impl.PersonServiceImpl.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''  
  4. 2013-09-25 09:53:13,313 [http-8080-2] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Acquired Connection [jdbc:mysql://localhost:3306/mvc?useUnicode=true&characterEncoding=UTF-8, UserName=root@localhost, MySQL-AB JDBC Driver] for JDBC transaction  
  5. 2013-09-25 09:53:13,323 [http-8080-2] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Switching JDBC Connection [jdbc:mysql://localhost:3306/mvc?useUnicode=true&characterEncoding=UTF-8, UserName=root@localhost, MySQL-AB JDBC Driver] to manual commit  
  6. 2013-09-25 09:53:13,327 [http-8080-2] DEBUG [org.springframework.jdbc.core.JdbcTemplate] - Executing prepared SQL update  
  7. 2013-09-25 09:53:13,328 [http-8080-2] DEBUG [org.springframework.jdbc.core.JdbcTemplate] - Executing prepared SQL statement [delete from person where id=?]  
  8. 2013-09-25 09:53:13,348 [http-8080-2] DEBUG [org.springframework.jdbc.core.JdbcTemplate] - SQL update affected 1 rows  
  9. 2013-09-25 09:53:13,363 [http-8080-2] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Initiating transaction rollback  
  10. 2013-09-25 09:53:13,364 [http-8080-2] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Rolling back JDBC transaction on Connection [jdbc:mysql://localhost:3306/mvc?useUnicode=true&characterEncoding=UTF-8, UserName=root@localhost, MySQL-AB JDBC Driver]  
  11. 2013-09-25 09:53:13,377 [http-8080-2] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Releasing JDBC Connection [jdbc:mysql://localhost:3306/mvc?useUnicode=true&characterEncoding=UTF-8, UserName=root@localhost, MySQL-AB JDBC Driver] after transaction  
  12. 2013-09-25 09:53:13,378 [http-8080-2] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource  

在2013-09-25 09:53:13,363处进行了rollback。
分享到:
评论

相关推荐

    转载 仿百度能力开放平台的spring cloud 微服务框架 ,-open-capacity-platform.zip

    8. **分布式事务**:Spring Cloud Data Flow和Spring Cloud Task可以帮助处理微服务环境中的复杂分布式事务问题。 9. **消息队列**:Spring Cloud Stream和RabbitMQ、Kafka等消息中间件结合,实现异步通信和解耦,...

    springmybatis

    3. 在session 中完成对数据的增删改查和事务提交等. 4. 在用完之后关闭session 。 5. 在java 对象和 数据库之间有做mapping 的配置文件,也通常是xml 文件。 mybatis实战教程(mybatis in action)之一:开发环境搭建 ...

    jsr168 portlet(struts2+spring2.5+hibernate3.3)(转载)

    它简化了配置,支持多种数据访问技术,包括JDBC、Hibernate等,并提供了事务管理、安全管理等企业级服务。 【Hibernate框架】Hibernate3.3是一个持久化框架,它简化了Java对象与数据库之间的交互。通过ORM(Object-...

    华为面试试题,很经典,转载

    【Spring】Spring框架是企业级应用开发的基石,面试可能围绕IoC(Inversion of Control)和AOP(Aspect-Oriented Programming)展开,包括Bean管理、依赖注入、事务处理、Spring MVC、Spring Boot、Spring Data JPA...

    使用open source产品组装你的web应用架构(转载)

    1. Spring Boot:Spring框架的简化版,为快速开发Java Web应用提供便利,内置了许多默认配置。 2. Django:Python的Web开发框架,强调简洁、实用和快速开发,提供完整的MVC结构。 3. Vue.js / React / Angular:...

    Java 最常见 200+ 面试题全解析:面试必备.pdf

    11. SpringBoot/SpringCloud:SpringBoot简化了Spring应用的配置和部署,而SpringCloud则是云环境下微服务架构的一整套解决方案。 12. Hibernate:作为Java对象关系映射工具,Hibernate简化了数据持久化的复杂性,...

    基于jsp动漫之家系统.zip

    Spring负责整个系统的依赖注入与事务管理,SpringMVC处理前端请求和视图的跳转,而MyBatis则进行数据库的持久层操作。HTML5作为前端开发的主要技术,为用户提供了良好的交互体验和丰富的页面元素展示。 系统的用户...

    Java面试资料大集合

    - **Spring框架**:依赖注入(DI)、AOP、事务管理等核心概念。 - **MyBatis**:持久层框架,动态SQL和映射文件的使用。 - **Maven或Gradle**:构建工具的使用和配置。 9. **数据库** - **SQL语句**:增删改查...

Global site tag (gtag.js) - Google Analytics