在业务代码中,有如下两种情况,比如:
throw new RuntimeException("xxxxxxxxxxxx"); 事务回滚
throw new Exception("xxxxxxxxxxxx"); 事务没有回滚

1).Spring的AOP即声明式事务管理默认是针对unchecked exception回滚。也就是默认对RuntimeException()异常或是其子类进行事务回滚;checked异常,即Exception可try{}捕获的不会回滚,如果使用try-catch捕获抛出的unchecked异常后没有在catch块中采用页面硬编码的方式使用spring api对事务做显式的回滚,则事务不会回滚, “将异常捕获,并且在catch块中不对事务做显式提交=生吞掉异常” ,要想捕获非运行时异常则需要如下配置:

解决办法:
1.在针对事务的类中抛出RuntimeException异常,而不是抛出Exception。
2.在txAdive中增加rollback-for,里面写自己的exception,例如自己写的exception:

<tx:advice id="txAdvice" transaction-manager="transactionManager">
   <tx:attributes>
     <tx:method name="*" rollback-for="com.cn.untils.exception.XyzException"/>
   </tx:attributes>
 </tx:advice>
 
或者
定义不会滚的异常

<tx:advice id="txAdvice">
    <tx:attributes>
       <tx:method name="update*" no-rollback-for="IOException"/>
       <tx:method name="*"/>
    </tx:attributes>
 </tx:advice>

2).spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback(Spring默认取决于是否抛出runtime异常).
 如果抛出runtime exception 并在你的业务方法中没有catch到的话,事务会回滚。 
 一般不需要在业务方法中catch异常,如果非要catch,在做完你想做的工作后(比如关闭文件等)一定要抛出runtime exception,否则spring会将你的操作commit,这样就会产生脏数据.所以你的catch代码是画蛇添足。
 
如:
try {  
    //bisiness logic code  
} catch(Exception e) {  
    //handle the exception  
}

由此可以推知,在spring中如果某个业务方法被一个 整个包裹起来,则这个业务方法也就等于脱离了spring事务的管理,因为没有任何异常会从业务方法中抛出!全被捕获并吞掉,导致spring异常抛出触发事务回滚策略失效。
 不过,如果在catch代码块中采用页面硬编码的方式使用spring api对事务做显式的回滚,这样写也未尝不可。
 
 3).基于注解的事务:

Transactional的异常控制,默认是Check Exception 不回滚,unCheck Exception回滚
 如果配置了rollbackFor 和 noRollbackFor 且两个都是用同样的异常,那么遇到该异常,还是回滚
 rollbackFor 和noRollbackFor 配置也许不会含盖所有异常,对于遗漏的按照Check Exception 不回滚,unCheck Exception回滚

默认遇到throw new RuntimeException("...");会回滚
需要捕获的throw new Exception("...");不会回滚

// 指定回滚
@Transactional(rollbackFor=Exception.class) 
    public void methodName() {
       // 不会回滚
       throw new Exception("...");
    } 
//指定不回滚
@Transactional(noRollbackFor=Exception.class)
    public ItimDaoImpl getItemDaoImpl() {
        // 会回滚
        throw new RuntimeException("注释");
    }

// 如果有事务,那么加入事务,没有的话新建一个(不写的情况下)
    @Transactional(propagation=Propagation.REQUIRED) 
    // 容器不为这个方法开启事务
    @Transactional(propagation=Propagation.NOT_SUPPORTED)
    // 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
    @Transactional(propagation=Propagation.REQUIRES_NEW) 
    // 必须在一个已有的事务中执行,否则抛出异常
    @Transactional(propagation=Propagation.MANDATORY)
    // 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
    @Transactional(propagation=Propagation.NEVER) 
    // 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
    @Transactional(propagation=Propagation.SUPPORTS) 
    
    /*
    public void methodName(){
       // 本类的修改方法 1
       update();
       // 调用其他类的修改方法
       otherBean.update();
       // 本类的修改方法 2
       update();
    }
    other失败了不会影响 本类的修改提交成功
    本类update的失败,other也失败
    */
@Transactional(propagation=Propagation.NESTED) 
// readOnly=true只读,不能更新,删除 
@Transactional (propagation = Propagation.REQUIRED,readOnly=true) 
// 设置超时时间
@Transactional (propagation = Propagation.REQUIRED,timeout=30)
// 设置数据库隔离级别
@Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)

转自:http://blog.sina.com.cn/s/blog_6ac4c6cb01018pbl.html

转载于:https://blog.51cto.com/ezcloud/1671383

Spring 事务之@Transactional相关推荐

  1. Spring——事务注解@Transactional的源码分析

    本篇结合我的这篇<Spring事务注解@Transactional>,为第二节[2.Spring声明式事务的原理]的详细说明,debug了被@Transactional包裹的目标方法所在类 ...

  2. Spring——事务注解@Transactional【建议收藏】

    在某些业务场景下,如果一个请求中,需要同时写入多张表的数据或者执行多条sql,为了保证操作的原子性(要么同时成功,要么同时失败),避免数据不一致的情况,我们一般都会用到事务:Spring框架下,我们经 ...

  3. Spring 事务管理@transactional 的实现原理和使用

    转载自:http://tech.lede.com/2017/02/06/rd/server/SpringTransactional/ 本文主要讨论Spring声明式事务中使用注解@Transactio ...

  4. spring事务注解@Transactional参数详解

    在Spring中进行事务管理操作有两种方式:编程式事务管理和声明式事务管理.这里介绍的是第二种方式. 1.声明式事务管理(底层使用AOP原理): 1>基于注解方式.(本文章基于注解) 2> ...

  5. Spring 事务注解@Transactional使用注意事项

    缺省情况下,Spring 事务基于Spring AOP技术,此时使用事务注解 @Transactional 需要留意以下问题 : 1. 不要在 protected,private 或者包内可见方法上使 ...

  6. Spring事务注解Transactional失效

    前情提要:当Service接口实现类中存在内部方法调用,并且方法需要支持事务控制时,事务控制失效,事务的传播级别为默认REQUIRED(默认模式). 1.简化版翻车代码: Service接口层 Ser ...

  7. Spring事务注解@Transactional失效和切面失效问题

    人最宝贵的是生命,生命属于人只有一次.人的一生应当这样度过:当他回首往事时,不会因虚度年华而悔恨,也不会因碌碌无为而羞耻.这样,临终前他就可以自豪地说:"我已经把自己整个生命和全部精力都献给 ...

  8. 解决Spring事务注解@Transactional在类内部方法调用不生效的问题

    问题现象: package cn.sw.study.web.service.impl; import cn.sw.study.web.dao.UserMapper; import cn.sw.stud ...

  9. spring 事务-使用@Transactional 注解(事务隔离级别)

    先看下@Transactional可以配制那些参数及以其所代表的意义. isolation 枚举org.springframework.transaction.annotation.Isolation ...

最新文章

  1. NAS设置NFS共享便于KODI添加视频的方式
  2. 全球及中国家用除湿机行业消费需求调研及十四五发展趋势研究报告2022-2027年
  3. POJ 3279(Fliptile)题解
  4. 集成学习(ensemble learning)(三)
  5. jMeter parallel controller 无法使用 CSV Data config 提供的变量?
  6. Weighted Slope One 算法
  7. GitBash添加tree命令
  8. 选择排序--Selection sort
  9. MediaPlayer的错误修复
  10. FreeTextBox使用详解(FTBv3-1-6)
  11. java基础案例7-4升级日记本
  12. MATLAB/Simulink双馈风机调频模型,风电调频模型,基于三机九节点搭建含双馈风机的电力系统模型
  13. 《西游记》《封神榜》各路神仙基本层次图,不要再傻傻分不清楚了
  14. android 360开机启动,手机360设置开机启动项
  15. 动态规划旅游问题:汽车加满油可以跑n千米,中途有若干个加油站,请用动态规划的方式求解中途加油次数最少的方案。
  16. 禅道管理员admin密码登录失败,更改密码
  17. MapGuide HTTP API
  18. Python 获取股票K线数据
  19. Windows 权限维持学习记录
  20. 数字ic设计——UART

热门文章

  1. 【CentOS 7笔记35】,几个特殊符号和一些常用命令#
  2. Python IO编程-组织文件
  3. redis增删改查封装
  4. JCo3 建立连接到SAP(2)- 连接池
  5. 视频数据:深度数据采集(Depth Data)
  6. html转义符 xsl转义符
  7. 移动数据分析服务使用教程
  8. Django error信息邮件通知功能配置部署
  9. 网站开发流程以及HTML5简介(三)
  10. ROCK 聚类算法‏