@Transactional事务传播

@Transactional事务传播

原始表数据

image-20230701191818135

@Transactional()控制事务传播的配置项目(默认Propagation.REQUIRED)

@Transactional(propagation=Propagation.REQUIRED)           //控制事务传播。默认是Propagation.REQUIRED
@Transactional(isolation=Isolation.DEFAULT)                //控制事务隔离级别。默认跟数据库的隔离级别相同
@Transactional(readOnly=false)                             //控制事务可读写、只可读。默认可读写
@Transactional(timeout=30)                                 //控制事务的超时时间,单位秒。默认跟数据库的事务控制系统相同
@Transactional(rollbackFor=RuntimeException.class)         //控制事务遇到哪些异常会回滚。默认是RuntimeException
@Transactional(rollbackForClassName=RuntimeException)      //同上
@Transactional(noRollbackFor=NullPointerException.class)   //控制事务遇到哪些异常不会回滚。默认遇到RuntimeException回滚
@Transactional(noRollbackForClassName=NullPointerException)//同上

咱们此次就使用默认的@Transactional注解,不添加任何参数。

并且不使用**try{}catch{}**捕获异常。

同类调用方法

同类A方法调用B方法

1. 同类A方法和B方法都有@Transactional注解

@Service
public class A_Service {
    
    
    @Resource
    UserMapper userMapper;
    
	@Transactional
    public void A(){
    
    
        User user = new User();
        user.setId(5);
        user.setEmail("A");
        userMapper.updateById(user);
        B();
    }

    @Transactional
    public void B(){
    
    
        User user = new User();
        user.setId(5);
        user.setEmail("B");
        userMapper.updateById(user);
        throw new RuntimeException("B方法业务异常");
    }
}

然后使用测试类测试方法

@SpringBootTest
public class TransactionalTest {
    
    
    @Resource
    A_Service a_Service;

    @Test
    public void test(){
    
    
        a_Service.A();
    }
}

运行结果

image-20230701193714501

然后再看看数据库数据回滚没有

image-20230701193847889

可以看到数据已经回滚

当同类A方法和B方法@Transactional注解,当A方法调用B方法时,B方法自己有事务,但是A方法也有事务,B方法就会加入A方法的事务里。

所以在A、B任何地方发生异常都会进行回滚。

2. A方法有@Transactional注解,B方法没有

修改B方法:

    public void B(){
    
    
        User user = new User();
        user.setId(5);
        user.setEmail("B");
        userMapper.updateById(user);
        throw new RuntimeException("B方法业务异常");
    }

再次测试,然后再看看数据库数据回滚没有

image-20230701193847889

当同类A方法@Transactional注解,当是B方法没有时,当A方法调用B方法时,A方法有事务,但B方法没有,B方法就会加入A方法的事务里。

所以在A、B任何地方发生异常都会进行回滚。

3. A方法没有@Transactional注解,B方法有@Transactional注解

修改A方法

public void A(){
    
    
    User user = new User();
    user.setId(5);
    user.setEmail("A");
    userMapper.updateById(user);
    b_service.B();
}

再次测试,然后再看看数据库数据回滚没有

image-20230701202200706

可以看到数据被A方法和B方法的都进行了修改。

说明当同类B方法被A方法调用时,B方法发现A方法没有事务。所以自己的事务也不会生效,所以两条SQL都没有进行回滚。

异类调用方法

A类A方法调用B类B方法

1. A类A方法和B类B方法都有@Transactional注解

A类:

@Service
public class A_Service {
    
    
    @Resource
    UserMapper userMapper;

    @Resource
    B_Service b_service;

    @Transactional
    public void A(){
    
    
        User user = new User();
        user.setId(5);
        user.setEmail("A");
        userMapper.updateById(user);
        b_service.B();
    }
}

B类:

@Service
public class B_Service {
    
    
    @Resource
    UserMapper userMapper;

    @Transactional
    public void B(){
    
    
        User user = new User();
        user.setId(5);
        user.setEmail("B");
        userMapper.updateById(user);
        throw new RuntimeException("B方法业务异常");
    }
}

然后使用测试类测试方法

@SpringBootTest
public class TransactionalTest {
    
    
    @Resource
    A_Service a_Service;

    @Test
    public void test(){
    
    
        a_Service.A();
    }
}

运行结果

image-20230701193714501

然后再看看数据库数据回滚没有

image-20230701193847889

可以看到数据已经回滚

当A类A方法和B类B方法@Transactional注解,当调用B类B方法时,B方法自己有事务,但是A方法也有事务,B方法就会加入A方法的事务里。

所以在A、B任何地方发生异常都会进行回滚。

2. A类A方法有@Transactional注解,B类B方法没有

修改B类B方法:

    public void B(){
    
    
        User user = new User();
        user.setId(5);
        user.setEmail("B");
        userMapper.updateById(user);
        throw new RuntimeException("B方法业务异常");
    }

再次测试,然后再看看数据库数据回滚没有

image-20230701193847889

可以看到数据已经回滚

当A类A方法有@Transactional注解,B类B方法没有。

当A类A方法调用B类B方法时,B类B方法会加入A类A方法的事务。所以B类B方法报错,两个方法的SQL会全部回滚。

如果异常是在调用完B类B方法,在A类A方法或者B类B方法发生异常,事务都会进行回滚。

3. A类A方法没有@Transactional注解,B类B方法有@Transactional注解

修改A类A方法

public void A(){
    
    
    User user = new User();
    user.setId(5);
    user.setEmail("A");
    userMapper.updateById(user);
    b_service.B();
}

再次测试,然后再看看数据库数据回滚没有

image-20230701195710127

可以看到数据被A类A方法修改了,但是B类B方法的的数据回滚

说明当B类B方法被A类A方法调用时,B类B方法发现A类A方法没有事务,但是自己有事务就会创建事务,但是A类A方法依旧不会回滚。

如果异常是在调用完B类B方法,在A类A方法发生异常,那A和B方法的SQL都会执行,并且事务不会回滚。

总结

我们发现同类和异类事务大致相同,比如A类A方法和B类B方法都有@Transactional注解和A类A方法有@Transactional注解,B类B方法没有注解都是一样的效果。

但是有一点不同的是:同类A方法没有@Transactional注解,B方法有@Transactional注解和A类A方法没有@Transactional注解,B类B方法有@Transactional注解,得到的效果是不一样的。

本期测试到此结束

猜你喜欢

转载自blog.csdn.net/m0_57647880/article/details/131494624