一、@Transactional注解 声明式事务
声明式事务对代码没有侵入性,方法内只需要写业务逻辑就可以了,帮助我们节省了很多代码,他会自动帮我们进行事务的开启、提交以及回滚等操作,把程序员从事务管理中解放出来。可以说优点很明显,但是这种方式的缺点也很明
// 默认是RuntimeException就回滚,传播机制为请求事务,REQUIRED
@Transactional(rollbackFor = RollBackException.class,propagation = Propagation.REQUIRED)
public Boolean execute(){
try {
// 代码
} catch (Exception e) {
log.error("xxxxxx",e);
//回滚方式一:手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//回滚方式二:抛异常
// throw new RollBackException("发生异常了肿么办!!!");
}
return true;
}
问题一:声明式事务的粒度问题
声明式事务有一个局限,那就是他的最小粒度要作用在方法上。也就是说,如果想要给一部分代码块增加事务的话,那就需要把这个部分代码块单独独立出来作为一个方法,在大事务耗时过长需要高并发优化的情况下不建议使用声明式事务,建议采用上面提到的编程式事务方式
问题二:声明式事务用不对在某些场景下容易失效
- @Transactional 应用在非 public 修饰的方法上,Transactional将会失效,当用在protected、private 修饰的方法上使用 @Transactional 注解,虽然事务无效,但不会有任何报错,这是我们很容犯错的一点。
- @Transactional 注解属性 propagation 设置错误。
- @Transactional 注解属性 rollbackFor 设置错误。
- 同一个类中方法调用,导致@Transactional失效。
- 异常被你的 catch“吃了”导致@Transactional失效。
总结:@Transactional 注解的看似简单易用,但如果对它的用法一知半解,还是会踩到很多坑的。
二、DataSourceTransactionManager 编程式事务
Spring的事务处理中,通用的事务处理流程是由抽象事务管理器AbstractPlatformTransactionManager来提供的,而具体的底层事务处理实现,由PlatformTransactionManager的具体实现类来实现,如 DataSourceTransactionManager 、JtaTransactionManager和 HibernateTransactionManager等。文章来源:https://www.toymoban.com/news/detail-478319.html
推荐使用编程式事务文章来源地址https://www.toymoban.com/news/detail-478319.html
@Service
public class Test {
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
@Autowired
private IotSensorTypeMapper typeMapper;
@Autowired
private IotGatewayDoMapper doMapper;
public void test11(){
//方式一:使用默认bean对象TransactionDefinition
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
//方式二:自己创建,可以设置事务传播机制,但一般都是使用默认即可PROPAGATION_REQUIRED。
// DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//transactionStatus = dataSourceTransactionManager.getTransaction(def);
// 代码逻辑 ..
try {
IotGatewayDo iotGatewayDo = new IotGatewayDo();
iotGatewayDo.setGatewayId(1L);
iotGatewayDo.setName("cccc");
iotGatewayDo.setStationNumber(1);
doMapper.insertIotGatewayDo(iotGatewayDo);
IotSensorType sensorType = new IotSensorType();
sensorType.setUnit("ww");
sensorType.setName("222");
sensorType.setK(1.0f);
sensorType.setB(0f);
sensorType.setPoint(1);
typeMapper.insertIotSensorType(sensorType);
dataSourceTransactionManager.commit(transactionStatus); // 手动提交
} catch (Exception e) {
System.out.println("异常——————————————————");
dataSourceTransactionManager.rollback(transactionStatus); // 事务回滚
e.printStackTrace();
}
}
}
到了这里,关于Mybatis 使用事务的多种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!