您的位置:首页 > 编程语言 > Java开发

再析spring注解事务之事务传播

2015-08-09 23:35 169 查看
转载自:http://greenyouyou.blog.163.com/blog/static/13838814720118772722131/
在项目开发过程中,事务管理我们一般都交给Spring去管理,他们的一些配置基本知识,大家可以参考我早以前写的一篇博文《Spring与JDBC》,今天的重点是谈谈事务的传播属性。先从看看下面的方法,然后我们开始:

public class ServiceA{
@resource
ServiceB serviceB;
public void myMethodA(){
//相应逻辑
serviceB.myMethodB();
}
}
public class ServiceB{
public void myMethodB(){
//相应逻辑
}
}
有两个方法,在myMethodA中调用了myMethodB,当然这些都是我们的service层的方法。
1. @Transactional(propagation=Propagation.REQUIRED)
这个传播属性是我们在类上加上@Transactional注解后,我们默认使用的传播属性。现在我们给我们的两个方法都加上这个注解(或者说默认不用加),此时开始执行myMethodA方法,此方法发现没有事务,他新建一个事务。当myMethodA调用myMethodB方法的时候,由于myMethodB方法传播属性为REQUIRED,此时他发现当前线程已经开启一个事务,他就使用此事务继续执行。结合传播属性再次理解下:
如果有事务,那么加入事务;如果没有,新建事务。
2. @Transactional(propagation=Propagation. NOT_SUPPORTED)
这个传播属性就是不为此方法开启事务,我们用他用的也比较多,经常在一些查询的方法上加上他,提高效率,同时还加上readonly的配置:
@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
3. @Transactional(propagation=Propagation. REQUIRES_NEW)
现在给myMethodA加上我们的默认注解(REQUIRED),myMethodB加上REQUIRES_NEW传播属性。此时的执行逻辑就变为了:开始执行A方法,A方法发现没有事务,开启事务,当执行到B方法的时候,B方法再次开启事务,A方法开启的事务挂起,只有在B方法的事务提交后他才执行。也就是说在我们的程序中开启了两个事务。如果方法B和方法A的执行成功与否互不干扰。但是我们得注意,如果方法B执行不成功,他会抛出异常,这会影响到A方法的事务提交,如果我们不捕捉B方法抛出的异常,A方法将不会提交。所以最后的一个不太严谨的结论是:
A的事务不会影响B,但是B的事务可能会影响A。
4. @Transactional(propagation=Propagation. NESTED)
现在给myMethodA加上我们的默认注解(REQUIRED),myMethodB加上NESTED传播属性。此时的执行逻辑就变为了:开始执行A方法,A方法发现没有事务,开启事务,当执行到B方法的时候B方法使用A方法的事务。这个时候用上面的函数举例子就不太好了,我用另外的一个方法去举例:
public void myMethodA(){
myMethodC();
myMethodB();
}
首先我们给B方法配置好我们的NESTED属性,其他方法默认。如果B方法执行失败他会回滚,但是C方法不会受他的影响,事务会正常提交。但是如果C方法执行失败,不论B方法执行是否成功,事务都不会提交。(注意B方法在另外一个类中)
5. @Transactional(propagation=Propagation. PROPAGATION_NEVER)
他表示方法不能在事务中运行,同样举例,A方法事务默认,B方法设置为她。那么执行B方法的时候就要报错了,因为B方法运行在A方法中,A方法中有事务在运行。
6. @Transactional(propagation=Propagation. PROPAGATION_MANDATORY)
与上面正好相反,他表示方法必须在一个事务中运行。也就是说他只能被另外的可以开启事务的方法调用。
7. @Transactional(propagation=Propagation. SUPPORTS)
一句话说明下:如果有事务,就在当前事务中运行。如果没有事务,那就在非事务中运行。

看到这里,其实主要的东西你已经理解了。但是你可能忽略了一个小细节,你有没有发现,我的例子里myMethodA和myMethodB肯定不在同一类里,那么在同一个类里不行么?同样是方法调用,为什么不行?先很负责任的给你说,肯定不行,在同一个类里又是另外一个解释了,一会我将简单说下。再回来说为什么不行,因为spring事务管理器是通过AOP来实现的,AOP是针对方法,但是又与类相关的,具体解释我会有新的博文来解释AOP,大家注意留心看。
如果A和B方法都是在同一个类里,比方说 :
public class ServiceA{
public void myMethodA(){
//相应逻辑
myMethodB();
}
}
此时在A方法中调用B方法绕过了springAOP的处理,所以他什么也没做,也就是说加在B方法上的所有注解都没有用上。而如果写在两个类中,spring就会感知到她得调用了,事务也就起作用了,不知道这样解释大家有没有明白,欢迎各位留言交流。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: