手记

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
     }
   //主动捕捉异常导致框架无法捕获,从而导致事物失效
 }`
**建议:若非实际业务要求,则在业务层统一抛出异常,然后在控制层统一处理**

最后

欢迎大家评论区一起交流,相互提升;整理资料不易,如果喜欢文章记得点个赞哈,感谢大家支持!!!
0人推荐
随时随地看视频
慕课网APP