Spring事务传播级别REQUIRED和NOT_SUPPORTED测试

10 篇文章 0 订阅

背景

Spring为了让在同一个方法下处理不同的事务,于是有了事务传播级别

REQUIRED

当前线程没有事务,会新建一个事务,如果存在事务,则使用该事务

NOT_SUPPORTED

当前线程存在事务,挂起当前事务,执行完后,恢复挂起的事务

事例

测试同一个声明式事务下的REQUIRED和NOT_SUPPORTED

TestPropagation
public class TestPropagation {
    private UserService userService;
    /** 
    * 顶层事务处理逻辑
    * @since 2021/1/12 
    */ 
    @Transactional(propagation = Propagation.REQUIRED)
     public void test() throws SQLException {
        //插入用户记录  使用Propagation.REQUIRED ,如果当前存在事务,使用该事务,如果没有则创建新的事务
        userService.insertUser();
        //插入用户记录  使用Propagation.NOT_SUPPORTED  会挂起当前事务,执行完后,会恢复挂起的事务
        //抛出异常会导致之前执行的事务回滚
        userService.insertUserWithPropagationNotSupported();
    }
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}
UserService
  @Transactional(rollbackFor = Exception.class,propagation= Propagation.REQUIRED)
    public void insertUser() throws SQLException {
        //使用Spring提供的工具类,获取当前线程的连接-已经在事务拦截器中创建了连接
        Connection connection = DataSourceUtils.getConnection(dataSource);
        //获取JDBC 执行SQL的对象
        Statement statement = connection.createStatement();
        //执行插入语句
        statement.execute("insert into t_user(name,age) values('小黑',100)");
    }

    @Transactional(rollbackFor = Exception.class,propagation= Propagation.NOT_SUPPORTED)
    public void insertUserWithPropagationNotSupported() throws SQLException {
        //使用Spring提供的工具类,获取当前线程的连接-已经在事务拦截器中创建了连接
        Connection connection = DataSourceUtils.getConnection(dataSource);
        //获取JDBC 执行SQL的对象
        Statement statement = connection.createStatement();
        //执行插入语句
        statement.execute("insert into t_user(name,age) values('小黑NOT_SUPPORTED',100)");
        //抛出异常,因为不支持事务,所以以上插入语句不会回滚
        int i=1/0;
    }
执行测试用例
    @Test
    public void testPropagation() throws SQLException {
        TestPropagation testPropagation = context.getBean(TestPropagation.class);
        UserService userService = context.getBean(UserService.class);
        try {
            //执行插入
            testPropagation.testInsertUser();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //查询所有用户结果
        userService.selectUser();
    }
打印查询结果
id:1 name:小明
id:2 name:小白
id:4 name:小黑NOT_SUPPORTED
结果说明
  • 先执行 insertUser() 后执行insertUserWithPropagationNotSupported()并抛出异常
  • insertUser()的结果被回滚
  • insertUserWithPropagationNotSupported()的结果没有回滚并成功持久化到数据库
  • 使用NOT_SUPPORTED事务传播级别后,如果抛出异常会导致其他事务回滚,而本身并不受影响
原因分析
  • @Transactional默认的事务传播级别是Propagation.REQUIRED
    • 使用此传播级别后,当执行方法时,会在本地线程创建一个连接,并且通过连接设置自动提交为fasle,即autoCommmit=false,当方法没有异常,最后会使用连接提交本次事务
  • @Transactional(propagation= Propagation.NOT_SUPPORTED)
    • 设置传播级别为Propagation.NOT_SUPPORTED后,当执行方法前,会判断当前线程是否存在事务,如果存在则挂起当前事务,并执行查询时使用新的连接
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值