Spring事务中的@Transactional注解中的参数说明

目录

注解声明        

propagation (事务传播行为)

REQUIRED

        外部没有事务则创建当前事务

        外部有事务则合并(加入)事务​编辑

REQUIRES_NEW

        外部没有事务则创建一个事务 

        外部有事务则将外部事务挂起,内部影响外部,外部不影响内部

SUPPORTS

        外部没有事务则以普通方法执行​编辑

        外部有事务则加入当前事务执行

NOT_SUPPORTED

        外部没有事务则以普通方法执行

        外部有事务则挂起外部事务,内部还是以普通方法执行,内部如果发生了报错也不会影响到外部的事务

MANDATORY

        外部没有事务则抛出异常

        外部有事务则加入当前事务执行

NEVER

        外部没有事务则以普通方法执行

        外部有事务则抛出异常

NESTED

        外部没有事务就创建一个内部的事务

        外部有事务则嵌套在外部事务中 , 外部影响内部,内部不影响外部

场景题

isolation(事务隔离级别)

并发事务引起的问题

脏读(Dirty reads)

不可重复读(Nonrepeatable read)

幻读(Phantom read)

不可重复读与幻读的区别

隔离级别

timeout

readOnly

rollbackFor 和 noRollbackFor

事务失效的场景


注解声明        

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";
	
    //传播行为
    Propagation propagation() default Propagation.REQUIRED;
	
    //隔离级别
    Isolation isolation() default Isolation.DEFAULT;
	
    //超时级别
    int timeout() default -1;

    //是否只读
    boolean readOnly() default false;

    Class<? extends Throwable>[] rollbackFor() default {};

    String[] rollbackForClassName() default {};

    Class<? extends Throwable>[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};
}

propagation (事务传播行为)

        Spring中的事务传播机制用于控制多个事务方法相互调用时事务的行为,复杂的业务场景中,多个事务方法之间的调用可能会导致事务的不一致,比如数据丢失,重复提交等问题,使用事务传播机制可以避免这些问题的发生,保证事务的一致性和完整性

Spring的事务规定了7中事务的传播级别,默认的传播机制是REQUIRED

传播行为含义
REQUIRED (0)如果不存在事务则开启一个事务,如果存在事务则加入之前的事务,保证总是会有一个事务在执行
REQUIRES_NEW (3)每次执行都新开一个事务,如果当前存在事务,则把当前事务挂起
SUPPORTS (1)有事务就加入事务,没有则普通执行
NOT_SUPPORTED (4)有事务则暂停该事务,没有则普通执行
MANDATORY (2)强制有事务,没有事务则报异常
NEVER (5)有事务则报异常
NESTED (6)如果之前有事务,则创建嵌套事务,嵌套事务回滚不影响父事务,反之父事务则影响嵌套事务

     PS : 下面说的“外部”指的A方法中调B方法,那A方法就是外部方法,B是内部方法

REQUIRED

        外部没有事务则创建当前事务

        外部有事务则合并(加入)事务

REQUIRES_NEW

        外部没有事务则创建一个事务 

                只是内部的一个事务,不包括外部的

        外部有事务则将外部事务挂起,内部影响外部,外部不影响内部

                比如两个事务,A调B,挂起A事务,执行B事务,B事务提交或回滚后,恢复A事务执行

SUPPORTS

        外部没有事务则以普通方法执行

        外部有事务则加入当前事务执行

NOT_SUPPORTED

        外部没有事务则以普通方法执行

        外部有事务则挂起外部事务,内部还是以普通方法执行,内部如果发生了报错也不会影响到外部的事务

MANDATORY

        外部没有事务则抛出异常

        外部有事务则加入当前事务执行

NEVER

        外部没有事务则以普通方法执行

        外部有事务则抛出异常

NESTED

        外部没有事务就创建一个内部的事务

        

        外部有事务则嵌套在外部事务中 , 外部影响内部,内部不影响外部

        

PS : 这里需要注意下REQUIRES_NEW和NESTED的区别,正好是反过来了

REQUIRES_NEW : 内部影响外部,外部不影响内部

NESTED :内部不影响外部,外部影响内部

场景题

        问:一个长的事务方法a,在读写分离的情况下,里面即有读库操作,也有写库的操作,再调用个读库方法b,方法该用什么传播机制呢?

这种情况,读方法如果是最后一步,直接not_supported就行了,避免读报错导致数据回滚,如果是中间步骤,最好还是required,因为异常失败需要回滚一下。

例如:A B C三个操作,C就是最后一步,B就是中间步骤。

如果一个读操作在中间(如B操作)失败了,那么就需要让A做回滚,因为C还没执行,所以A必须回滚才能保证一致性。

场景题来源:程序员hollis面试题库中

isolation(事务隔离级别)

        事务的隔离级别定义了一个事务可能受其他并发事务影响的程度。

并发事务引起的问题

        在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务。并发虽然是必须的,但可能会导致以下问题:

脏读(Dirty reads)

        脏读发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。

不可重复读(Nonrepeatable read)

        不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间进行了更新。

幻读(Phantom read)

        幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录。

不可重复读与幻读的区别

不可重复读的重点是修改 :

        同样的条件, 你读取过的数据, 再次读取出来发现值不一样了

例如:在事务1中,Mary 读取了自己的工资为1000,操作并没有完成

  con1 = getConnection();  
  select salary from employee empId ="Mary";  

在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务.

  con2 = getConnection();  
  update employee set salary = 2000;  
  con2.commit();  

在事务1中,Mary 再次读取自己的工资时,工资变为了2000

  //con1  
  select salary from employee empId ="Mary"; 

在一个事务中前后两次读取的结果并不一致,导致了不可重复读。

幻读的重点在于新增或删除

        同样的条件, 第1次和第2次读出来的记录数不一样

例如:目前工资为1000的员工有10人。事务1,读取所有工资为1000的员工。

 con1 = getConnection();  
 Select * from employee where salary = 1000; 

共读取10条记录

这时另一个事务向employee表插入了一条员工记录,工资也为1000

 con2 = getConnection();  
 Insert into employee(empId,salary) values("Lili",1000);  
 con2.commit();  

事务1再次读取所有工资为1000的员工

  //con1  
  select * from employee where salary =1000;  

共读取到了11条记录,这就产生了幻像读。

从总的结果来看, 似乎不可重复读和幻读都表现为两次读取的结果不一致。

但如果你从控制的角度来看, 两者的区别就比较大。

对于前者, 只需要锁住满足条件的记录。 对于后者, 要锁住满足条件及其相近的记录。

隔离级别

隔离级别含义
ISOLATION_DEFAULT (-1)默认,使用后端数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED (1)读未提交,最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
ISOLATION_READ_COMMITTED (2)读已提交,允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
ISOLATION_REPEATABLE_READ (4)可重复读,对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
ISOLATION_SERIALIZABLE (8)串行化的,最高的隔离级别,完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读,也是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的数据库表来实现的

PS : 隔离级别越高,数据越安全,并发性能越差

timeout

        指定事务超时时间,单位为秒。如果事务执行时间超过设定的超时时间,将回滚事务。

@Transactional(timeout = 30)
public void methodWithTimeout() {
    // ...
}

readOnly

        指定事务是否为只读,默认值为 false。如果设置为 true,表示只读事务,不允许有写操作。

@Transactional(readOnly = true)
public void readOnlyMethod() {
    // ...
}

rollbackFor 和 noRollbackFor

        指定在哪些异常情况下回滚事务或不回滚事务。

@Transactional(rollbackFor = CustomException.class)
public void methodWithRollbackForException() {
    // ...
}

@Transactional(noRollbackFor = AnotherException.class)
public void methodWithNoRollbackForException() {
    // ...
}

事务失效的场景

        Spring中事务的失效场景-CSDN博客

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
@Transactional注解Spring框架常用的事务管理注解,它可以被应用到类或方法上。当它被应用到类上时,它表示所有的方法都将被事务管理;当它被应用到方法上时,它表示该方法将被事务管理。 @Transactional注解可以接受一些参数,包括: 1. propagation:事务传播行为,默认是Propagation.REQUIRED。 2. isolation:事务隔离级别,默认是Isolation.DEFAULT。 3. timeout:事务超时时间,默认是-1,表示使用数据库默认超时时间。 4. readOnly:是否为只读事务,默认是false。 5. rollbackFor:指定哪些异常需要回滚事务。 6. noRollbackFor:指定哪些异常不需要回滚事务。 下面是一些常见的事务传播行为: 1. REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务,加入到这个事务。 2. REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。 3. SUPPORTS:支持当前事务,如果当前存在事务,就加入到这个事务,如果当前不存在事务,就以非事务状态执行。 4. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 5. MANDATORY:支持当前事务,如果当前不存在事务,就抛出异常。 6. NEVER:以非事务方式执行操作,如果当前存在事务,就抛出异常。 7. NESTED:如果当前存在事务,则在嵌套事务内执行,如果当前没有事务,则新建一个事务。嵌套事务是独立于父事务的,它有自己的提交和回滚。如果嵌套事务内发生异常,只会回滚当前事务的操作,而不会回滚父事务的操作。 总的来说,@Transactional注解可以让我们更方便地管理事务,避免手动处理事务的繁琐过程。但是,我们需要谨慎使用它,特别是在复杂的应用场景,需要仔细考虑事务传播行为和隔离级别等参数

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值