最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......  
  为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志。但是这边情况来了,当这个方法异常时候 日志是打印了,但是加的事务却没有回滚。

例:  
   类似这样的方法不会回滚 (一个方法出错,另一个方法不会回滚) :

  1. if(userSave){
  2. try {
  3. userDao.save(user);
  4. userCapabilityQuotaDao.save(capabilityQuota);
  5. } catch (Exception e) {
  6. logger.info("能力开通接口,开户异常,异常信息:"+e);
  7. }
  8. }

下面的方法回滚(一个方法出错,另一个方法会回滚):

  1. if(userSave){
  2. try {
  3. userDao.save(user);
  4. userCapabilityQuotaDao.save(capabilityQuota);
  5. } catch (Exception e) {
  6. logger.info("能力开通接口,开户异常,异常信息:"+e);
  7. throw new RuntimeException();
  8. }
  9. }

或者:

  1. if(userSave){
  2. try {
  3. userDao.save(user);
  4. userCapabilityQuotaDao.save(capabilityQuota);
  5. } catch (Exception e) {
  6. logger.info("能力开通接口,开户异常,异常信息:"+e);
  7. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  8. }
  9. }

为什么不会滚呢??是对Spring的事务机制就不明白。!! 
   默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚。  
   spring aop  异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过  
    
配置来捕获特定的异常并回滚  
  换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚
  解决方案: 
  方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在service上层(webservice客户端,view层action)要继续捕获这个异常并处理
  方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常(现在项目的做法)

参考博客  Spring事务管理只对出现运行期异常进行回滚   http://blog.csdn.net/abc19900828/article/details/39497631

spring事物传播机制和隔离级别    http://blog.csdn.net/hijiankang/article/details/9174461

spring事务处理详解    http://blog.csdn.net/u013628152/article/details/47980811

1:Java包含两种异常:checked异常和unchecked异常。

checked和unchecked异常之间的区别是: 
Checked异常必须被显式地捕获try-catch-finally,而unchecked异常则可以不必捕获或抛出。 
Checked异常继承java.lang.Exception类。Unchecked异常继承自java.lang.RuntimeException类。

2:Mysql 存储引擎中InnoDB与Myisam的主要区别

事务处理方面:innodb 支持事务功能,myisam 不支持。 
Myisam 的执行速度更快,性能更好。

engine = innodb 和 engine = myisam 
可使用下述语句之一检查表的表类型: 
SHOW TABLE STATUS LIKE ‘tbl_name’; 
SHOW CREATE TABLE tbl_name;

使用下述语句,可检查mysqld服务器支持的存储引擎: 
SHOW ENGINES;

3:spring事务处理

throw new RuntimeException(“xxxxxxxxxxxx”); 默认事务回滚 
throw new Exception(“xxxxxxxxxxxx”); 默认事务不回滚 
Spring的AOP即声明式事务管理默认是针对unchecked exception回滚。也就是默认对RuntimeException()异常或是其子类进行事务回滚; 
checked异常,throw new Exception默认不会回滚

若想让checked异常或者自定义异常回滚 
(1)配置文件方式

  1. <tx:advice id="txAdvice">
  2. <tx:attributes>
  3. <tx:method name="update*" no-rollback-for="IOException"/>
  4. <tx:method name="*"/>
  5. </tx:attributes>
  6. </tx:advice>
  7. <tx:advice id="txAdvice" transaction-manager="transactionManager">
  8.   <tx:attributes>
  9.     <tx:method name="*" rollback-for="com.cn.untils.exception.MyException"/>
  10.   </tx:attributes>
  11. </tx:advice>

(2)注解方式

  1. @Transactional(rollbackFor = Exception.class)
  2. @Transactional(rollbackFor = MyException.class)

不起作用:

  1. @Transactional
  2. public void addAdmin(Admin admin) throws Exception {
  3. try {
  4. this.adminDao.add(admin);
  5. admin.setUsername("123456789012345");
  6. this.adminDao.update(admin);
  7. } catch (Exception e) {
  8. e.printStackTrace();
  9. throw new Exception("测试!");
  10. }
  11. }

起作用

  1. @Transactional(rollbackFor = Exception.class)
  2. public void addAdmin(Admin admin) throws Exception {
  3. try {
  4. this.adminDao.add(admin);
  5. admin.setUsername("123456789012345");
  6. this.adminDao.update(admin);
  7. } catch (Exception e) {
  8. e.printStackTrace();
  9. throw new Exception("测试!");
  10. }
  11. }

起作用

  1. @Transactional
  2. public void addAdmin(Admin admin) {
  3. try {
  4. this.adminDao.add(admin);
  5. admin.setUsername("123456789012345");
  6. this.adminDao.update(admin);
  7. } catch (Exception e) {
  8. e.printStackTrace();
  9. throw new RuntimeException("测试!");
  10. }
  11. }

完整写法:

  1. @Transactional(rollbackFor = RuntimeException.class)
  2. public void addAdmin(Admin admin) {
  3. try {
  4. this.adminDao.add(admin);
  5. admin.setUsername("123456789012345");
  6. this.adminDao.update(admin);
  7. } catch (Exception e) {
  8. e.printStackTrace();
  9. throw new RuntimeException("测试!");
  10. }

Spring事务异常回滚,捕获异常不抛出就不会回滚(转载) 解决了我一年前的问题的更多相关文章

  1. Spring事务异常回滚,捕获异常不抛出就不会回滚

    最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......    为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常 ...

  2. 【转】Spring事务异常回滚,捕获异常不抛出就不会回滚

    最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......     为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异 ...

  3. spring事物回滚机制 (事务异常回滚,捕获异常不抛出就不会回滚)

    当异常被捕获catch的时候,spring的事物则不会回滚 为什么不会滚呢??  spring aop  异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常 ...

  4. Spring事务异常回滚

    最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......    为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常 ...

  5. 异常如果一直被throws抛出的话就会被jvm异常处理器处理了

    异常如果一直被throws抛出的话就会被jvm异常处理器处理了,这时jvm会跳出正常运行状态. 异常如果一直被throws抛出的话就会被jvm异常处理器处理了,这时jvm会跳出正常运行状态. 异常如果 ...

  6. spring事务 异常回滚

    spring事务回滚 可抛出自定义继承自RuntimeException

  7. Spring事务异常rollback-only

    转自:https://blog.csdn.net/sgls652709/article/details/49472719 前言 在利用单元测试验证spring事务传播机制的时候出现了下面的异常: Tr ...

  8. Spring事务异常rollback-only 笔记

    造成以上异常的原因情形: 在spring里面我们配置了事务的传播机制是REQUIRED,所以这两个事务最终会合并成一个事务.当a方法调用b方法时,程序中a方法中由于某某原因导致抛出异常(或者明确将该事 ...

  9. hibernate整合spring事务异常

    Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushM ...

随机推荐

  1. checkbook全选/反选/全不选

    <!doctype html><html lang="en"><head> <meta charset="UTF-8" ...

  2. 热烈祝贺Polymer中文组织站点上线

    欢迎来到前端世界的明天 由于官网被墙, 所以 http://docs.polymerchina.org/ 其实是一件很有意义的事. 组件化和重用,一直是编程界几十年来前进的方向和目标,随着时间的推移和 ...

  3. 编写javascript的基本技巧

    第一.编写可维护的代码 什么叫着编写可维护的代码呢?就是当我的做出来的项目,拿给其它编码团队能很快的看懂 你编写的代码,你的整个项目的逻辑等等.一个项目的修改维护是要比开发一个项目的成本 是要高的.例 ...

  4. Apple Swift学习资料汇总

    今年的苹果开发者大会(WWDC)上,公布了ios8的几个新特性,其中包括引入了群聊功能,支持第三方输入法等功能.但更让开发者感兴趣的莫过于Swift语言的发布了. Swift是apple自创的一门转为 ...

  5. codeblocks 使用指南z

    1.界面风格更改 首先贴怎么普通设置出来,或者改配置文件 这是我的风格 类似于DEV-CPP里面的一个主题,看的很舒服 具体设置如下: Settings-Editor 1.代码当前行高亮 在Gener ...

  6. jmx使用应该注意的基本规范

    1.标准MBean 名称必需是在要监控的类名后面加上“MBean ”. 2.监控的类和MBean 接口必需在同一包下,也可以理解为注册的接口名字必须以MBean结尾,接口实现类比接口名字少了MBean ...

  7. 玩转Android---事件监听篇---第2篇

    事件监听篇---第二篇 下面是各种常用控件的事件监听的使用 ①EditText(编辑框)的事件监听---OnKeyListener ②RadioGroup.RadioButton(单选按钮)的事件监听 ...

  8. Android onSaveInstanceState()

    我们知道,由于手机的内存问题,很容易造成切换activity之后上一个activity被回收的情况,虽然我们按下back按键的时候,还是能够回到上一个activity,但是此时我们并不是执行的onRe ...

  9. 用document.title=“xxx”动态修改title,在ios的微信下面不生效的解决办法!

    //需要jQuery var $body = $('body'); document.title = 'title'; // hack在微信等webview中无法修改document.title的情况 ...

  10. js数组(二)

    一.位置方法 indexOf()和laseIndexOf() indexOf是从数组的第0项开始向后查找,没有找到返回-1,要求使用=== var numbers = [1,2,3,4,5,4,3,2 ...