Skip to content

事务控制

@Transactional注解参数说明

事务传播行为种类:SpringTransactionDefinition接口中规定了7种类型的事务传播行为,**它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播。 使用示例:@Transactional(propagation=Propagation.REQUIRED)

事务传播行为类型说明
PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类 似的操作。

@Transactional注解失效原因排查

  1. @Transactional 加于private方法,无效
  2. @Transactional 加于未加入接口的public方法, 无效
  3. @Transactional 加于未加入接口的public方法,再通过普通接口方法调用,无效
  4. @Transactional 加于接口方法后,无论下面调用的是private或public方法,都有效
  5. @Transactional 加于接口方法后,被本类普通接口方法直接调用,无效
  6. @Transactional 加于接口方法后,被本类普通接口方法通过接口调用,有效
  7. @Transactional 加于接口方法后,被它类的接口方法调用,有效
  8. @Transactional 加于接口方法后,被它类的私有方法调用后,有效
  9. 方法捕获异常但没抛出异常,无效

失效原因说明

@Transactional失效的背后其实就是Spring代理机制造成的。通俗点说就是我们现在都不用去new对象了,而是把对象交给Spring去管理,既然交给Spring去管理,那就要按照Spring的方式去使用。 Spring是什么方式管理?它会把你注入的对象都转换成Bean,这个Bean是被修饰过的代理类,它和new出来的对象不一样。 为什么this.xxxxx()会失效?因为this调用是java的方式,它并不是Spring的调用方式。

手动事务/编程式事务

方式一

java
//这个类在配数据源的时候要配置
@Autowired
DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
TransactionDefinition transactionDefinition;
 
//开启手动事务
TransactionStatus transactionStatus = null;
try {
    transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
    //批量插入
    workProMapper.insertBatchInterruptData(batchList);
    dataSourceTransactionManager.commit(transactionStatus);//提交
}catch (Exception e){
    e.printStackTrace();
    log.error(e.getMessage(),e);//记录日志
    dataSourceTransactionManager.rollback(transactionStatus);//回滚
}

方式二

java
@Autowired
private TransactionTemplate transactionTemplate;
 
public void performTransactionalOperation() {
    //execute方法是被try catch包裹的,自动做了开启事务和回滚事务
    transactionTemplate.execute(new TransactionCallback<Void>() {
        public Void doInTransaction(TransactionStatus status) {
            //在这里执行数据库操作
 
            return null;
        }
    });
}