我们经常用到的Spring事务声明方式是:
使用AOP切面声明事务。
使用注解@Transactional声明事务。
这次试验一下另外一种事务实现方式:编程式事务。
以SpringBoot项目为例,使用以下代码声明事务:
@Primary
@Bean(name = "transactionManager")
public DataSourceTransactionManager getDataSourceTransactionManager(@Qualifier("dataSource")DataSource dataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
@Primary
@Bean(name = "transactionTemplate")
public TransactionTemplate getTransactionTemplate(@Qualifier("transactionManager")DataSourceTransactionManager transactionManager) {
TransactionTemplate transactionTemplate = new TransactionTemplate();
transactionTemplate.setTransactionManager(transactionManager);
return transactionTemplate;
}
关于TranscationTemplate的解释:
Template class that simplifies programmatic transaction demarcation and transaction exception handling.
模板类,它简化了编程事务的划分和事务的异常处理。
在需要开启事务时,使用方法如下:
int count = transactionTemplate.execute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus status) {
info.setId(RandomUtil.randomUUID());
int count1 = qyReportInfoMapper.insert(info);
info.setId(RandomUtil.randomUUID());
int count2 = qyReportInfoMapper.insert(info);
return count1 + count2;
}
});
正常情况下,会在对应的表中插入两条记录,如下图:
如果在执行了一条数据插入操作之后,不变更主键,直接造成主键冲突,代码运行异常,就会导致事务回滚,代码如下:
int count = transactionTemplate.execute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus status) {
info.setId(RandomUtil.randomUUID());
int count1 = qyReportInfoMapper.insert(info);
int count2 = qyReportInfoMapper.insert(info);
return count1 + count2;
}
});
抛出异常原因:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'd9206b48-c595-4566-9e1a-c8e211ce2fef' for key 'PRIMARY'
事务回滚,一条数据都没有插入。
如果想在SpringMVC中使用,只需要如下声明即可:
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
这次尝试了编程式事务的实现,其实是因为在阅读Flowable源码时,发现它与Spring整合时,就是基于TranscationTemplate实现的,关键的代码段如下:
public class SpringTransactionInterceptor extends AbstractCommandInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringTransactionInterceptor.class);
protected PlatformTransactionManager transactionManager;
public SpringTransactionInterceptor(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@Override
public <T> T execute(final CommandConfig config, final Command<T> command) {
LOGGER.debug("Running command with propagation {}", config.getTransactionPropagation());
// If the transaction is required (the other two options always need to go through the transactionTemplate),
// the transactionTemplate is not used when the transaction is already active.
// The reason for this is that the transactionTemplate try-catches exceptions and marks it as rollback.
// Which will break nested service calls that go through the same stack of interceptors.
int transactionPropagation = getPropagation(config);
if (transactionPropagation == TransactionTemplate.PROPAGATION_REQUIRED && TransactionSynchronizationManager.isActualTransactionActive()) {
return next.execute(config, command);
} else {
//主要的实现在这里
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setPropagationBehavior(transactionPropagation);
return transactionTemplate.execute(status -> next.execute(config, command));
}
}
private int getPropagation(CommandConfig config) {
switch (config.getTransactionPropagation()) {
case NOT_SUPPORTED:
return TransactionTemplate.PROPAGATION_NOT_SUPPORTED;
case REQUIRED:
return TransactionTemplate.PROPAGATION_REQUIRED;
case REQUIRES_NEW:
return TransactionTemplate.PROPAGATION_REQUIRES_NEW;
default:
throw new FlowableIllegalArgumentException("Unsupported transaction propagation: " + config.getTransactionPropagation());
}
}
}
以上,欢迎指正和探讨。
觉的不错?可以关注我的公众号↑↑↑
文章转载自字痕随行,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。