Spring事务和事务传播机制

Spring事务和事务传播机制

1.什么是事务

指的是一系列的操作或步骤,这些操作要么全部完成、要么全部不完成。对于数据库而言、一系列操作数据库的SQL语句就是一个事务,这些SQL语句只能同时执行成功或失败。

事务的特性:ACID

  1. 原子性:事务是不可分割的单位,一个事务中所有的操作要么成功、要么失败。
  2. 一致性:事务提交前后符合我们预设的规则,数据的完整性不能被破坏。(例如A有100元,B有100元,A向B转账了50元,A现在50元,B现在150元,它们总和是一致的)
  3. 隔离性:允许多个事务同时对数据进行读写的能力,隔离性可以防止多个事务交叉执行从而导致数据不一致的问题。
  4. 持久性:事务一旦被提交,对数据的修改就是永久的。

没有事务的隔离性可能会有什么问题?

  1. 脏读:事务A读取到了事务B还未提交的数据,但是B事务又进行了回滚,导致A事务读取到的数据是错误的。
  2. 不可重复读:一个事务两次查询的结果不同,在两次查询的过程中,有一个事务将数据修改了。
  3. 幻读:一个事务两次查询的结果集不同,在两次查询的过程中,有一个事务新增了一部分数据。

事务的隔离级别:

  1. 读未提交:一个事务可以看到还未被提交的事务数据。
  2. 读已提交:一个事务只能看到已经提交的事务数据,因此可以解决脏读问题。
  3. 可重复读:一个事务可以查看到其他事务已经提交的修改记录,看不到其他事务对已有记录的更新,因此每次查询的结果都是相同的,可以解决不可重复读的问题。
  4. 序列化:事务最高隔离级别,他会强制将事务进行排序,因此事务就不会发生冲突,从而解决了脏读、不可重复读、幻读问题。

Spring事务的分类:

  1. 编程式事务(手动的进行创建、提交/回滚事务)
  2. 声明式事务(使用注解自动的实现事务的创建、提交/回滚)。

事务的操作流程:

  1. 开启事务(start transaction)
  2. commit(提交事务)
  3. rollback(回滚事务)

2.Spring编程式事务的实现

DataSourceTransactionManager是一个Spring的事务管理器,它使用数据源来管理事务。这个事务管理器在事务开始时,会得到一个数据库连接,允许事务的创建、提交/回滚。

TransactionDefinition 用于定义事务的特性,创建一个事务。


@SpringBootTest
class UserMapperTest {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private DataSourceTransactionManager transactionManager;

    @Autowired
    private TransactionDefinition definition;

    @Test
    void addUser() {
        //开启事务
        TransactionStatus transactionStatus = transactionManager.getTransaction(definition);
        //执行操作
        int result = userMapper.addUser("mary","123",null);
        System.out.println(result);
        //提交事务
        transactionManager.commit(transactionStatus);
        //回滚事务
        //transactionManager.rollback(transactionStatus);
    }

}

3.声明式事务

@Transactional:

  1. 用于方法:只能应用再public方法上,表示进入方法时自动开启事务、结束方法时自动提交事务(方法内没有产生异常才会提交)
  2. 用于类:表示执行该类中的任一public方法,都会开启和提交事务。
public class UserController {
    @Autowired
    private UserMapper userMapper;

    @Transactional(rollbackFor = Exception.class)
    @RequestMapping("/add")
    public int addUser(String username, String password, String avatar){
        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){
            return -1;
        }

        int result = userMapper.addUser(username, password, avatar);

        try{
            //捕获可能产生的异常...
        }catch (Exception e){
            //手动进行回滚
            log.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return -2;
        }

        return result;
    }
}

当方法对外抛出了异常,如果程序没有处理且抛出的异常和声明rollbackfor参数匹配,Spring会将这个事务标记为回滚。事务管理器最终会实现对这个事务的回滚。

@Transactional:注解的参数

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    //当存在多个事务管理器时指定使用哪一个事务管理器
    @AliasFor("transactionManager")
    String value() default "";

    //当存在多个事务管理器时指定使用哪一个事务管理器
    @AliasFor("value")
    String transactionManager() default "";

    String[] label() default {};
	
    //事务的传播行为
    Propagation propagation() default Propagation.REQUIRED;

    //事务的隔离级别
    Isolation isolation() default Isolation.DEFAULT;

    //事务的超时时间,超时会自动进行回滚,默认值为-1表示没有超时时间,
    int timeout() default -1;

    String timeoutString() default "";

    //指定事务是否为只读事务
    boolean readOnly() default false;

    //用于指定能够出发事务回滚的异常类型,可以指定多个异常类型
    Class<? extends Throwable>[] rollbackFor() default {};

    //用于指定能够出发事务回滚的异常类型,可以指定多个异常类型
    String[] rollbackForClassName() default {};

    //抛出指定的异常类型,不回滚事务
    Class<? extends Throwable>[] noRollbackFor() default {};

    //抛出指定的异常类型,不回滚事务
    String[] noRollbackForClassName() default {};
}

4.Spring事务的隔离级别

  1. Isolation.DEFAULT:以连接的数据库的事务隔离级别为主。
  2. Isolation.READ_UNCOMMITTED:读未提交
  3. Isolation.READ_COMMITTED:读已提交
  4. Isolation.REPEATABLE_READ:可重复读
  5. Isolation.SERIALIZABLE:串行化

在Spring的声明式事务中,只需要将其配置在@Transaction注解中。

5.Spring事务的传播机制

主要解决一个多个事务相互调用时,事务是如何在这些方法间进行传播的以及它们之间的影响。

举一个例子:将购物车的商品支付购买

在这里插入图片描述

5.1事务的传播机制

  1. REQUIRED:默认的事务传播级别,表示如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务。
  2. SUPPORTS:如何当前存在事务,则加入该事务,如果当前没有事务则以非事务的方式运行。
  3. MANDATORY:如果当前存在事务,则加入该事务,如果当前没有事务,则抛出异常。
  4. REQUIRE_NEW:如果当前存在事务,则把当前事务挂起,创建一个新事务,如果当前不存在事务,创建一个新事务。
  5. NOT_SUPPORTED:如果当前存在存在事务,则把当前事务挂起,以非事务方式运行。
  6. NEVER:如果当前存在事务,则抛出异常,不存在事务,以非事务方式运行。
  7. NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套来运行,如果当前没有事务,则和REQUIRED相同。

加入事务和嵌套事务:

  1. 加入事务可以理解为将当前事务的sql语句添加到上一个事务中。要么所有的SQL语句全部执行成功,要么都不执行。
    非事务方式运行。
  2. NEVER:如果当前存在事务,则抛出异常,不存在事务,以非事务方式运行。
  3. NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套来运行,如果当前没有事务,则和REQUIRED相同。

加入事务和嵌套事务:

  1. 加入事务可以理解为将当前事务的sql语句添加到上一个事务中。要么所有的SQL语句全部执行成功,要么都不执行。
  2. 嵌套事务可以理解为将在当前事务内部再开启一个事务,如果进行回滚只能影响到自己,而不会影响到嵌套外的事务。但是嵌套事务和外部事务时一起提交的。也就是说外部事务可以影响内部事务的提交。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

南 栀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值