1.问题1的提出
class AServiceImpl{
@AutoWide
BService bService;
@Transactional
public void a() {
bService.b();
bService.c();
int i =10/0;
}
}
class BServiceImpl{
@Transactional(propagation = Propagation.REQUIRED,timeout = 2)
public void b() {
}
@Transactional(propagation = Propagation.REQUIRES_NEW,timeout = 2)
public void c() {
}
}
bService.b()方法使用默认的传播行为REQUIRED,和a共用一个事务, int i =10/0;出现异常需要回滚,b会回滚。
bService.c()方法使用默认的传播行为REQUIRES_NEW,和a不共用一个事务, int i =10/0;出现异常需要回滚,b会回滚。
- 结论:bService.b()回滚,bService.c()不回滚。
2.问题2的题提出
class AServiceImpl{
@Transactional
@Transactional
public void a() {
b();
c();
}
@Transactional(propagation = Propagation.REQUIRED,timeout = 2)
public void b() {
System.out.println("b");
}
@Transactional(propagation = Propagation.REQUIRES_NEW,timeout = 2)
public void c() {
System.out.println("c");
}
}
的写法和下面的写法一模一样:
class AServiceImpl{
@Transactional
public void a() {
System.out.println("b");
System.out.println("c");
}
}
即b和c自己的事务失效,完全相当于拷贝代码到a方法中。如果我们想要的是各自拥有自己的自治的事务,该怎么办呢?为什么会出现这个问题?
2.1为什么为出现bc方法事务失效的问题?
原因:@Transactional 底层使用的是aop,使用的代理对象才能使用事务,本方法内部嗲用,绕过了代理对象,所以bc事务无效,a仍然有效(如果其类通过代理对象调用的话)。
2.2解决方案
1.先引入aspactj的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
在嗲用b,c方法之前通过切面重新获得此对象的代理AServiceImpl aService = AopContext.currentProxy();
可以解决这个问题。
代码如下:
class AServiceImpl{
@Transactional
public void a() {
AServiceImpl aService = AopContext.currentProxy();
aService.b();
aService.c();
}
@Transactional(propagation = Propagation.REQUIRED,timeout = 2)
public void b() {
System.out.println("b");
}
@Transactional(propagation = Propagation.REQUIRES_NEW,timeout = 2)
public void c() {
System.out.println("c");
}
}
2.3其他的解决方案
另外在抽象出一层,做事务层,不要把相互调用的方法放到一类中
2.4错误的解决方案
这种会造成循环依赖,会爆炸:
@AutoWide
AServiceImpl AServiceImpl;