• 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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    修改 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("用户购买成功~");
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    创建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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试 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--------");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    故意写错

    img

    修 改 GoodsService.java ,

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

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

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

    😄总结

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

    😘Spring 声明式事务系列

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

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

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

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

  • 相关阅读:
    Python 机器学习入门之K近邻算法
    程序设计题 2:双11抢宝计划
    Windows cmd/powershell 管道过滤命令: find
    拼搏一周,刷完了阿里P8整理的这3份1000道Java高频面试题笔记,拿到了阿里P7职位
    vue+mapbox通过地图图层属性进行区划颜色填充(工作笔记,不能直接复制使用,需要自行调整部分代码)
    Antv/G2 分组柱状图+折线图双轴图表
    【红日靶场】vulnstack1-完整渗透过程
    利用nicegui开发ai工具示例
    数据结构——双向链表
    深入理解netty
  • 原文地址:https://blog.csdn.net/apple_67445472/article/details/132307738