1.问题原因
spring采用动态代理机制来实现事务控制,而动态代理最终都是要调用原始对象的,而原始对象在去调用方法时,是不会再触发代理了!可以理解为同一个类中非事务方法调用方法时用的是当前对象去调用,而不是spring生成的代理对象,所以会导致事务失效。
另外常见的事务失效的场景如下:
1. 非 public 权限方法会导致事务失效
2. final 或者 static 修饰的方法
3. 未被 spring 管理的类
4. 多线程调用
5. 数据库引擎不支持事务。
6. 事务没有开启
7. 事务的传播特性
8. 自己将异常 catch 掉了
9. 默认情况下只会回滚RuntimeException(运行时异常)和Error(错误),对于普通的非运行时异常,它不会回滚。
2. 问题解决
1. 将需要进行事务管理的方法单独写到一个Service文件中
@Servcie
public class ServiceA
{
@Autowired
private ServiceB serviceB;
public void save(User user)
{
queryData1();
queryData2();//调用事务方法serviceB.doSave(user);
}
}-------------------------分界线----------------------------------------//新加的 @Servcie
@Servcie
public class ServiceB
{
//事务方法@Transactional(rollbackFor=Exception.class)public void doSave(User user)
{
addData1();
updateData2();
}
}
2. 在该Service类中注入自己,使用注入的自己进行调用事务方法
@Servcie
public class ServiceA
{
//注入自己
@Autowiredprivate ServiceA serviceA;
public void save(User user)
{
queryData1();
queryData2();//this.doSave(user);//使用注入的自己 调用事务方法
serviceA.doSave(user);
}
@Transactional(rollbackFor=Exception.class)
public void doSave(User user)
{
addData1();
updateData2();
}
}
3. 使用 AopContext.currentProxy() 获取代理对象
(1)增加maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
(2)springboot启动类加上注解:@EnableAspectJAutoProxy(exposeProxy = true)
(3)Service类中,获取代理对象后,再去调用事务方法
CommServiceImpl currentProxy = (CommServiceImpl) AopContext.currentProxy()