事务

1.事务传播机制

Propagation 属性

  • REQUIRED(Spring默认的事务传播类型):如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务
    a1 b1 b2 回滚
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
    A(a1);  //调用A入参a1
    testB();    //调用testB
}
@Transactional(propagation = Propagation.REQUIRED)
public void testB(){
    B(b1);  //调用B入参b1
    throw Exception;     //发生异常抛出
    B(b2);  //调用B入参b2
}
  • REQUIRES_NEW:每次执行都会创建新事务,并同时将上下文中的事务挂起,执行完当前线程后再恢复上下文中事务。
    a1 回滚 b1 b2 成功 (B是新事物 和A独立)
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
    A(a1);  //调用A入参a1
    testB();    //调用testB
    throw Exception;     //发生异常抛出
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void testB(){
    B(b1);  //调用B入参b1
    B(b2);  //调用B入参b2
}
  • SUPPORTS:如果上下文中存在事务则加入当前事务,如果没有事务则以非事务方式执行。
    a1 b1 成功 b2 失败 (A无事务,B按非事务执行,如果A有事务,B也有事务)
public void testMain(){
    A(a1);  //调用A入参a1
    testB();    //调用testB
}
@Transactional(propagation = Propagation.SUPPORTS)
public void testB(){
    B(b1);  //调用B入参b1
    throw Exception;     //发生异常抛出
    B(b2);  //调用B入参b2
}
  • NOT_SUPPORTED:当上下文中有事务则挂起当前事务,执行完当前逻辑后再恢复上下文事务。
    a1 b2 失败 b1 成功 (B按无事务执行 b1成功 b2失败 A有事务 a1失败)
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
    A(a1);  //调用A入参a1
    testB();    //调用testB
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void testB(){
    B(b1);  //调用B入参b1
    throw Exception;     //发生异常抛出
    B(b2);  //调用B入参b2
}
  • MANDATORY:该传播级别要求上下文中必须存在事务,否则抛出异常。
    a1成功 b1 b2失败 (B无事务,抛异常)
public void testMain(){
    A(a1);  //调用A入参a1
    testB();    //调用testB
}
@Transactional(propagation = Propagation.MANDATORY)
public void testB(){
    B(b1);  //调用B入参b1
    throw Exception;     //发生异常抛出
    B(b2);  //调用B入参b2
}
  • NEVER:该传播级别要求上下文中不能存在事务,否则抛出异常。
    B直接抛出事务异常 A回滚 都失败
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
    A(a1);  //调用A入参a1
    testB();    //调用testB
}
@Transactional(propagation = Propagation.NEVER)
public void testB(){
    B(b1);  //调用B入参b1
    B(b2);  //调用B入参b2
}
  • NESTED:嵌套事务,如果上下文中存在事务则嵌套执行,如果不存在则新建事务
    都回滚
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
    A(a1);  //调用A入参a1
    testB();    //调用testB
    throw Exception;     //发生异常抛出
}
@Transactional(propagation = Propagation.NESTED)
public void testB(){
    B(b1);  //调用B入参b1
    B(b2);  //调用B入参b2
}

2.事务异常处理

spring事务只对RuntimeException奏效,同一个Service类中的方法相互调用需要使用注入的对象来调用,不要直接使用this.方法名来调用,this.方法名调用是对象内部方法调用,不会通过Spring代理,也就是事务不会起作用,通过aop来获取异常,如果手动捕获则不会回滚

  • 正常回滚
@PostMapping("/test")
@Transactional
public void test() {
    transPlatformAccessMapper.insertTest();
    int i = 1/0;
}
  • 不会回滚
@PostMapping("/test")
@Transactional
public void test() {
    try{
        transPlatformAccessMapper.insertTest();
        int i = 1/0;
    }catch (Exception e){
        e.printStackTrace();
    }

}

2.1 手动回滚

  • 回滚点
@PostMapping("/test")
    @Transactional
    public void test() {
        //设置回滚点,只回滚以下异常
        Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
        try{
            transPlatformAccessMapper.insertTest();
            int i = 1/0;
        }catch (Exception e){
            e.printStackTrace();
            //手工回滚到回滚点
            TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
        }
    }
  • 全部回滚
@PostMapping("/test")
@Transactional
public void test() {
    try{
        transPlatformAccessMapper.insertTest();
        int i = 1/0;
    }catch (Exception e){
        e.printStackTrace();
        // 全部回滚
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}
posted @ 2023-08-30 13:56  lwx_R  阅读(5)  评论(0编辑  收藏  举报