如何使用编程式事务

555 阅读2分钟

介绍

编程式事务允许开发者在代码中明确控制事务的边界、启动、提交和回滚等操作,从而确保数据的一致性和完整性。编程式事务允许开发者根据业务逻辑将多个数据库操作组合成一个事务,或者将一个大事务拆分成多个小事务。这样可以避免不必要的数据锁定,提高系统的并发性能。

Spring框架提供了两种编程事务管理方法:

  • TransactionTemplate 或 TransactionalOperator。
  • 直接实现TransactionManager。

Spring 官方推荐使用 TransactionTemplate 在命令式流程中进行编程式事务管理,并推荐使用 TransactionalOperator 在反应式代码中进行编程式事务管理。

如何使用

1. TransactionTemplate

TransactionTemplate采用与其他Spring模板(如JdbcTemplate)相同的方法。它使用回调方法。通过调用TransactionTemplate#execute(..)方法,该方法接收一个TransactionCallback参数,该接口是一个函数式接口,我们只需将需要在事务上下文中执行的代码放入方法中即可。 将我们的业务代码放入doInTransaction方法中即可。该接口是有返回值的,它还有一个抽象子类TransactionCallbackWithoutResult,如果你没有返回值则可以使用该类。

  • 有返回值
@Service
public class UserService {
  @Resource
  private TransactionTemplate transactionTemplate ;
  public Integer saveUsers(Users users) {
    Integer result = transactionTemplate.execute(new TransactionCallback<Integer>() {
      @Override
      public Integer doInTransaction(TransactionStatus status) {
        return usersMapper.insertUser(users) ;
      }
    }) ;
    return result ;
  }
}
  • 无返回值
public void saveUsers(Users users) {
  transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    @Override
    protected void doInTransactionWithoutResult(TransactionStatus status) {
      usersMapper.insertUser(users) ;
    }
  }) ;
}
  • 事务回滚 事务的回滚通过TransactionStatus#setRollbackOnly方法。
public Users saveUser(Users users) {
  return transactionTemplate.execute(new TransactionCallback<Users>() {
    @Override
    public Users doInTransaction(TransactionStatus status) {
      try {
        return usersMapper.insertUser(users) ;
      } catch (Exception e) {
        // 回滚
        status.setRollbackOnly() ;
      }
      return null ;
    }
  }) ;
}
  • 事务属性配置 以上我们是通过直接注入系统默认创建的TransactionTemplate进行使用,都使用的是默认行为,我们可以通过如下的方式进行自定义属性的配置:
private TransactionTemplate transactionTemplate ;

public UserService(PlatformTransactionManager transactionManager) {
  // 自己构建事务模版
  this.transactionTemplate = new TransactionTemplate(transactionManager) ;
  // 事务传播行为
  this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED) ;
  // 设置超时时间
  this.transactionTemplate.setTimeout(30); // seconds
}

2. TransactionalOperator

该类是基于响应式编程中应用的编程式事务,这里就不做介绍了。

3. TransactionManager

该接口的有2个子接口分别是:

  • PlatformTransactionManager
  • ReactiveTransactionManager(基于响应式)

这里不对响应式对介绍。

private PlatformTransactionManager transactionManager ;
private DefaultTransactionDefinition definition ;
private TransactionStatus status ;

@Resource
private UsersRepository usersRepository ;

public UserService3(PlatformTransactionManager transactionManager) {
  this.transactionManager = transactionManager ;
  // 事务定义,比如:事务的传播特性
  definition = new DefaultTransactionDefinition() ;
  definition.setName("pgName") ;
  definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED) ;
}

public Integer saveUsers(Users users) {
  TransactionStatus status = this.transactionManager.getTransaction(definition) ;
  Integer result = null ;
  try {
    result = usersMapper.insertUser(users) ;
  } catch (Exception e) {
    // 回滚事务
    transactionManager.rollback(status) ;
    throw e ;
  }
  // 提交事务
  transactionManager.commit(status) ;
  return result ;    
}