对事务的学习总体来讲应该蕴含以下几个局部:
- 事务的概念:数据库层面的,简略理解什么是事务,以及隔离级别、事务的提交、回滚、保留点等基本概念。
- 动静代理以及 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
@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 的重要属性包含:
- 事务流传机制 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 的默认流传机制。
比方事务管制的经典案例银行转账交易:转账交易由转出和转入两局部性能组成,如果咱们依照如下形式实现的话:
@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 即可。