前言
@Transactional介绍
transactionManager
isolation
propagation
-
表明事务的传播行为,默认值为
Propagation.REQUIRED
。
-
Propagation.REQUIRED
:若是存在一个事务,则支持当前事务。若是没有事务则开启一个新的事务。好比A方法内部调用了B方法,此时B方法将会使用A方法的事务。
-
Propagation.MANDATORY
:支持当前事务,若是当前没有事务,就抛出异常。
-
Propagation.NEVER
:以非事务方式执行,若是当前存在事务,则抛出异常。
-
Propagation.NOT_SUPPORTED
:以非事务方式执行操做,若是当前存在事务,就把当前事务挂起。
-
Propagation.REQUIRES_NEW
:新建事务,若是当前存在事务,把当前事务挂起。好比A方法使用默认的事务传播属性,B方法使用
REQUIRES_NEW
,此时A方法在内部调用B方法,一旦A方法出现异常,A方法中的事务回滚了,可是B方法并无回滚,由于A和B方法使用的不是同一个事务,B方法新建了一个事务。
-
Propagation.NESTED
:支持当前事务,新增
Savepoint
点,也就是在进入子事务以前,父事务创建一个回滚点,与当前事务同步提交或回滚。 子事务是父事务的一部分,在父事务还未提交时,子事务必定没有提交。嵌套事务一个很是重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所作的动做。而内层事务操做失败并不会引发外层事务的回滚。
timeout
readOnly
rollbackFor 属性
noRollbackFor
@Transactional失效场景
底层数据库引擎不支持事务
在非public修饰的方法使用
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
复制代码
异常被 " 踹死了 "
@Transactional
public void method(){
try{
}catch(Exception ex){
return;
}
}
复制代码
方法中调用同类的方法
public class Test{
public void A(){
B();
}
@Transactional
public void B(){
}
}
复制代码
-
为何会失效呢?:其实缘由很简单,Spring在扫描Bean的时候会自动为标注了
@Transactional
注解的类生成一个代理类(proxy),当有注解的方法被调用的时候,其实是代理类调用的,代理类在调用以前会开启事务,执行事务的操做,可是同类中的方法互相调用,至关于
this.B()
,此时的B方法并不是是代理类调用,而是直接经过原有的Bean直接调用,因此注解会失效。
-
如何解决呢?:这就涉及到注解失效的缘由了,后续文章会介绍到,这里不过多介绍了。
rollbackFor属性设置错误
noRollbackFor属性设置错误
propagation属性设置错误
-
事务的传播属性在上面已经介绍了,默认的事务传播属性是
Propagation.REQUIRED
,可是一旦配置了错误的传播属性,也是会致使事务失效,以下三种配置将会致使事务失效:
原始SSM项目,重复扫描致使事务失效
-
在原始的SSM项目中都配置了
context:component-scan
而且同时扫描了service层,此时事务将会失效。
-
按照Spring配置文件的加载顺序来讲,会先加载Springmvc的配置文件,若是在加载Springmvc配置文件的时候把service也加载了,可是此时事务还没加载,将会致使事务没法成功生效。
-
解决方法很简单,把扫描service层的配置设置在Spring配置文件或者其余配置文件中便可。
总结