首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring事务传播实现子事务的独立性

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

作者头像
十毛
发布2019-07-15 14:39:22
9980
发布2019-07-15 14:39:22
举报

在一些业务场景中,为了保持业务数据的一致性,需要用到事务,特别是交易系统。但是其中部分逻辑,比如订单关闭,需要自成一个独立的事务,最重要的是不能受到外部事务调用的影响(比如外部的异常,不能导致订单关闭子逻辑的回滚)。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");
}

参考

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.07.13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring事务传播
  • 业务实现
  • 验证
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档