关闭

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

标签: springexceptionserviceclassejbapi
1258人阅读 评论(0) 收藏 举报
分类:
[转自:http://cn.dydou.cn/ws/201108/0QQI132011.html]
spring异常抛出触发事务回滚策略导读:Spring、EJB的声明式事务 默认 情况下都是在 抛出unchecked exception 后才会触发事务的回滚 测试用业务逻辑方法: Java代码 /** *如果在spring事务配置中不为切入点(如这里的切入点可以定义......

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

测试用业务逻辑方法: 

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.}  
/**
 * 如果在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 


单元测试代码:



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.}  
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中如果某个业务方法被一个 

Java代码  
1.try {  
2.    //bisiness logic code  
3.} catch(Exception e) {  
4.    //handle the exception  
5.}  
try {
	//bisiness logic code
} catch(Exception e) {
	//handle the exception
}
整个包裹起来,则这个业务方法也就等于脱离了spring事务的管理,因为没有任何异常会从业务方法中抛出!全被捕获并吞掉,导致spring异常抛出触发事务回滚策略失效。 
不过,如果在catch代码块中采用页面硬编码的方式使用spring api对事务做显式的回滚,这样写也未尝不可。 


 

spring trigger transaction rollback exception thrown Strategy
 

Spring, EJB's declarative transaction by default, throw an unchecked exception are only triggered after the transaction rollback 

Test business logic methods: 

/**
 *  If you do not spring transaction configuration as a starting point, such as the starting point of the test can be defined as  * ) Configuration transaction is rolled back (in the format:  - The type of exception caused the rollback)  
 *  The spring default only service method throws an unchecked exception triggered rollback  
 */
public class TestServiceImpl extends Service implements TestService {

        /**
         *  Test spring exception triggered the transaction to roll back the service method  
         */
        public void testAddPerson(String name) throws Exception {
                TestPerson p = new TestPerson();
                p.setName(name);
                this.getHibernateGenericController().save(p);
                
                /*
                 *  Manufacture of RuntimeException  
                 *  In spring the default exception rollback strategy, the exception thrown to trigger a transaction rollback  , Data will not be inserted  
                 */
                throw new RuntimeException(" Throw a runtime exception  ");
                
                /**
                 *  The same is unchecked exception, spring default exception rollback strategy under the thrown Error can also trigger a rollback of the transaction, the data will not be inserted  
                 */
//              throw new Error();
                
                /**
                 *  Even in spring default exception triggered transaction rollback strategy (unchecked exception triggered rollback),  
                 *  If you use try  -catch Capture of unchecked exception thrown when no in the catch block in the page hard-coded to use spring API do explicit rollback transaction, the transaction will not be rolled back, the data is inserted  
                 *  The exception to a capture  , And in a catch block to do an explicit commit transaction  = Eat out exception "  
                 */
//              try {
//                      throw new RuntimeException(" This throws a runtime exception is try  -catch Capture  ");
//              } catch(Exception e) {
//                      System.out.println(" Caught exception:  " + e.getMessage());
//              }
                
                /**
                 *  Because the exception class is a checked exception, so it throws an exception of does not trigger a rollback of the transaction, the data is inserted  
                 */
//              throw new Exception("a Exception instance");
                
                /**
                 *  The BaseException inherited from Exception, as well as checked exception thrown when it  :
                 * spring The default rollback strategy, the transaction is not rolled back, the data was inserted;  
                 *  In the configure TransactionProxyFactoryBean transactionAttributes  
                                        <prop key="test*">
                                                ... ...,-BaseException
                                        </prop>
                         After the transaction is rolled back, the data has not been inserted  
                 */
//              throw new BaseException(" A BaseException  ");
        }

}



Unit test code:



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(" Smith, John  ");
        }
}


Catch the exception and the catch block in the transaction do not explicitly presented (or the other should do the operation, such as closure of resources, etc.) = Health swallow an exception 


spring of the transaction boundaries are started before the business method is called, the business method implementation of the completion of the subsequent implementation of the commit or rollback (Spring default depends on whether the runtime throws an exception).



If you throw runtime exception in the way your business does not catch that, then the transaction will be rolled back.



In general do not need to catch an exception in business method, If I have to catch, in the work you want done (such as closing documents, etc.) must throw runtime exception, otherwise the spring will put your operation commit, that would create dirty data. So you catch code is superfluous.


From this we can deduce that if a business in the spring in the method is a 

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

The whole package together, then this business method is the same as out of spring management of its affairs, since no exceptions will be thrown from a business method! Were all captured and eaten, leading to an exception thrown spring trigger transaction rollback strategy for failure. 
However, if the catch block the use of hard-coded pages use spring api to do the transaction explicit rollback, so that was also something that can not be. 

本篇文章来源于 中文DY豆-cn.dydou.cn 原文链接:http://cn.dydou.cn/ws/201108/0QQI132011.html

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:606631次
    • 积分:9355
    • 等级:
    • 排名:第1935名
    • 原创:319篇
    • 转载:210篇
    • 译文:0篇
    • 评论:12条
    最新评论