zoukankan      html  css  js  c++  java
  • (转)spring异常抛出触发事务回滚策略

    背景:在面试时候问到事务方法在调用过程中出现异常,是否会传递的问题,平时接触的比较少,有些懵逼。

    spring异常抛出触发事务回滚策略

    Spring、EJB的声明式事务默认情况下都是在抛出unchecked exception后才会触发事务的回滚 

    测试用业务逻辑方法: 

    /** 
     * 如果在spring事务配置中不为切入点(如这里的切入点可以定义成test*)配置事务在什么情况下回滚(格式:-引起回滚的异常类型) 
     * 则spring默认只会在service方法抛出unchecked exception才会触发回滚 
     */  
    public class TestServiceImpl extends Service implements TestService {  
      
        /** 
         * 测试spring异常触发事务回滚的service方法 
         */  
        public void testAddPerson(String name) throws Exception {  
            TestPerson p = new TestPerson();  
            p.setName(name);  
            this.getHibernateGenericController().save(p);  
              
            /* 
             * 制造RuntimeException 
             * 在spring默认的异常回滚策略下,该异常的抛出会触发事务的回滚,数据不会被插入 
             */  
            throw new RuntimeException("抛出个运行时异常");  
              
            /** 
             * 同样是unchecked exception,spring默认的异常回滚策略下Error的抛出也会触发事务的回滚,数据不会被插入 
             */  
    //      throw new Error();  
              
            /** 
             * 即使是在spring默认的异常触发事务回滚策略(unchecked exception触发回滚)下, 
             * 如果使用try-catch捕获抛出的unchecked异常后没有在catch块中采用页面硬编码的方式使用spring api对事务做显式的回滚,则事务不会回滚,数据被插入 
             * “将异常捕获,并且在catch块中不对事务做显式提交=生吞掉异常” 
             */  
    //      try {  
    //          throw new RuntimeException("这个抛出的运行时异常会被try-catch捕获");  
    //      } catch(Exception e) {  
    //          System.out.println("捕获到异常: " + e.getMessage());  
    //      }  
              
            /** 
             * 因为Exception类是个checked exception,所以这里抛出的异常不会触发事务的回滚,数据被插入 
             */  
    //      throw new Exception("a Exception instance");  
              
            /** 
             * 该BaseException继承自Exception,也为checked exception,抛出它后: 
             * spring默认的回滚策略下,事务未回滚, 数据被插入; 
             * 在TransactionProxyFactoryBean的transactionAttributes中配置 
                        <prop key="test*"> 
                            ... ...,-BaseException 
                        </prop> 
                后,事务回滚,数据未被插入 
             */  
    //      throw new BaseException("一个BaseException");  
        }  
      
    }  

    关于TransactionProxyFactoryBean的transactionAttributes中字符串的值(定义自TransactionAttributeEditor): 
    is a transaction attribute descriptors that parsed via TransactionAttributeEditor 
    见本博客:http://wuaner.iteye.com/admin/blogs/567792 

    单元测试代码: 

    public class TestSpringDefaultRollback extends TestCase {  
      
        private static ApplicationContext context = new ClassPathXmlApplicationContext("resource/xxx/applicationContext.xml");  
        public void testDefaultRollback() throws Exception{  
            TestService testServiceImpl = (TestService)context.getBean("testService");  
            testServiceImpl.testAddPerson("张三");  
        }  
    }  

    将异常捕获,并且在catch块中不对事务做显式提交(或其他应该做的操作如关闭资源等)=生吞掉异常 

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

    try {  
        //bisiness logic code  
    } catch(Exception e) {  
        //handle the exception  
    }  

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

    详解Java中的checked异常和unchecked异常

    详解Java中的checked异常和unchecked异常

    ps:讲解很清楚

    再来看什么是checked异常,什么是unchecked的异常。其实,Java语言规范对这两个定义十分简单,

    将派生于Error或者RuntimeException的异常称为unchecked异常,所有其他的异常成为checked异常。

    如果出现了RuntimeException,就一定是程序员自身的问题。

     

    Throwable包含了错误(Error)和异常(Excetion两类)
    Exception又包含了运行时异常(RuntimeException, 又叫非检查异常)和非运行时异常(又叫检查异常)
    (1) Error是程序无法处理了, 如果OutOfMemoryError、OutOfMemoryError等等, 这些异常发生时, java虚拟机一般会终止线程 .
    (2) 运行时异常都是RuntimeException类及其子类,如 NullPointerException、IndexOutOfBoundsException等, 这些异常是不检查的异常, 是在程序运行的时候可能会发生的, 所以程序可以捕捉, 也可以不捕捉. 这些错误一般是由程序的逻辑错误引起的, 程序应该从逻辑角度去尽量避免.
    (3) 检查异常是运行时异常以外的异常, 也是Exception及其子类, 这些异常从程序的角度来说是必须经过捕捉检查处理的, 否则不能通过编译. 如IOException、SQLException等
  • 相关阅读:
    吴裕雄--天生自然java开发常用类库学习笔记:LinkedList类
    吴裕雄--天生自然java开发常用类库学习笔记:List接口
    吴裕雄--天生自然JAVA SPRING框架开发学习笔记:SSM(Spring+Spring MVC+MyBatis)框架整合搭建详细步骤
    吴裕雄--天生自然JAVA SPRING框架开发学习笔记:测试SSH框架分层整合及验证事务是否有效
    吴裕雄--天生自然JAVA SPRING框架开发学习笔记:SSH框架(Struts2+Spring+Hibernate)搭建整合详细步骤
    吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring声明式事务管理(基于Annotation注解方式实现)
    吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring声明式事务管理(基于XML方式实现)
    吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring事务管理接口PlatformTransactionManager、TransactionDefinition和TransactionStatus
    吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring JDBCTemplate简介
    吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring使用AspectJ开发AOP基于XML和基于Annotation
  • 原文地址:https://www.cnblogs.com/lixuwu/p/10764072.html
Copyright © 2011-2022 走看看