转载:http://blog.csdn.net/z69183787/article/details/37819831

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

首先展示问题:

Spring applicationContext.xml配置:

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

Spring mvc.dispatcher.xml配置:

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

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

  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. return false;
  10. }

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

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

需要在 applicationContext.xml增加:

  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增加:

  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中配置:

  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。

( update 2014.05.27  今天看见一种说法:key word =双亲上下文。不使用ContextLoaderListener监听器来加载spring的配置,改用DispatcherServlet来加载spring的配置,不要双亲上下文,只使用一个DispatcherServlet就不会出现上述问题。笔者这里未测过这个办法,因为我自己的业务需要一个extends ContextLoaderListener的selfListener,有兴趣的朋友可以自己测试下这个说法,并欢迎把测试的结果与我交流 :) )

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

在 applicationContext.xml增加:

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

在 Spring mvc.dispatcher.xml增加:

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

经过如上配置,可以发现事务控制部分,可以回滚。

另外:也不是必须运行时异常才会回滚。@Transactional  (rollbackfor=Exception.class) 这样设置的话,任何异常都可以回滚。

springmvc事务回滚失效的更多相关文章

  1. springmvc 事务回滚说明

    Spring中的@Transactional(rollbackFor = Exception.class)属性详解 序言 今天我在写代码的时候,看到了.一个注解@Transactional(rollb ...

  2. springmvc mybatis 声明式事务管理回滚失效,(checked回滚)捕捉异常,传输错误信息

    一.知识点及问题 后端框架: Spring .Spring mvc .mybatis 业务需求: client先从服务端获取用户大量信息到client,编辑完毕之后统一Post至服务端,对于数据的改动 ...

  3. (转)spring异常抛出触发事务回滚策略

    背景:在面试时候问到事务方法在调用过程中出现异常,是否会传递的问题,平时接触的比较少,有些懵逼. spring异常抛出触发事务回滚策略 Spring.EJB的声明式事务默认情况下都是在抛出unchec ...

  4. Spring-Java事物回滚失效处理

    spring-Java事物回滚失效处理最近在做项目中,无意间发现有个类在抛事物回滚操作,数据也正常的插入到数据库当中了,于是仔细查看看一下具体原因. 一切还是要从Java的检查型异常和非检查型异常说起 ...

  5. SQL 事务回滚

    事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务,SQL Server能将逻辑相关的一组操作绑定在一起,以便服 ...

  6. Spring异常抛出触发事务回滚

    Spring.EJB的声明式事务默认情况下都是在抛出unchecked exception后才会触发事务的回滚 /** * 如果在spring事务配置中不为切入点(如这里的切入点可以定义成test*) ...

  7. 【Java EE 学习 19】【使用过滤器实现全站压缩】【使用ThreadLocal模式解决跨DAO事务回滚问题】

    一.使用过滤器实现全站压缩 1.目标:对网站的所有JSP页面进行页面压缩,减少用户流量的使用.但是对图片和视频不进行压缩,因为图片和视频的压缩率很小,而且处理所需要的服务器资源很大. 2.实现原理: ...

  8. SqlServer事务回滚(2)

    SQL Server 2008中SQL应用系列--目录索引 SQL事务 一.事务概念    事务是一种机制.是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行.因此事务是 ...

  9. jfinal 基本应用 --事务回滚

    事务回滚 1.当时需要用到事务回滚,但是看到网上只有问题,没有真实的到底怎么用法. 2.我看了一下文档,结合了网上的大神的博客. 第一种方法: Db.tx(new IAtom(){ @Override ...

随机推荐

  1. Eclipse中把Java工程修改成web工程

    Eclipse中把Java工程修改成web工程 点击项目:右击:选择properties--输入project facets,将“Dynamic Web Module”打勾即可:

  2. c/c++的typedef/using类型别名

    久而久之,发现c/c++的typedef给类型自定义别名的语法糖就保证设计的一致性而言,确实是个相当不错的特性,跟oracle pl/sql的rowtype或type一样,可惜java.mysql均不 ...

  3. MySQL中INSERT的一般用法

    原文链接:http://www.blogjava.net/midnightPigMan/archive/2014/12/15/421406.html MySQL中INSERT的一般用法 INSERT语 ...

  4. 20145331魏澍琛《网络对抗》Exp4 恶意代码分析

    20145331魏澍琛<网络对抗>Exp4 恶意代码分析 基础问题回答 1.如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监控下系统一天天的到底在干些什么.请设计下你想监控的操作 ...

  5. 【源码编译】spark源码编译

    本文采用cdh版本spark-1.6.0-cdh5.12.0 1.源码包下载 2.进入根目录编译,编译的方式有2种 maven mvn clean package \ -DskipTests -Pha ...

  6. @SuppressWarings注解的作用和用法

    一.前言 编码时我们总会发现如下变量未被使用的警告提示: 上述代码编译通过且可以运行,但每行前面的“感叹号”就严重阻碍了我们判断该行是否设置的断点了.这时我们可以在方法前添加 @SuppressWar ...

  7. Linux(CentOS 6.5) 下安装MySql 5.7.18 二进制版本粗浅攻略

    鉴于Linux和mysql因不同版本,安装方式也不同,所以在阅读本攻略前,请确保各位同学的版本和我的Linux.MySql 版本一致. 如果不一致,只能参考. 我的版本: Linux CentOS 6 ...

  8. LINK : fatal error LNK1104: 无法打开文件“libboost_serialization-vc90-mt-gd-1_62.lib”

    boost安装:https://www.cnblogs.com/sea-stream/p/10205425.html 在vs中添加

  9. 退出shell 脚本

    #!/bin/bash export TOP_PID=$$ trap 'exit 1' TERM exit_script(){ kill -s TERM $TOP_PID } echo "b ...

  10. Windows10中注册 regsvr32 xxx.ocx报错but the call to DIIRegisterServer failed with error code 0x80040200

    网站中有读取居民身份证的机器,需要安装一些注册activeX控件然后进入指定目录下执行以下命令regsvr32 xxx.ocx报了个错: but the call to DIIRegisterServ ...