Spring事务传播机制

对事务的学习总体来讲应该包含以下几个部分:

  1. 事务的概念:数据库层面的,简单了解什么是事务,以及隔离级别、事务的提交、回滚、保存点等基本概念。
  2. 动态代理以及Spring AOP,是Spring框架实现事务控制的底层技术基础。
  3. Spring框架事务的实现方式。
  4. Spring框架事务实现的底层原理。

可以循序渐进逐步学习,也可以单独学习其中某一部分,但是只有全部彻底掌握了,才能对事务有一个全局的了解。

一般来讲,程序员实现事务控制有两种选择:编程式事务、声明式事务。从代码编写的角度讲,编程式事务太麻烦,现在用的很少了,20年前的程序员绝大部分用的都是编程式事务,非常麻烦,需要自己获取连接、开启事务、提交或回滚事务、关闭连接等。

声明式事务是基于AOP实现的,现在JAVA世界的绝大部分项目都是基于Spring框架实现的,Spring框架、尤其是Springboot框架对事务管理的支持非常友好,使用非常简单。

Spring框架实现事务控制其实非常简单,主要的注解只有两个:

  1. @EnableTransactionManagement
  2. @Transactional

@EnableTransactionManagement注解是负责在配置类中打开Spring的事务管理功能,@Transactional是具体负责开启及实现事务控制的。从应用层面来讲,@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;

    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 {};
}

@Transactional的重要属性包括:

  1. 事务传播机制Propagation
  2. 隔离级别isolation
  3. 等待超时时间timeout
  4. 回滚条件rollbackFor
  5. 不回滚条件noRollbackFor

其实Spring事务管理是重度依赖于数据库底层的支持的,尤其是类似隔离级别、等待超时时间等概念,都是直接依赖于数据库底层去实现的,Spring事务管理其实什么都不需要干,只需要把配置好的属性传递给数据库连接、交给数据库去完成即可。

而事务传播机制Propagation与其他特性不同,是spring框架事务管理功能的重头戏。事务传播机制负责控制不同事务发生的时候,上层事务与下层事务之间的关系。

Spring定义了以下7种事务传播机制:

REQUIRED

Support a current transaction, create a new one if none exists. Analogous to EJB transaction attribute of the same name.
This is the default setting of a transaction annotation.

需要启用事务,当前不存在事务的话,就创建一个新事务,如果存在事务的话,则加入。

这是Spring的默认传播机制。

比如事务控制的经典案例银行转账交易:转账交易由转出和转入两部分功能组成,如果我们按照如下方式实现的话:

@Transactional
public void transfer(Acct acct1,Acct acct2){
    withdrawl(acct2);
     deposit(acct1);
}
@Transactional(propagation=Propagation.REQUIRED)
public void deposit(){
    acct1.deposit();
}
@Transactional(propagation=Propagation.REQUIRED)
public void withdrawl(){
   acct2.wiwithdrawl();
}

转出和转入方法就必须要启用事务、事务传播机制可以设置为REQUIRED,那么在转出交易调用的时候,因为transfer方法已经开启了一个事务,所以,转出方法withdrawl不再开启新事物、而是使用已经存在的事务,同样,转入方法deposit也使用该事务。这样,转出交易和转入交易就被包含在了同一个事务中,能够实现要么全部成功、要么全部失败的交易目标。

SUPPORTS

Support a current transaction, execute non-transactionally if none exists. Analogous to EJB transaction attribute of the same name.
Note: For transaction managers with transaction synchronization, SUPPORTS is slightly different from no transaction at all, as it defines a transaction scope that synchronization will apply for. As a consequence, the same resources (JDBC Connection, Hibernate Session, etc) will be shared for the entire specified scope. Note that this depends on the actual synchronization configuration of the transaction manager.
See Also:
org.springframework.transaction.support.AbstractPlatformTransactionManager.setTransactionSynchronization

当前如果已经开启了事务的话,则加入,如果没有已经开启的事务的话,也无所谓,当前方法不开启事务。

MANDATORY

Support a current transaction, throw an exception if none exists. Analogous to EJB transaction attribute of the same name.

当前方法被调用的时候必须有事务,如果没有已经开启的事务的话,就不干,抛异常。

上面银行转账交易,也可以采用MANDATORY。

REQUIRES_NEW

Create a new transaction, and suspend the current transaction if one exists. Analogous to the EJB transaction attribute of the same name.
NOTE: Actual transaction suspension will not work out-of-the-box on all transaction managers. This in particular applies to org.springframework.transaction.jta.JtaTransactionManager, which requires the javax.transaction.TransactionManager to be made available to it (which is server-specific in standard Java EE).
See Also:
org.springframework.transaction.jta.JtaTransactionManager.setTransactionManager

启用新事务,如果当前已经存在一个事务的话,则挂起该事务。

被挂起的事务不会受到开启的新事务执行结果的影响,无论新事务被提交还是被回滚。

NOT_SUPPORTED

Execute non-transactionally, suspend the current transaction if one exists. Analogous to EJB transaction attribute of the same name.
NOTE: Actual transaction suspension will not work out-of-the-box on all transaction managers. This in particular applies to org.springframework.transaction.jta.JtaTransactionManager, which requires the javax.transaction.TransactionManager to be made available to it (which is server-specific in standard Java EE).
See Also:
org.springframework.transaction.jta.JtaTransactionManager.setTransactionManager

不启用事务,如果当前已经存在一个事务的话则挂起当前事务。

NEVER

Execute non-transactionally, throw an exception if a transaction exists. Analogous to EJB transaction attribute of the same name.

不启用事务,如果当前已经存在一个事务的话就抛出异常。

NESTED

Execute within a nested transaction if a current transaction exists, behave like REQUIRED otherwise. There is no analogous feature in EJB.
Note: Actual creation of a nested transaction will only work on specific transaction managers. Out of the box, this only applies to the JDBC DataSourceTransactionManager. Some JTA providers might support nested transactions as well.
See Also:
org.springframework.jdbc.datasource.DataSourceTransactionManager

嵌套事务,如果当前已经存在一个事务的话,则行为类似于REQUIRED。注意:嵌套事务仅针对特定的事务管理器,需要特定事务管理器的支持,是否生效取决于JDBC数据源的事务管理器。

嵌套事务的实际含义是:如果当前存在一个事务的话,则保存当前事务的savepoint(保存点),并加入事务,如果当前不存在事务的话,就启用一个新事务。

嵌套事务实际使用了数据库的savepoint,需要数据库支持savepoint,如果数据库不支持savepoint,那么这个NESTED也就不会生效。

savepoint的意思对当前事务已经执行的数据库操作记录一个保存点,新方法加入事务后,如果执行成功则一起提交,如果执行失败则只回滚新方法的操作,不回滚保存点以前的数据库操作。

以上Spring提供的7种事务传播机制,我们应该都有所了解。但是,实际应用场景中能用到的,或者用的比较多的,也就REQUIRED、以及REQUIRED_NEW。一般情况下REQUIRED足够满足需要了,有些应用框架需要记录操作日志,审计用,不论操作成功还是失败都需要记录。这种情况下,REQUIRED_NEW即可。

全部评论

相关推荐

10-03 17:08
已编辑
西安电子科技大学 Java
点赞 评论 收藏
分享
真tmd的恶心,1.面试开始先说我讲简历讲得不好,要怎样讲怎样讲,先讲背景,再讲技术,然后再讲提升多少多少,一顿说教。2.接着讲项目,我先把背景讲完,开始讲重点,面试官立即打断说讲一下重点,无语。3.接着聊到了项目的对比学习的正样本采样,说我正样本采样是错的,我解释了十几分钟,还是说我错的,我在上一家实习用这个方法能work,并经过市场的检验,并且是顶会论文的复现,再怎么不对也不可能是错的。4.面试官,说都没说面试结束就退出会议,把面试者晾在会议里面,丝毫不尊重面试者难受的点:1.一开始是讲得不好是欣然接受的,毕竟是学习。2.我按照面试官的要求,先讲背景,再讲技术。当我讲完背景再讲技术的时候(甚至已经开始蹦出了几个技术名词),凭什么打断我说讲重点,是不能听出人家重点开始了?这也能理解,每个人都有犯错,我也没放心上。3.我自己做过的项目,我了解得肯定比他多,他这样贬低我做过的项目,说我的工作是错误的,作为一个技术人员,我是完全不能接受的,因此我就和他解释,但无论怎么解释都说我错。凭什么,作为面试官自己不了解相关技术,别人用这个方式work,凭什么还认为这个方法是错的,不接受面试者的解释。4.这个无可厚非,作为面试官,不打招呼就退出会议,把面试者晾着,本身就是有问题。综上所述,我现在不觉得第一第二点也是我的问题,面试官有很大的问题,就是专门恶心人的,总结面试官说教,不尊重面试者,打击面试者,不接受好的面试者,技术一般的守旧固执分子。有这种人部门有这种人怎么发展啊。最后去查了一下,岗位关闭了。也有可能是招到人了来恶心人的,但是也很cs
牛客20646354...:招黑奴啊,算法工程师一天200?
点赞 评论 收藏
分享
评论
2
8
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务