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

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

测试用业务逻辑方法: 

 


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

Java代码  收藏代码
  1. /** 
  2.  * 如果在spring事务配置中不为切入点(如这里的切入点可以定义成test*)配置事务在什么情况下回滚(格式:-引起回滚的异常类型) 
  3.  * 则spring默认只会在service方法抛出unchecked exception才会触发回滚 
  4.  */  
  5. public class TestServiceImpl extends Service implements TestService {  
  6.   
  7.     /** 
  8.      * 测试spring异常触发事务回滚的service方法 
  9.      */  
  10.     public void testAddPerson(String name) throws Exception {  
  11.         TestPerson p = new TestPerson();  
  12.         p.setName(name);  
  13.         this.getHibernateGenericController().save(p);  
  14.           
  15.         /* 
  16.          * 制造RuntimeException 
  17.          * 在spring默认的异常回滚策略下,该异常的抛出会触发事务的回滚,数据不会被插入 
  18.          */  
  19.         throw new RuntimeException("抛出个运行时异常");  
  20.           
  21.         /** 
  22.          * 同样是unchecked exception,spring默认的异常回滚策略下Error的抛出也会触发事务的回滚,数据不会被插入 
  23.          */  
  24. //      throw new Error();  
  25.           
  26.         /** 
  27.          * 即使是在spring默认的异常触发事务回滚策略(unchecked exception触发回滚)下, 
  28.          * 如果使用try-catch捕获抛出的unchecked异常后没有在catch块中采用页面硬编码的方式使用spring api对事务做显式的回滚,则事务不会回滚,数据被插入 
  29.          * “将异常捕获,并且在catch块中不对事务做显式提交=生吞掉异常” 
  30.          */  
  31. //      try {  
  32. //          throw new RuntimeException("这个抛出的运行时异常会被try-catch捕获");  
  33. //      } catch(Exception e) {  
  34. //          System.out.println("捕获到异常: " + e.getMessage());  
  35. //      }  
  36.           
  37.         /** 
  38.          * 因为Exception类是个checked exception,所以这里抛出的异常不会触发事务的回滚,数据被插入 
  39.          */  
  40. //      throw new Exception("a Exception instance");  
  41.           
  42.         /** 
  43.          * 该BaseException继承自Exception,也为checked exception,抛出它后: 
  44.          * spring默认的回滚策略下,事务未回滚, 数据被插入; 
  45.          * 在TransactionProxyFactoryBean的transactionAttributes中配置 
  46.                     <prop key="test*"> 
  47.                         ... ...,-BaseException 
  48.                     </prop> 
  49.             后,事务回滚,数据未被插入 
  50.          */  
  51. //      throw new BaseException("一个BaseException");  
  52.     }  
  53.   
  54. }  


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

单元测试代码: 

Java代码  收藏代码
  1. public class TestSpringDefaultRollback extends TestCase {  
  2.   
  3.     private static ApplicationContext context = new ClassPathXmlApplicationContext("resource/xxx/applicationContext.xml");  
  4.     public void testDefaultRollback() throws Exception{  
  5.         TestService testServiceImpl = (TestService)context.getBean("testService");  
  6.         testServiceImpl.testAddPerson("张三");  
  7.     }  
  8. }  

 




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

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



 

展开阅读全文

没有更多推荐了,返回首页