对事务的学习总体来讲应该蕴含以下几个局部:
- 事务的概念:数据库层面的,简略理解什么是事务,以及隔离级别、事务的提交、回滚、保留点等基本概念。
- 动静代理以及Spring AOP,是Spring框架实现事务管制的底层技术根底。
- Spring框架事务的实现形式。
- Spring框架事务实现的底层原理。
能够循序渐进逐渐学习,也能够独自学习其中某一部分,然而只有全副彻底把握了,能力对事务有一个全局的理解。
一般来讲,程序员实现事务管制有两种抉择:编程式事务、申明式事务。从代码编写的角度讲,编程式事务太麻烦,当初用的很少了,20年前的程序员绝大部分用的都是编程式事务,十分麻烦,须要本人获取连贯、开启事务、提交或回滚事务、敞开连贯等。
申明式事务是基于AOP实现的,当初JAVA世界的绝大部分我的项目都是基于Spring框架实现的,Spring框架、尤其是Springboot框架对事务管理的反对十分敌对,应用非常简单。
Spring框架实现事务管制其实非常简单,次要的注解只有两个:
- @EnableTransactionManagement
- @Transactional
@EnableTransactionManagement注解是负责在配置类中关上Spring的事务管理性能,@Transactional是具体负责开启及实现事务管制的。从利用层面来讲,@Transactional是学习的重点。
@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documentedpublic @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的重要属性包含:
- 事务流传机制Propagation
- 隔离级别isolation
- 期待超时工夫timeout
- 回滚条件rollbackFor
- 不回滚条件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的默认流传机制。
比方事务管制的经典案例银行转账交易:转账交易由转出和转入两局部性能组成,如果咱们依照如下形式实现的话:
@Transactionalpublic 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即可。