美文网首页
Spring事务传播实现子事务的独立性

Spring事务传播实现子事务的独立性

作者: 十毛tenmao | 来源:发表于2019-07-13 21:16 被阅读0次

    在一些业务场景中,为了保持业务数据的一致性,需要用到事务,特别是交易系统。但是其中部分逻辑,比如订单关闭,需要自成一个独立的事务,最重要的是不能受到外部事务调用的影响(比如外部的异常,不能导致订单关闭子逻辑的回滚)。Spring使用事务传播的特性,完美地解决这个问题

    Spring事务传播

    Spring在TransactionDefinition接口中规定了7种类型的事务传播行为。事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为。这是Spring为我们提供的强大的工具箱,使用事务传播行可以为我们的开发工作提供许多便利。

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

    根据Spring事务传播的类型,可以看出PROPAGATION_REQUIRES_NEW是可以满足我们的需求的

    业务实现

    这里我们假设创建订单时,需要完成了两步(插入用户,插入商品,这里没用关闭订单做示例了,因为逻辑比较复杂),其中插入用户这一步,自身的事务特性不受外部影响,所以使用Propagation.REQUIRES_NEW

    • UserManager
    @Component
    public class UserManager {
        @Resource
        private UserMapper userMapper;
    
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        public void insert(User user) {
            userMapper.insert(user);
        }
    
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        public void insertWithException(User user) {
            userMapper.insert(user);
            throw new RuntimeException("foo");
        }
    }
    
    • ProductManager
    @Component
    public class ProductManager {
        @Resource
        private ProductMapper productMapper;
    
        @Transactional(propagation = Propagation.REQUIRED)
        public void insert(Product product) {
            productMapper.insert(product);
        }
    }
    

    验证

    • 外部异常:用户信息插入成功,商品信息插入失败
    @Component
    public class OrderManager {
        @Resource
        private UserManager userManager;
        @Resource
        private ProductManager productManager;
    
        @Transactional(rollbackFor = Exception.class)
        public void createOrder(String userName, String productName) {
            User user = new User(null, userName);
            //插入用户信息
            userManager.insert(user);
    
            Product product = new Product(null, productName);
    
            //插入商品信息
            productManager.insert(product);
            throw new RuntimeException("fail to create order");
        }
    }
    
    • 插入用户异常:用户信息插入失败,商品信息插入失败
    @Transactional(rollbackFor = Exception.class)
    public void createOrder(String userName, String productName) {
        User user = new User(null, userName);
        userManager.insertWithException(user);
    
        Product product = new Product(null, productName);
    
        productManager.insert(product);
        throw new RuntimeException("fail to create order");
    }
    

    参考

    相关文章

      网友评论

          本文标题:Spring事务传播实现子事务的独立性

          本文链接:https://www.haomeiwen.com/subject/irtvkctx.html