美文网首页
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