Spring入门知识 ———— Spring事务的传播行为

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38111957/article/details/83959696

一、引言

不知道小伙伴们有没有想过这样一个问题,比如说有两个方法,同时都具有事务,如果说其中一个方法调用另外一个方法,那么事务运行的机制是什么样子的。如果被调用的方法正常执行,而调用者确异常了,那么整个事务会进行回滚吗?

针对这么一个问题,Spring还是提供了一个很好的解决办法,也提出一个概念,事务的传播行为。

二、事务的传播行为

当事务方法被另一个事物方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有的事务当中运行,也可能开启一个新的事务,并在自己的事务中运行。

事务的传播行为可以由传播属性指定,Spring定义7中类型传播行为,本章主要介绍两种常用的。

三、具体实现

接着上一章的案例继续,现在需要实现一个功能,可以一次性购买多个商品。

新建一个Service类,如果在同一个类中指定传播行为,是不会生效的。

@Service
public class CheckOutService {

    @Autowired
    private DataBaseService dataBaseService;

    /**
     * 一次性购买多个商品
     * @param userid 用户编码
     * @param cidlist 商品编码
     * @return
     */
    @Transactional
    public int goListShopping(int userid,List<Integer> cidlist){
        for (Integer cid : cidlist){
            dataBaseService.goShopping(userid,cid);
        }
        return 1;
    }
}

现在呢,为了制造演示效果,还是修改库存的实现方法,只是为了在购买第二个商品时,抛出一个异常。

    public int updateStory(int id) {
        //加上这么一个操作,只是为了抛出一个异常
        if (id == 2){
            System.out.println(100/0);
        }
        String sql = "update tb_commodity set stock = stock - 1 where id = ?";
        return jdbcTemplate.update(sql, id);
    }

按道理来说,即使在第二次购买的时候出现问题,发现钱不够了,但是可以购买一个商品的。但是默认的事务传播行为可不允许我们这么干。

如果我们使用默认的事务传播行为,则第二次失败后,第一次购买的商品也会被回滚。

修改传播属性为REQUIRES_NEW,当前事务会被挂起,开启新的事务。

这就是事务的传播行为。

@Service
public class DataBaseService {

    @Autowired
    private DataBaseDao dataBaseDao;

    /**
     * 购物操作
     * @param userid 用户编码,减去该用户账户相对应的购买商品金额
     * @param cid 商品编码,查询该商品的价格,以及购买成功是库存-1
     *
     * 使用propagaion来指定事务的传播行为,默认是REQIORED,表示共用一个事务,即使第一次购买成功,第二次购买失败,但结果还是整个进行回滚
     *
     * 如果指定传播行为是:REQUIRES_NEW ,则当前事务会被挂起,被调用的方法,开启新的事务。
     *            第一购买成功之后就提交了,即使第二次失败了,也和第一次无关
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int goShopping(int userid,int cid){

        //查询商品
        Commodity commodity =  dataBaseDao.selectCommodityByid(cid);

        //减去用户账户金额
        dataBaseDao.updateAccount(userid,commodity.getPrice());

        //减去该商品的库存
        dataBaseDao.updateStory(cid);

        return 1;
    }
}

 

猜你喜欢

转载自blog.csdn.net/weixin_38111957/article/details/83959696
今日推荐