事务的学习


事务:

@Transactional注解与try catch_@transactional try catch-CSDN博客

一口气怼完12种@Transactional的失效场景_@transactional try catch不生效的场景-CSDN博客

事务方法的调用

同一个类中

1.事务A掉 非事务B B抛异常

AB事务生效 A,B方法都会发生回滚(具有传播性)

 @Transactional(rollbackFor = Exception.class)
    public int doSaveUserA(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(100));
        user.setName("小红");
        user.setPhone("123455");
        userMapper.insert(user);
        doSaveUserB();
        return result;
    }

    public int doSaveUserB(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(101));
        user.setName("小lijdifajldf");
        user.setPhone("123455");
        userMapper.insert(user);
            int u = 1/0;
        return result;
    }

2.事务A掉非事务B A抛异常 AB事务生效;

A,B中方法都会发生回滚

@Transactional(rollbackFor = Exception.class)
public int doSaveUserA(){
    int result=0;
    User user = new User();
    user.setId(Long.valueOf(100));
    user.setName("小红");
    user.setPhone("123455");
    userMapper.insert(user);
    doSaveUserB();
    int a = 1/0;
    return result;
}


public int doSaveUserB(){
    int result=0;
    User user = new User();
    user.setId(Long.valueOf(101));
    user.setName("小lijdifajldf");
    user.setPhone("123455");
    userMapper.insert(user);
    return result;
}

3 事务A掉事务B A抛异常

AB事务生效(会进行事务的回滚)

@Transactional(rollbackFor = Exception.class)
    public int doSaveUserA(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(100));
        user.setName("小红");
        user.setPhone("123455");
        userMapper.insert(user);
        doSaveUserB();
        int a = 1/0;
        return result;
    }


    @Transactional(rollbackFor = Exception.class)
    public int doSaveUserB(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(101));
        user.setName("小lijdifajldf");
        user.setPhone("123455");
        userMapper.insert(user);
        return result;
    }

4 事务A掉事务B B抛异常 AB事务生效(回滚)

 @Transactional(rollbackFor = Exception.class)
    public int doSaveUserA(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(100));
        user.setName("小红");
        user.setPhone("123455");
        userMapper.insert(user);
        doSaveUserB();

        return result;
    }


    @Transactional(rollbackFor = Exception.class)
    public int doSaveUserB(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(101));
        user.setName("小lijdifajldf");
        user.setPhone("123455");
        userMapper.insert(user);
        int a = 1/0;
        return result;
    }

5 非事务A调用事务B B抛异常

A无事务 B事务不生效 也就是不会回滚

这里有个点 调用事务的方法A 和 事务方法B不能再同一个类中

public int doSaveUserA(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(100));
        user.setName("小红");
        user.setPhone("123455");
        userMapper.insert(user);
        doSaveUserB();

        return result;
    }


    @Transactional(rollbackFor = Exception.class)
    public int doSaveUserB(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(101));
        user.setName("小lijdifajldf");
        user.setPhone("123455");
        userMapper.insert(user);
        int a = 1/0;
        return result;
    }

A,B都会插入

6.非事务A掉事务B(通过注入-相当于调用不同类中的B方法)

B抛异常 A无事务,B事务生效

什么叫做通过注入的方法

@Service
public class TranscationServiceImpl {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TranscationServiceImpl transcationServiceImpl;


    public int doSaveUserA(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(100));
        user.setName("小红");
        user.setPhone("123455");
        userMapper.insert(user);
        transcationServiceImpl.doSaveUserB();
        return result;
    }


    @Transactional(rollbackFor = Exception.class)
    public int doSaveUserB(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(101));
        user.setName("小lijdifajldf");
        user.setPhone("123455");
        userMapper.insert(user);
        int a = 1/0;
        return result;
    }
}

A会插入,B不会插入,会发生回滚

7.非事务A掉事务B(通过注入)

A抛异常 A无事务,B不触发事务,ab数据都会增加成功

public class TranscationServiceImpl {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TranscationServiceImpl transcationServiceImpl;


    public int doSaveUserA(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(100));
        user.setName("小红");
        user.setPhone("123455");
        userMapper.insert(user);
        transcationServiceImpl.doSaveUserB();
        int a =1/0;
        return result;
    }


    @Transactional(rollbackFor = Exception.class)
    public int doSaveUserB(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(101));
        user.setName("小lijdifajldf");
        user.setPhone("123455");
        userMapper.insert(user);
        return result;
    }
}

8. 事务A掉非事务B(通过注入)

A或B抛异常 AB事务生效 (事务传播性)

public class TranscationServiceImpl {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TranscationServiceImpl transcationServiceImpl;


    @Transactional(rollbackFor = Exception.class)
    public int doSaveUserA(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(100));
        user.setName("小红");
        user.setPhone("123455");
        userMapper.insert(user);
        transcationServiceImpl.doSaveUserB();
        return result;
    }



    public int doSaveUserB(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(101));
        user.setName("小lijdifajldf");
        user.setPhone("123455");
        userMapper.insert(user);
        int a =1/0;
        return result;
    }
}

总结

直接调用
1.事务A     调用  非事务B    B抛异常    AB事务生效            A,B方法都会发生回滚(具有传播性)
2.事务A     调用  非事务B    A抛异常    AB事务生效;          A,B中方法都会发生回滚
3.事务A     调用  事务B      A抛异常    AB事务生效           (会进行事务的回滚)
4.事务A     调用  事务B      B抛异常    AB事务生效           (回滚)
5.非事务A   调用  事务B      B抛异常    A无事务 B事务不生效    也就是不会回滚

通过注入的方式 通过注入-相当于调用不同类中的B方法
6.非事务A   调用  事务B     B抛异常     A无事务,B事务生效        A不会回滚,B会发生回滚
7.非事务A   调用  事务B     A抛异常     A无事务,B不触发发事务     A,B数据都会增加成功
8.事务A     调用  非事务B   A或B抛异常  AB事务生效 (事务传播性)  都会发生回滚

结论: 事务A方法调用方法B, 无论方法B有无事务 以及 A或者B方法发生异常,都会进行方法的回滚(事务生效)

非事务A方法调用方法B, B只有通过注入(AOP)的方式进行调用才会生效,

​ private 方法不能加事务

非事务A掉事务B(AOP)方式可以用xxxService xxxService = (xxxService)(AopContext.currentProxy());然后xxxService.B(),获取到xxxService的代理类,再调用事务方法,强行经过代理类,激活B事务切面。

@Service
public class TranscationServiceImpl {

    @Autowired
    private UserMapper userMapper;





    public int doSaveUserA(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(100));
        user.setName("小红");
        user.setPhone("123455");
        userMapper.insert(user);
        TranscationServiceImpl transcationService = (TranscationServiceImpl) (AopContext.currentProxy());
        transcationService.doSaveUserB();
        return result;
    }



    @Transactional(rollbackFor = Exception.class)
    public int doSaveUserB(){
        int result=0;
        User user = new User();
        user.setId(Long.valueOf(101));
        user.setName("小lijdifajldf");
        user.setPhone("123455");
        userMapper.insert(user);
        int a =1/0;
        return result;
    }
}

Spring的事务的传播机制

【Spring学习34】Spring事务(4):事务属性之7种传播行为_事物属性与行为-CSDN博客

一文搞通Spring事务的七种传播机制(通俗易懂)_spring事务传播机制-CSDN博客

​ Spring事务传播机制是指在多个事务方法相互调用的情况下,事务如何在方法之间进行传播和管理的机制。通过事务传播机制,可以控制事务的范围和行为,保证多个事务方法的一致性和完整性。Spring提供了七种事务传播行为,分别是:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。其中REQUIRED为Spring默认的传播机制。

7种传播机制简介

1.REQUIRED:如果当前存在事务,则加入该事务,如果不存在事务,则创建一个事务。

​ **解释:**当方法a声明了该事务,方法b也声明该事务时,如果方法a调用了方法b,那么b不会再创建自己事务而是加入方法a,他们共享同一个事务上下文,b回滚a也回滚、a回滚b也回滚。

​ 而当方法a未声明事务,方法b声明了该事务时,a调用b,会为方法b创建事务,而a不会。

(required需要,没有新建,有加入)

@Transactional(propagation = Propagation.REQUIRED)  //默认@Transactional即可

​ REQUIRED常用于有修改操作的操作

  1. SUPPORTS:如果当前存在事务,则加入该事务,如果不存在事务,则以非事务的方式执行。

    解释:当方法a声明了一个事务,方法b声明了该事务时,同理,他们共享事务上下文。

    ​ 而当方法a未声明事务,方法b声明该事务,a调用b,a、b都没有事务,出现异常时a、b都不回滚。 当然如果有一个方法c声明了该事务,我们直接调用该方法,出现异常也不会回滚,

    ​ 因为主方法是未声明事务的,因此c也以非事务的方式执行。

    supports支持,有则加入,没有就不管了,非事务运行

    @Transactional(propagation = Propagation.SUPPORTS)
    

    SUPPORTS常用于只有查询相关的操作:当只需要查询时不开启事务,而当需要根据这些查询结果再进行修改操作时,加入到修改操作方法的事务中去,从而保证原子性

3.MANDATORY:如果当前存在事务,则加入到当前事务中;如果当前没有事务,则抛出异常。

​ **解释:**当方法a声明了一个事务,方法b声明了该事务时,同理,他们共享事务上下文。

​ 而当方法a未声明事务,方法b声明事务,a调用b,抛出异常。

​ 同理如果有一个方法c声明了该事务,我们直接调用该方法,由于主方法未声明事务因此会直接抛出异常。

mandatory强制性,有则加入,没有异常

@Transactional(propagation = Propagation.MANDATORY)
  1. REQUIRES_NEW:总是创建一个新的事务,如果当前存在事务,则挂起当前事务。

    解释: 不论方法a是否声明事务,方法b声明了该事务时,a调用b,都会为b创建一个自己的事务。

    ​ 而当a没有事务时,b独立事务运行;

    ​ 当a有事务时,挂起a的事务,等待b的事务执行完毕后再恢复执行a。

    requires_new需要新的,不管有没有,直接创建新事务

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    
  2. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起当前事务

    **解释:**如果方法a存在事务,会挂起a的事务,等待b执行完毕后再恢复执行a。

    not supported不支持事务,存在就挂起

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    
  3. NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。

          解释:当方法a声明了一个事务,方法b声明了该事务时,a调用b,b方法会抛出异常。
       
          <font color='red'>(**never不支持事务,存在就异常**)</font>
    
    @Transactional(propagation = Propagation.NEVER)
    

7. NESTED:如果当前存在事务,则在当前事务中创建一个新的嵌套事务;如果当前没有事务,则创建一个新的事务。

required 事务与 nested事务的区别

​ 解释:如果数据库支持嵌套事务,那么就会存在多个begin和commit,a调用b,方法b运行完就提交了,与a互不影响。如果数据库不支持嵌套事务比如常用的MySQL,那么使用savepoint设置保存点,如果代码出现问题需要回滚,就使用rollback返回到保持点,最后在代码执行完后commit。

nested存在就在嵌套的执行,没有就找是否存在外面的事务,有则加入,没有则新建

 @Transactional(propagation = Propagation.NESTED)

事务传播的49种组合方式

​ 这里都以方法a和方法b举例,a调用b。

1.方法a事务传播方式为REQUIRED时
REQUIRED - REQUIRED:
    如果a方法在事务中运行,则b方法将继承a方法的事务。
    如果a方法没有事务,则b方法将在一个新的事务中运行。
REQUIRED - SUPPORTS:
    如果a方法在事务中运行,则b方法将继承a方法的事务。
    如果a方法没有事务,则b方法将以非事务方式运行。
REQUIRED - MANDATORY:
    如果a方法在事务中运行,则b方法将继承a方法的事务。
    如果a方法没有事务,则b方法将抛出异常。
REQUIRED - REQUIRES_NEW
    无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
REQUIRED - NOT_SUPPORTED
    如果a方法在事务中运行,则b方法将以非事务方式运行。
    如果a方法没有事务,则b方法也将以非事务方式运行。
REQUIRED - NEVER
    如果a方法在事务中运行,则b方法将抛出异常。
    如果a方法没有事务,则b方法将以非事务方式运行。
REQUIRED - NESTED
    如果a方法在事务中运行,则b方法将作为a方法的嵌套事务运行。
    如果a方法没有事务,则b方法将在一个新的事务中运行。
2. 方法a事务传播方式为SUPPORTS时
SUPPORTS - REQUIRED:
            如果a方法在事务中运行,则b方法将继承a方法的事务。
            如果a方法没有事务,则b方法将在一个新的事务中运行。
SUPPORTS - SUPPORTS:
           无论a方法是否在事务中运行,b方法都不会开启新的事务,而是以非事务方式运行。
SUPPORTS - MANDATORY:
            如果a方法在事务中运行,则b方法将继承a方法的事务。
            如果a方法没有事务,则b方法将抛出异常。
SUPPORTS - REQUIRES_NEW:
           无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
SUPPORTS - NOT_SUPPORTED:
           无论a方法是否在事务中运行,b方法都将以非事务方式运行。
SUPPORTS - NEVER:
          如果a方法在事务中运行,则b方法将抛出异常。如果a方法没有事务,则b方法将以非事务方式运行。
SUPPORTS - NESTED:
          如果a方法在事务中运行,则b方法将作为a方法的嵌套事务运行。如果a方法没有事务,则b方法将以非事务方式运行。
3. 方法a事务传播方式为MANDATORY时
MANDATORY - REQUIRED:
       如果a方法在事务中运行,则b方法将继承a方法的事务。
       如果a方法没有事务,则b方法将抛出异常。
MANDATORY - SUPPORTS:
       如果a方法在事务中运行,则b方法将继承a方法的事务。
       如果a方法没有事务,则b方法将以非事务方式运行。
MANDATORY - MANDATORY
       如果a方法在事务中运行,则b方法将继承a方法的事务。
       如果a方法没有事务,则b方法将抛出异常。
MANDATORY - REQUIRES_NEW
       无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
MANDATORY - NOT_SUPPORTED
       如果a方法在事务中运行,则b方法将以非事务方式运行。
       如果a方法没有事务,则b方法也将以非事务方式运行。
MANDATORY - NEVER
       如果a方法在事务中运行,则b方法将抛出异常。
       如果a方法没有事务,则b方法将以非事务方式运行。
MANDATORY - NESTED
       如果a方法在事务中运行,则b方法将作为a方法的嵌套事务运行。
       如果a方法没有事务,则b方法将抛出异常。
4. 方法a事务传播方式为REQUIRES_NEW时
REQUIRES_NEW - REQUIRED:
        无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
REQUIRES_NEW - SUPPORTS:
        无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
REQUIRES_NEW - MANDATORY:
        无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
REQUIRES_NEW - REQUIRES_NEW:
        无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
REQUIRES_NEW - NOT_SUPPORTED:
        无论a方法是否在事务中运行,b方法都将以非事务方式运行。
REQUIRES_NEW - NEVER:
        无论a方法是否在事务中运行,b方法都会以非事务方式运行。
REQUIRES_NEW - NESTED:
        无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
5. 方法a事务传播方式为NOT_SUPPORTED时
NOT_SUPPORTED - REQUIRED
       如果a方法在事务中运行,则b方法将以非事务方式运行。
       如果a方法没有事务,则b方法将在一个新的事务中运行。
NOT_SUPPORTED - SUPPORTS
       无论a方法是否在事务中运行,b方法都将以非事务方式运行。
NOT_SUPPORTED - MANDATORY
       如果a方法在事务中运行,则b方法将以非事务方式运行。
       如果a方法没有事务,则b方法将抛出异常。
NOT_SUPPORTED - REQUIRES_NEW
      无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
NOT_SUPPORTED - NOT_SUPPORTED
      无论a方法是否在事务中运行,b方法都将以非事务方式运行。
NOT_SUPPORTED - NEVER
      如果a方法在事务中运行,则b方法将抛出异常。
      如果a方法没有事务,则b方法将以非事务方式运行。
NOT_SUPPORTED - NESTED
      如果a方法在事务中运行,则b方法将以非事务方式运行。
      如果a方法没有事务,则b方法将在一个新的事务中运行。
6.方法a事务传播方式为NEVER时
NEVER - REQUIRED
        如果a方法在事务中运行,则b方法将抛出异常。
        如果a方法没有事务,则b方法将在一个新的事务中运行。
NEVER - SUPPORTS
        如果a方法在事务中运行,则b方法将抛出异常。
        如果a方法没有事务,则b方法将以非事务方式运行。
NEVER - MANDATORY
       如果a方法在事务中运行,则b方法将抛出异常。
       如果a方法没有事务,则b方法将抛出异常。
NEVER - REQUIRES_NEW
       无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
NEVER - NOT_SUPPORTED
       无论a方法是否在事务中运行,b方法都将以非事务方式运行。
NEVER - NEVER
       如果a方法在事务中运行,则b方法将抛出异常。如果a方法没有事务,则b方法将以非事务方式运行。
NEVER - NESTED
       如果a方法在事务中运行,则b方法将抛出异常。如果a方法没有事务,则b方法将以非事务方式运行。
7.方法a事务传播方式为NESTED时
NESTED - REQUIRED
        如果a方法在事务中运行,则b方法将作为a方法的嵌套事务运行。
        如果a方法没有事务,则b方法将在一个新的事务中运行。
NESTED - SUPPORTS
        如果a方法在事务中运行,则b方法将作为a方法的嵌套事务运行。
        如果a方法没有事务,则b方法将以非事务方式运行。
NESTED - MANDATORY
        如果a方法在事务中运行,则b方法将作为a方法的嵌套事务运行。
        如果a方法没有事务,则b方法将抛出异常。
NESTED - REQUIRES_NEW
        无论a方法是否在事务中运行,b方法都会开启一个新的事务并在该事务中运行。
NESTED - NOT_SUPPORTED
        如果a方法在事务中运行,则b方法将以非事务方式运行。
        如果a方法没有事务,则b方法将以非事务方式运行。
NESTED - NEVER
         如果a方法在事务中运行,则b方法将抛出异常。
         如果a方法没有事务,则b方法将以非事务方式运行。
NESTED - NESTED
         如果a方法在事务中运行,则b方法将作为a方法的嵌套事务运行。
         如果a方法没有事务,则b方法将在一个新的事务中运行。

@Transcational 与 try catch

​ 如果在该注解标注的方法或被其调用的方法中有try catch,那么想要使得事务生效,一定要在catch中把异常直接抛出,如果不处理不向上抛出,则事务不会生效

与try…catch同时使用

方法一:catch代码块手动抛出新的异常
try{
	...
}catch(Exception e){
	// throw e;在rollbackFor = Exception.class时可用
	throw new RuntimeException();//抛出新的异常
}

方法二:catch代码块手动事务回滚
try{
	...
}catch(Exception e){
	TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
	...
}

Spring事务@Transactional常见的8种失效场景(通俗易懂)_事务失效的8大场景-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白鼠666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值