为了账号安全,请及时绑定邮箱和手机立即绑定

SpringBoot事务隔离等级和传播行为的那些事儿

Spring定义了七种传播行为:
图片描述

一、开启事物管理

//import org.springframework.transaction.annotation.EnableTransactionManagement;
`@SpringBootApplication

@EnableTransactionManagement //显示开启事物管理,springboot默认已经开启事物管理,可不用显示的注解
public class Application extends SpringBootServletInitializer {

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(Application.class);
}

public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}

}`
二、配置事物

在需要事物的类或方法上使用**@Transactional**(import org.springframework.transaction.annotation.Transactional)

1、isolation 隔离级别(Springboot默认值为Isolation.DEFAULT)

用法:
`~~~
@Transactional(isolation=Isolation.DEFAULT)
public void test() {

}

枚举值(org.springframework.transaction.annotation):
`public enum Isolation {
    DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
    READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
    READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
    REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
    SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
}`
`DEFAULT` :默认值,表示使用底层数据库的默认隔离级别。大部分数据库为`READ_COMMITTED(**MySql默认隔离级别为REPEATABLE**)`   
`READ_UNCOMMITTED` :该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。   
`READ_COMMITTED` :该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。   
`REPEATABLE_READ` :该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。   
`SERIALIZABLE` :所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。   
**通过使用 `isolation` 属性设置,例如:`@Transactional(isolation = Isolation.DEFAULT)/2.`**

**2、事物传播行为 propagation(springboot默认值为Propagation.REQUIRED)**

用法:
`~~~
@Transactional(propagation=Propagation.REQUIRED)
public void test() {
        
}
~~~`
枚举值(org.springframework.transaction.annotation.Propagation):
public enum Propagation {

    REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

    SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

    MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

    REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

    NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

    NEVER(TransactionDefinition.PROPAGATION_NEVER),

    NESTED(TransactionDefinition.PROPAGATION_NESTED);

}
`REQUIRED` :如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。   
`SUPPORTS` :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。   
`MANDATORY` :如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。   
`REQUIRES_NEW` :创建一个新的事务,如果当前存在事务,则把当前事务挂起。   
`NOT_SUPPORTED` :以非事务方式运行,如果当前存在事务,则把当前事务挂起。   
`NEVER` :以非事务方式运行,如果当前存在事务,则抛出异常。   
`NESTED` :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 `REQUIRED` 。   
指定方法:通过使用 `propagation` 属性设置,例如:`@Transactional(propagation = Propagation.REQUIRED)`

**3、readOnly=true只读,不能更新,删除**
`~~~
@Transactional(readOnly=true) 
~~~`
**三、常见坑点**

1、遇到异常检测不回滚,原因:默认RuntimeException级别才回滚,如果是Eexception级别的异常需要手动添加.
`~~~
@Transactional(rollbackFor=Exception.class)
~~~`
2、捕捉异常后事物不生效,原因:捕捉处理了异常导致框架无法感知异常,自然就无法回滚了。
`@Transactional(rollbackFor=Exception.class)
public void test() {
     try {
          //业务代码
     } catch (Exception e) {
         // TODO: handle exception
     }
   //主动捕捉异常导致框架无法捕获,从而导致事物失效
 }`
**建议:若非实际业务要求,则在业务层统一抛出异常,然后在控制层统一处理**

最后

欢迎大家评论区一起交流,相互提升;整理资料不易,如果喜欢文章记得点个赞哈,感谢大家支持!!!
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消