文章目录
前言
本文主要介绍编程式事务和声明式事务的使用,然后进行总结分析
一、编程式事务
1、概念
编程式事务是通过编写代码来显式地控制事务的开始、提交和回滚。在编程式事务中,开发人员需要手动编写事务管理的代码,包括事务的开始、提交和回滚操作。这通常涉及到使用事务管理器、事务的开始和结束标记、异常处理等。编程式事务提供了更细粒度的控制,但也需要更多的代码和维护工作。
2、实现
主要基于TransactionDefinition和PlatformTransactionManager核心接口,进行拓展使用,比较好的拓展有TransactionTemplate模板类,我们可以根据自己的需要来进行编程,需要我们在代码中手动开启事务、手动提交or回滚
1、PlatformTransactionManager
需要我们手写开启事务、提交以及回滚
@Autowired
private TransactionDefinition transactionDefinition;
@Autowired
private PlatformTransactionManager platformTransactionManager;
public void forlanTest() {
TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
try {
//TODO 业务逻辑、SQL操作
platformTransactionManager.commit(transaction);
} catch (Throwable e) {
e.printStackTrace();
platformTransactionManager.rollback(transaction);
}
}
2、TransactionTemplate
内部已经帮我们封装了开启事务、提交事务,只需要对异常的情况进行捕获处理,进行回滚,还能根据自己的需要,知道成功还是失败
@Autowired
private TransactionTemplate transactionTemplate;
public void forlanTest() {
Boolean result = transactionTemplate.execute((transactionStatus) -> {
try {
//TODO 业务逻辑、SQL操作
return Boolean.TRUE;
} catch (Throwable e) {
e.printStackTrace();
transactionStatus.setRollbackOnly();
return Boolean.FALSE;
}
});
}
3、拓展
我们可以设置事务隔离级别、传播行为等
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
public interface TransactionDefinition {
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
int TIMEOUT_DEFAULT = -1;
}
二、声明式事务
1、概念
声明式事务是通过使用注解或配置来定义事务的行为,而不需要显式地编写事务管理的代码。在声明式事务中,开发人员只需要在方法或类级别上添加事务相关的注解或配置,框架会自动处理事务的开始、提交和回滚。声明式事务提供了更简洁和易于维护的方式来管理事务,开发人员可以将更多的精力放在业务逻辑上,而不是事务管理的细节上。
2、实现
直接在对应的方法上加上注解@Transactional进行增强即可
@Transactional
public void forlanTest() {
//TODO 业务逻辑、SQL操作
}
三、总结
1、编程式事务
- 优点:自己可以灵活控制,什么时候开启事务,什么时候提交、回滚
- 缺点:对代码有侵入性
2、声明式事务
通过AOP实现,本质就是在我们执行的目标方法前后帮我们做了开启事务,然后提交or回滚事务
- 优点:对代码无侵入性
- 缺点:
- 局限性,最小粒度只能作用在方法上
写一段代码,如果需要加事务的话,需要抽离出来声明为一个方法 - 很容易被程序员忽略,出现问题
比如:引入一些耗时操作,导致长事务;切面冲突问题,导致异常没有被事务切面捕获到; - 需要注意事务的场景
可以看下文章Spring事务失效原因分析解决
- 局限性,最小粒度只能作用在方法上
总的来说,编程式事务提供了更细粒度的控制和灵活性,适用于复杂的事务场景。而声明式事务则更加简洁和易于使用,适用于大多数常见的事务需求。选择使用哪种事务管理方式取决于具体的应用需求和开发团队的偏好,在实际工作中,我们大多使用的是声明式事务,官方也推荐使用它,简单省事,但是要注意避坑,具体可以关注这篇博客,正确使用就问题不大,不然还是建议使用编程式事务,实实在在,可控,什么时候开启事务,什么时候提交,什么时候回滚,清清楚楚。