Spring注解事务

126 阅读2分钟

Spring注解事务

String txName = TransactionSynchronizationManager.getCurrentTransactionName();获取当前事务名

事务需要注意方法是哪个事务在管理,哪个方法抛出异常对应的事务才会回滚,可以通过打印出事务名称来排查事务不生效的场景
例如下面的事务的save方法的事务管理

@Slf4j
@Service
public class TransactionServiceImpl implements TransactionService {

    @Autowired
    private BasecodeRepository basecodeRepository;

    @Autowired
    private ProjectService projectService;

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void save() {
        TransactionService transactionService = SpringBeanContextHolder.getBean(TransactionService.class);
        saveProject();
        try {
            saveWithTransactionPrivate();
        } catch (Exception e){
            log.info("save error",e);
        }
        // 注意这一行
        int i =  2/0;
    }
    
    private void saveProject(){
        Project project = Project.builder().projectName("testProject").content("test").build();
        projectService.save(project);
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();

        log.info("saveProject txName,{}",txName);
    }
    
    private void saveWithTransactionPrivate() {
        log.info("saveWithTransactionPrivate");
        Basecode basecode = Basecode.builder().name("saveTransaction").code("11").build();
        basecodeRepository.save(basecode);
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();

        log.info("saveWithTransactionPrivate txName,{}",txName);
        // 这里会抛出异常
        int i = 3/0;
    }

注意上面 save() 方法 int i = 2/0; 这个报错的地方,

  1. 注释掉int i = 2/0; 这一行,saveProject()saveWithTransactionPrivate() 保存都会成功,虽然saveWithTransactionPrivate() 方法中*int* i = 3/0这里报错发生了异常,但是异常在save() 方法中被捕获了,所以这样看 save() 方法是没有抛出异常的,所以事务没有回滚,打印出的事务名称是saveWithTransactionPrivatetxName,com.test.service.impl.TransactionServiceImpl.save,因为save() 方法抛出异常事务才会回滚
  2. save() 方法中加上int i = 2/0; ,save() 方法执行就会报错,抛出了异常事务就会回滚,所以saveProject()saveWithTransactionPrivate() 这两个方法都会回滚,保存都不会成功

如果想要save() 方法中内部的方法和save()方法里面抛出的异常不相互影响,可以使用 propagation = Propagation.REQUIRES_NEW 来实现,Propagation.REQUIRES_NEW 会开启一个新事务.
例如下面的saveWithTransaction()会开启一个新事务

@Slf4j
@Service
public class TransactionServiceImpl implements TransactionService {

    @Autowired
    private BasecodeRepository basecodeRepository;

    @Autowired
    private ProjectService projectService;

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void save() {
        TransactionService transactionService = SpringBeanContextHolder.getBean(TransactionService.class);
        saveProject();
        try {
            transactionService.saveWithTransaction();
        } catch (Exception e){
            log.info("save error",e);
        }
        int i =  2/0;
    }

    private void saveProject(){
        Project project = Project.builder().projectName("testProject").content("test").build();
        projectService.save(project);
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();

        log.info("saveProject txName,{}",txName);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveWithTransaction() {
        log.info("saveWithTransaction");
        Basecode basecode = Basecode.builder().name("saveTransaction").code("11").build();
        basecodeRepository.save(basecode);
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();

        log.info("saveWithTransaction txName,{}",txName);
    }
}

上面saveWithTransaction()代码打印出的事务名称为saveWithTransaction txName,com.test.service.impl.TransactionServiceImpl.saveWithTransactionsaveProject()方法中打印的为saveProject txName,com.test.service.impl.TransactionServiceImpl.save.所以saveWithTransaction()save() 方法不是同一个事务,所以save()方法抛出异常不会影响 saveWithTransaction() 方法执行

注意 transactionService.saveWithTransaction(); 这个地方要用通过Spring管理的Bean来调用,如果只是单纯的方法调用,saveWithTransaction() 方法的事务注解不会生效还是会沿用save()方法的事务

本文使用 文章同步助手 同步