Spring事务嵌套问题记录
问题描述
今天遇到一个spring事务嵌套的问题:
**Transaction rolled back because it has been marked as rollback-only**
问题复现
在ConsumerService.c()
中调用 ProducerService.p()
在ProducerService.p()
中抛出一个运行时异常
在ConsumerService.c()
catchp()
的异常
代码如下:
public class ProducerServiceImpl implements ProducerService{
@Autoware
private UserService userService;
@Transactional
@Override
public void p() {
//保存
userService.save(new User());
//模拟异常
throw new RuntimeException("eee");
}
}
public class ConsumerServiceImpl implements ConsumerService{
@Autoware
private UserService userService;
@Autoware
private ProducerService producerService;
@Transactional
@Override
public void c() {
//保存
userService.save(new User());
//调用p() 并catch
try{
producerService.p();
}catch(Exception e){
}
}
}
运行代码报错:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
问题解决
- 将
ProducerService.p()
方法的@Transactional
删除(没有其他方法调用c()
) - 在
ProducerService.p()
方法上加@Transactional(propagation = Propagation.REQUIRES_NEW)
开启新事务 - 如果不想改动
@Transactional
并且想不报错,代码改动如下
public class ConsumerServiceImpl implements ConsumerService{ @Autoware private UserService userService; @Autoware private ProducerService producerService; @Transactional @Override public void c() { //保存 userService.save(new User()); //调用p() 并catch try{ producerService.p(); }catch(Exception e){ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } } }
- 如果不想改动
@Transactional
并且 想让producerService.p();
不影响consumerService.c()
方法,代码改动如下 (此时c()
方法的代码将不会回滚!)
public class ConsumerServiceImpl implements ConsumerService{ @Autoware private UserService userService; @Autoware private ProducerService producerService; @Transactional @Override public void c() { try{ //保存 userService.save(new User()); //调用p() 并catch try{ producerService.p(); }catch(Exception e){ } }catch(Exception e){ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } } }
源码分析
todo