例如:事务中 有A,B,C,D等几个方法。 B 中的方法是往数据库中插入数据。
现在问题是 在 D方法中 产生了异常,导致B插入的数据也没了,
有没有方法,在D 异常的时候 A和C能回滚 但是B不回滚
Spring有以下几种事务传播行为可配置:
PROPAGATION_REQUIRED
支持当前事务,如果当前没有事务,就新建一个事务。
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY
支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起,新建一个事务。
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
我的配置如下:
@transactional(propagation=propagation.required)
public void service(){
A();
B();
C();
D();
}
@transactional(propagation=propagation.required)
void A(){
}
@transactional(propagation=propagation.requires_new)
void B(){
}
@transactional(propagation=propagation.required)
void C(){
}
@transactional(propagation=propagation.required)
void D(){
}
虽然事务的传播特性说道 PROPAGATION_REQUIRES_NEW 会新建一个事务,使嵌套的内部事务与外部事务保证无关性。
如果真如上面所说的话,上面的代码,是可以运行的,不管A、B、C、D谁有异常,都会使外层service进行回滚,但是B为新建事务,所以B不会随着外层事务回滚而回滚。
但是实际运行,B也随之进行回滚了,这就说明,PROPAGATION_REQUIRES_NEW 并没有新建一个事务,为什么呢?
我也没咋明白,不过找了些资料解释说,如果要使用PROPAGATION_REQUIRES_NEW必需保证,外部事务,与嵌套事务中的新建事务,必需位于两个service中。
详细请参考:http://blog.youkuaiyun.com/wangjunjun2008/article/details/53669951
所以我又 新建了一个,service 接口,命名为 NewService接口 ,实现类里面写入了 事务需要使用PROPAGATION_REQUIRES_NEW的B方法,并设置B方法事务为PROPAGATION_REQUIRES_NEW,将NewService注入到,service中。代码如下;
@autowrite
private NewService newService;
@transactional(propagation=propagation.required)
public void service(){
A();
newService.B();
C();
D();
}
@transactional(propagation=propagation.required)
void A(){
}
@transactional(propagation=propagation.required)
void C(){
}
@transactional(propagation=propagation.required)
void D(){
}
这样当C、D方法出现异常时,B方法不会进行回滚,但是还会出现一个问题,就是当 A() 方法 出现异常,B方法依然会回滚。
这就说明,只要有异常抛出,就不会执行后面的方法,直接返回外部事务,进行回滚,所以B方法,还没来得及新建事务,整个事务就进行回滚了。
解决办法: 值需要将B方法提前就好了。