Spring 声明式事务机制

😀前言
本篇是Spring 声明式事务系列的第二篇介绍了Spring 声明式事务机制

🏠个人主页:尘觉主页
在这里插入图片描述

🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉

在csdn获奖荣誉: 🏆csdn城市之星2名
⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ 💓Java全栈群星计划top前5
⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ 🤗 端午大礼包获得者

💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,感谢大家的观看🥰
如果文章有什么需要改进的地方还请大佬不吝赐教 先在次感谢啦😊

🤩声明式事务机制

😄事务的传播机制

事务的传播机制说明

  1. 当有多个事务处理并存时,如何控制?
  2. 比如用户去购买两次商品(使用不同的方法), 每个方法都是一个事务,那么如何控制呢?
  3. 这个就是事务的传播机制,看一个具体的案例(如图)

img

img

🥰事务传播机制种类

● 事务传播的属性/种类一览图

img

● 事务传播的属性/种类机制分析,

重点分析了 REQUIRED 和 REQUIRED_NEW 两种事务 传播属性, 其它知道即可(看上图)

img

img

● 事务的传播机制的设置方法

img

● REQUIRES_NEW 和 REQUIRED 在处理事务的策略

img

  1. 如果设置为 REQUIRES_NEW

buyGoods2 如果错误,不会影响到 buyGoods()反之亦然,即它们的事务是独立的.

  1. 如果设置为 REQUIRED

buyGoods2 和 buyGoods 是一个整体,只要有方法的事务错误,那么两个方法都不会执行成功.!

😋事务的传播机制-应用实例

● 事务的传播机制需要说明

  1. 比如用户去购买两次商品(使用不同的方法), 每个方法都是一个事务,那么如何控制呢?
    =>这个就是事务的传播机制
  2. 看一个具体的案例(用 required/requires_new 来测试):

修改 GoodsDao.java, 增加方法

public class GoodsDao {
/**
     * 根据商品id,返回对应的价格
     * @param id
     * @return
     */
    public Float queryPriceById2(Integer id) {
        String sql = "SELECT price From goods Where goods_id=?";
        Float price = jdbcTemplate.queryForObject(sql, Float.class, id);
        return price;
    }

    /**
     * 修改用户的余额 [减少用户余额]
     * @param user_id
     * @param money
     */
    public void updateBalance2(Integer user_id, Float money) {
        String sql = "UPDATE user_account SET money=money-? Where user_id=?";
        jdbcTemplate.update(sql, money, user_id);
    }

    /**
     * 修改商品库存 [减少]
     * @param goods_id
     * @param amount
     */
    public void updateAmount2(Integer goods_id, int amount){
        String sql = "UPDATE goods_amount SET goods_num=goods_num-? Where goods_id=?";
        jdbcTemplate.update(sql, amount , goods_id);
    }
}

修改 GoodsService.java 增加 buyGoodsByTx02(), 使用默认的传播机制

注解解读
1. 使用@Transactional 可以进行声明式事务控制
2. 即将标识的方法中的,对数据库的操作作为一个事务管理
3. @Transactional 底层使用的仍然是AOP机制
4. 底层是使用动态代理对象来调用buyGoodsByTx
5. 在执行buyGoodsByTx() 方法 先调用 事务管理器的 doBegin() , 调用 buyGoodsByTx()
如果执行没有发生异常,则调用 事务管理器的 doCommit(), 如果发生异常 调用事务管理器的 doRollback()

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void buyGoodsByTx(int userId, int goodsId, int amount) {


        //输出购买的相关信息
        System.out.println("用户购买信息 userId=" + userId
                + " goodsId=" + goodsId + " 购买数量=" + amount);

        //1.得到商品的价格
        Float price = goodsDao.queryPriceById(userId);
        //2. 减少用户的余额
        goodsDao.updateBalance(userId, price * amount);
        //3. 减少库存量
        goodsDao.updateAmount(goodsId, amount);

        System.out.println("用户购买成功~");

    }

@Transactional
    public void buyGoodsByTx2(int userId, int goodsId, int amount) {


        //输出购买的相关信息
        System.out.println("用户购买信息 userId=" + userId
                + " goodsId=" + goodsId + " 购买数量=" + amount);

        //1.得到商品的价格
        Float price = goodsDao.queryPriceById2(userId);
        //2. 减少用户的余额
        goodsDao.updateBalance2(userId, price * amount);
        //3. 减少库存量
        goodsDao.updateAmount2(goodsId, amount);

        System.out.println("用户购买成功~");

    }

创建MultiplyService类

解读

  1. multiBuyGoodsByTx 这个方法 有两次购买商品操作

  2. buyGoodsByTx 和 buyGoodsByTx2 都是声明式事务

  3. 当前buyGoodsByTx 和 buyGoodsByTx2 使用的传播属性是默认的 REQUIRED [这个含义前面讲过了
    即会当做一个整体事务进行管理 , 比如buyGoodsByTx方法成功,但是buyGoodsByTx2() 失败,会造成 整个事务的回滚 即会回滚buyGoodsByTx

  4. 如果 buyGoodsByTx 和 buyGoodsByTx2 事务传播属性修改成 REQUIRES_NEW
    这时两个方法的事务是独立的,也就是如果 buyGoodsByTx成功 buyGoodsByTx2失败, 不会造成 buyGoodsByTx回滚.

@Service
public class MultiplyService {
    @Resource
    private GoodsService goodsService;


    
    @Transactional
    public void multiBuyGoodsByTx() {

        goodsService.buyGoodsByTx(1, 1, 1);
        goodsService.buyGoodsByTx2(1, 1, 1);
    }
}

测试 TxTest.java,

可以验证:为 REQUIRED buyGoodsByTx 和 buyGoodsByTx02 是整体, 只要有方法的事务错误,那么两个方法都不会执行成功

@Test
public void buyGoodsByMulTxTest() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("tx_ioc.xml");
MultiplyTxService bean = ioc.getBean(MultiplyTxService.class);
bean.multiTxTest();
System.out.println("------ok--------");
}

故意写错

img

修 改 GoodsService.java ,

将 传 播 机 制 改 成 REQUIRES_NEW 可 以 验 证 : 设 置 为 REQUIRES_NEW

buyGoodsByTx 如果错误不会影响到 buyGoodsByTx02()反之亦然,也就 是说它们的事务是独立的

将二个方法的 @Transactional修改为下面的这种形式 完成测试
@Transactional(propagation = Propagation.REQUIRES_NEW)

😄总结

本篇介绍了事务传播机制种类和事务的传播机制-应用实例希望可以帮到大家

😘Spring 声明式事务系列

第一篇–> 什么是Spring 声明式事务详细讲解

😁热门专栏推荐
想学习vue的可以看看这个
java基础合集
数据库合集
redis合集
nginx合集
linux合集
等等等还有许多优秀的合集在主页等着大家的光顾感谢大家的支持

🤔欢迎大家加入我的社区 尘觉社区

文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁
希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尘觉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值