SpringBoot中开启事务

2023年 10月 3日 40.5k 0

什么是事务

在编程中,事务(Transaction)是指一个包含了一组操作或步骤的程序单元,这些操作或步骤被封装在一起作为一个单独的执行单元来执行。更简单的说就是,一个有若干操作的集合。执行后,它们要么一起成功,要么一起失败。

事务的特性

事务有四大特性(ACID),原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)四个属性,这些属性被称为ACID属性。

  • 原子性:事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。
  • 隔离性:事务的执行不会影响其他事务的执行。
  • 持久性:一旦事务提交,其修改的效果就是永久性的。
  • 一致性:事务的执行不能破坏数据库数据的完整性和一致性(必须使数据库从一个一致性状态变换到另一个一致性状态)。

Spring中的事务

在简单的了解事务后,接下来看看在Spring中如何实现事务。

Spring 支持两种类型的事务:声明式事务和编程式事务。

编程式事务

它一种通过编程方式控制事务边界的方法,它提供了更加灵活的事务控制方式,允许开发人员根据业务需求自定义事务的边界——由开发人员手动控制事务的开启、提交和回滚,以实现对事务的精细控制。

Spring提供了PlatformTransactionManager接口TransactionTemplate类来实现编程式事务管理。

开发人员可以通过注入TransactionTemplate实例,并使用该实例的execute方法来执行包含事务操作的业务逻辑。

  • 以下是通过TransactionTemplate类来实现事务管理的方法
 @Autowired
 private TransactionTemplate transactionTemplate;
 ​
 public void updateUser(User user) {
     try {
         transactionTemplate.execute(status -> {
             // 在事务中执行业务逻辑
             // ...
             return null;
         });
     } catch (Exception e) {
         // 发生异常时回滚事务
         transactionTemplate.rollback(status -> {
             // 回滚事务
             return null;
         });
     }
 }

PlatformTransactionManager接口定义了3个基本的事务操作方法,具体的实现都是由不同的子类来实现的。它有众多实现,但是我们并不需要掌握这些具体实现类的用法,我们只需要掌握好 PlatformTransactionManager 的用法即可。例如:如果你使用的是 JDBC 那么可以将 DataSourceTransactionManager 作为事务管理器。

 public interface PlatformTransactionManager extends TransactionManager {
   TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
   void commit(TransactionStatus status) throws TransactionException;
   void rollback(TransactionStatus status) throws TransactionException;
 }
 // 源码
  • 以下是使用PlatformTransactionManager的实现类DataSourceTransactionManager(springboot内置的)来实现编程式事务
 @Autowired
     private DataSourceTransactionManager transactionManager;
 ​
     public void updateName(){
         // 定义事务属性
         DefaultTransactionDefinition def = new DefaultTransactionDefinition();
         // 获取事务状态
         TransactionStatus status = transactionManager.getTransaction(def);
         try {
             // 在此处执行数据库操作或其他业务逻辑
             String username = "ready to one+1";
             Integer num = 1;
             workersMapper.updateUserName(username, num);
             int res = 1/0;
             // 提交事务
             transactionManager.commit(status);
 ​
         } catch (Exception e) {
             // 发生异常时回滚事务
             transactionManager.rollback(status);
         }
     }

上述例子中,会发生异常ArithmeticException,从而导致事务回滚,不会对数据库进行更新。

以上就是编程式事务,可以发现——它将事务的控制跟业务代码混合在了一起,这一定程度上增加了代码的复杂性。且在每个操作前后都需要手动调用事务管理器的方法,这可能会增加出错的可能性。如果在一些业务复杂的情况下,该情况尤为明显。

因此,对于复杂的业务逻辑,通常建议使用声明式事务管理,因为它更简洁、更易于管理。

声明式事务

使用声明式事务——首先,需要在Spring的配置文件中配置一个PlatformTransactionManager的实现,例如DataSourceTransactionManager。然后,可以在需要使用事务的方法或类上添加注解,例如@Transactional注解,来开启事务。

  • 配置事务管理器
 @Configuration
 public class AppConfig {
     
     @Autowired
     private DataSource dataSource;
 ​
     @Bean
     public PlatformTransactionManager transactionManager() {
         return new DataSourceTransactionManager(dataSource);
     }
 }
  • 通过注解来开启事务
     @Transactional
     public void test(){
         String username = "part+1";
         Integer num = 1;
         workersMapper.updateUserName(username, num);
         int res = 1/0;
     }

@Transactional注解开启了事务,test方法在事务的保护下执行,如果在执行过程中出现了异常,事务会被自动回滚。

以上就是spring中使用事务的两种方式

注意事项

  • spring的事务注解@Transactional只能应用到 public 方法上才会有效。其他类型(如:private)的方法虽然不报错,但不会生效。
  • 在同一类中调用该类的另一方法,另一方法的事务不会生效,因为同一类中方法相互调用不会被方法拦截器拦截到,因此没有经过Spring的代理类。默认只有在外部调用事务才会生效。即相同类里边,A 方法没有事务,B 方法有事务,A 方法调用 B 方法,则 B 方法的事务会失效。
  • 没有在类上标注@Service@Component等注解,这个类就不会被加载成一个Bean,这个类就不会被Spring管理了,事务就失效了。
  • 建议事务注解 @Transactional 一般添加在实现类上,而不要定义在接口上,如果加在接口类或接口方法上时,只有配置基于接口的代理这个注解才会生效。
  • 相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论