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; 这个报错的地方,
- 注释掉
int i = 2/0;这一行,saveProject()和saveWithTransactionPrivate()保存都会成功,虽然saveWithTransactionPrivate()方法中*int* i = 3/0这里报错发生了异常,但是异常在save()方法中被捕获了,所以这样看save()方法是没有抛出异常的,所以事务没有回滚,打印出的事务名称是saveWithTransactionPrivatetxName,com.test.service.impl.TransactionServiceImpl.save,因为save()方法抛出异常事务才会回滚 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.saveWithTransaction 而saveProject()方法中打印的为saveProject txName,com.test.service.impl.TransactionServiceImpl.save.所以saveWithTransaction()和save() 方法不是同一个事务,所以save()方法抛出异常不会影响 saveWithTransaction() 方法执行
注意 transactionService.saveWithTransaction(); 这个地方要用通过Spring管理的Bean来调用,如果只是单纯的方法调用,saveWithTransaction() 方法的事务注解不会生效还是会沿用save()方法的事务
本文使用 文章同步助手 同步