设为首页 加入收藏

TOP

day16-声明式事务-02(一)
2023-07-25 21:43:57 】 浏览:94
Tags:day16- 明式事 -02

声明式事务-02

3.事务的传播机制

事务的传播机制说明:

  1. 当有多个事务处理并存时,如何控制?

  2. 比如用户去购买两次商品(使用不同的方法),每个方法都是一个事务,那么如何控制呢?

    image-20230131224401793

    也就是说,某个方法本身是一个事务,然后该方法中又调用了其他一些方法,这些方法也是被@Transactional 修饰的,同样是事务。

  3. 问题在于:里层方法的事务是被外层方法事务管理?还是它本身作为一个独立的事务呢?这就涉及到事务的传播机制问题。

3.1事务传播机制种类

  • 事务传播的属性 / 种类:
传播属性 说明
REQUIRED (默认)如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事务,并且在自己的事务内运行
REQUIRES_NEW 当前的方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起
SUPPORTS 如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中
NOT_SUPPORTED 当前的方法不应该运行在事务中,如果有运行的事务,将它挂起
MANDATORY 当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常
NEVER 当前的方法不应该运行在事务中,如果有运行的事务,就抛出异常
NESTED 如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则,就启动一个新的事务,并在它自己的事务内运行

常用的只有前面两种:(1)REQUIRED,(2)REQUIRES_NEWREQUIRES_NEW


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

重点分析 REQUIRED 和 REQUIRES_NEW 两种事务传播属性,其他知道即可。

如下,有一个multiTxTest()方法,该方法中又有f1(),f2() 方法。所有方法都分别开启了声明式事务。

@Transactional
public void multiTxTest() {
    f1(); //含事务
    
    f2(); //含事务
}
  1. 如果f1(),f2() 的传播属性都是 REQUIRED,那么它们实际上是被Tx()的事务统一管理的。所有方法是一个整体,只要有一个方法的事务错误,那么两个方法都不会执行成功。

    image-20230201182508199
  2. 如果f1(),f2() 的传播属性都是 REQUIRES_NEW,那么f1(),f2()实际上是独立的事务,不会受到Tx()事务的影响。如果f1()错误,不会影响到f2(),反之亦然。

    image-20230201182408268

3.2应用实例

需求说明:

  1. 用户要去购买两次商品(使用不同的方法),每个方法都是一个事务,那么如何控制呢?
  2. 看一个具体的案例(用 required 和 requires_new 测试)

代码实现

1.GoodsDao.java

分别有6个方法:queryPriceById,queryPriceById2,updateBalance,updateBalance2,updateAmount,updateAmount2。

package com.li.tx.dao;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;

/**
 * @author 李
 * @version 1.0
 */
@Repository //将GoodsDao对象 注入到 spring 容器
public class GoodsDao {
    @Resource
    private JdbcTemplate jdbcTemplate;

    /**
     * 根据商品id,查询对应的商品价格
     * @param id
     * @return
     */
    public Float queryPriceById(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 updateBalance(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 updateAmount(Integer goods_id, int amount) {
        String sql = "update goods_amount set goods_num=goods_num-? where goods_id=? ";
        jdbcTemplate.update(sql, amount, goods_id);
    }

    //和queryPriceById的操作是一样的
    public Float queryPriceById2(Integer id) {
        String sql = "select price from goods where goods_id = ?";
        Float price = jdbcTemplate.queryForObject(sql, Float.class, id);
        return price;
    }

    //和updateBalance的操作是一样的
    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);
    }

    //和updateAmount的操作是一样的
    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);
    }
}

2.GoodsService.java,分别有两个方法buyGoodsByTx,buyGoodsByTx02

package com.li.tx.service;

import com.li.tx.dao.GoodsDao;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactiona
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇分享会上狂吹MySQL的4大索引结构.. 下一篇CentOS中docker的使用

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目