• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

SpringBoot(15) 事务@Transactional整合

武飞扬头像
邱秋Elena
帮助3


一、Spring事务介绍

Spring事务不仅可以通过使用事务注解@Transactional,同时支持编程式使用事务,但是这种模式不常用。这里详细介绍Spring事务。

1.事务隔离级别

使用事务其实只用到了一个注解@Transactional,这就是Spring的注解式事务。事务隔离级别是指若干个事务并发时的隔离程度,Spring声明事务可以通过isolation属性来设置Spring的事务隔离级别。其中提供了以下5种事务隔离级别。
@Transactional(isolation=IsolationDEFAULT):默认的事务隔离级别,即使用数据库的事务隔离级别。

数据库一共有如下四种隔离级别:

  1. Read uncommitted 读未提交

在该级别下,一个事务对一行数据修改的过程中,不允许另一个事务对该行数据进行修改,但允许另一个事务对该行数据读。
因此本级别下,不会出现更新丢失,但会出现脏读、不可重复读。

  1. Read committed 读已提交

在该级别下,未提交的写事务不允许其他事务访问该行,因此不会出现脏读;但是读取数据的事务允许其他事务的访问该行数据,因此会出现不可重复读的情况。

  1. Repeatable read 可重复读

在该级别下,读事务禁止写事务,但允许读事务,因此不会出现同一事务两次读到不同的数据的情况(不可重复读),且写事务禁止其他一切事务。

  1. Serializable 序列化

该级别要求所有事务都必须串行执行,因此能避免一切因并发引起的问题,但效率很低。

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为ReadCommitted。它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

学新通

2.事务传播行为

事务传播行为是指如果多个事务同时存在,Spring 就会处理这些事务的行为。事务传播行为分为如下几种。
学新通

可以看出1、2、3为一组,都表现对当前事务的支持,不同的在于当前不存在事务的处理方式;4、5、6为一组,都表现对当前事务的不支持,不同的在于当前有事务的处理方式。然后7单独一组。

举个小栗子,比如有一个service中有方法A,调用了方法B,方法B的传播行为是PROPAGATION_REQUIRED,那么如果方法A的传播行为也是PROPAGATION_REQUIRED,方法A运行的时候,开启了一个事务,方法A中执行到方法B的时候,察觉到当前已经有事务了,方法B就不会再创建新的事务,直接包含在方法A的事务当中。

  1. PROPAGATIONREQUIRED:如果当前存在事务,就加入该事务;如果当前没有事务,就创
    建一个新的事务,这是Spring默认的事务传播行为。
  2. PROPAGATION REOUIRES NEW:创建一个新的事务,如果当前存在事务,就把当前事务
    挂起。新建事务和被挂起的事务没有任何关系,是两个独立的事务。外层事务回滚失败时, 不能回滚内层事务执行结果,内外层事务不能相互干扰。
  3. PROPAGATION SUPPORTS:如果当前存在事务,就加入该事务;如果当前没有事务,就以非事务的方式继续运行。
  4. PROPAGATION NOT SUPPORTED:以非事务方式运行,如果当前存在事务,就把当前事务挂起。
  5. PROPAGATION NEVER:以非事务方式运行,如果当前存在事务,就抛出异常。
  6. PROPAGATION MANDATORY:如果当前存在事务,就加入该事务;如果当前没有事务,就抛出异常。
  7. PROPAGATIONNESTED:如果当前存在事务,就创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,该取值就等价于PROPAGATIONREQUIRED

3.声明式事务属性

Spring 事务不只拥有事务隔离级别和事务传播行为,另外还包含很多属性供开发者使用,分别说明如下。

ovalue:存放String类型的值,主要用来指定不同的事务管理器,满足在同一个系统中存在不同的事务管理器。比如在Spring容器中声明了多种事务管理器,然后开发者可以根据设置指定需要使用的事务管理器。通常一个系统需要访问多个数据库的场景下,就会设置多个事务管理器,然后进行不同的选择。

transactionManager:与value类似,也是用来选择事务管理器。
propagation:事务传播行为,默认值是PropagationREQUIRED。
isolation:事务的隔离级别,默认值是IsolationDEFAULT
timeout:事务的超时时间,默认值是-1,如果超过了设置的时间还没有执行完成,就会自动回滚当前事务。
readOnly:当前事务是不是只读事务,默认值是false。通常可以设置读取数据的事务的属性值为true。
rollbackFor:可以设置触发事务的指定异常,允许指定多个类型的异常。
noRollbackFor:与rollbackFor相反,可以设置不触发事务的指定异常,允许指定多个类型的异常。

4.事务回滚规则

Spring的事务回滚通常是根据当前事务抛出异常的时候,Spring事务管理器捕捉到未经处理的异常,然后根据规则来决定当前事务是否回滚。如果捕获的异常正好是设置notRollbackFor属性的异常,那么将不会被捕获。在默认配置下,Spring只有捕获运行时异常(RuntimeException)的子类时才会进行回滚。

5.@Transactional使用注意事项

在使用@Transactional注解的时候,需要注意一些情况:

  • @Transactional需要在类的上方使用,而不是在接口的上方使用,如果在接口上使用,事务就会失效。
  • @Transactional只能在public修饰的方法上,如果使用在private或protected修饰的方法上,事务就会无效。
  • @Transactional 尽量不在类的上方使用,因为这样会对类内的全部方法使用事务,如果对查询方法使用事务,就可能会影响效率。

二、编码实现

    @GetMapping("/insert")
    @Transactional(rollbackFor = Exception.class)
    public String insert(User user) {
        testService.insert(user);
        user.setAge(user.getAge()  );
        testService.update(user);
        return user.getName();
    }

抛出异常后数据库并未进行修改;

@Transactional 异常不回滚几种原因:

  1. @Transactional是基于AOP动态代理做的,所以方法必须是public;其他的修饰符不生效。
  2. Spring事务控制器在catch里面做了判断只有RuntimeException或者错误信息的时候才会回滚,故不是RuntimeException的异常不会回滚。
  3. Transactional的异常控制,默认是Check Exception 不回滚,unCheck Exception回滚
    如果配置了rollbackFor 和 noRollbackFor 且两个都是用同样的异常,那么遇到该异常,还是回滚
    rollbackFor 和noRollbackFor 配置也许不会含盖所有异常,对于遗漏的按照Check Exception
    不回滚,unCheck Exception回滚。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfhbbjk
系列文章
更多 icon
同类精品
更多 icon
继续加载