SpringDataJPA+Hibernate框架源码剖析(四)框架整合 之 事务管理器的构建(包括spring的事务机制)
SpringDataJPA+Hibernate框架源码剖析系列文章:
- SpringDataJPA+Hibernate框架源码剖析(一)框架介绍
- SpringDataJPA+Hibernate框架源码剖析(二)框架整合 之 EntityManagerFactory的构建
- SpringDataJPA+Hibernate框架源码剖析(三)框架整合 之 Repository接口实现的生成
- SpringDataJPA+Hibernate框架源码剖析(四)框架整合 之 事务管理器的构建(包括spring的事务机制)
- SpringDataJPA+Hibernate框架源码剖析(五)框架整合 之 SpringBoot整合JPA剖析
- SpringDataJPA+Hibernate框架源码剖析(六)@PersistenceContext和@Autowired注入EntityManager的区别
SpringDataJPA+Hibernate框架整合主要关注三个方面: EntityManagerFactory的构建 、 Repository接口实现的生成 、 事务管理器的构建 。
注:spring是采用注解式配置;为了控制篇幅本系列主要分析JPA和hibernate相关源码,需要配置过程和pom依赖的同学请自行百度。
JPA事务管理器的构建
注:将自己的事务处理机制与spring的事务机制做整合,这是任何ORM框架与Spring整合的必经之路。Spring的事务和ORM框架的事务本质上都是操作数据库的事务,到java中也就是JDBC的事务即Connection的事务,主要思路是@Transactional标记的方法会被spring的事务切面拦截,在横切逻辑中初始化一个Connection并保存到TransactionSynchronizationManager的ThreadLocal属性中,在此方法的后续数据库操作中都使用TransactionSynchronizationManager中的这个Connection。(spring的事务处理流程请参考-- spring事务源码剖析 )。
由于JPA有单独的事务管理器,所以需要声明一下。JpaTransactionManager也能兼容Mybatis的事务,如果一个项目既想用Mybatis也想用JPA+hibernate时事务管理器也要选则JpaTransactionManager。只有Mybatis时可以用DataSourceTransactionManager
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory){
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
return jpaTransactionManager;
}
至此配置部分完毕。
接下来分析下hibernate与JPA整合后是怎样和spring的声明式事务挂上钩的,首先分析一下JPATransactionManager在spring的事务切面中干了什么。
注:spring事务这块源码建议大家先看流程图,虽然原理简单但是调用栈特别深,贴代码讲解很容易看懵了(spring的事务处理流程请参考-- spring事务源码剖析 )。
spring事务切面的入口方法TransactionInterceptor.invoke()方法
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
// 对原方法进行拦截增强,织入事务横切逻辑
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
TransactionAspectSupport.invokeWithinTransaction()
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
// 获取事务属性解析器ProxyTransactionManagementConfiguration中注入
TransactionAttributeSource tas = getTransactionAttributeSource();
// 当前方法上声明式事务的相关属性信息
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 获取事务管理器,封装了事务启动、提交、回滚的横切逻辑,就是从spring工厂中获取这里获取的是JpaTransactionManager
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 封装了当前方法相关信息
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// A.获取事务详情,开启事务(包含当前事务全部信息,以及上层挂起事务)
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
// 执行原方法
retVal = invocation.proceedWithInvocation();
catch (Throwable ex) {
// target invocation exception
// B. 如果目标方法剖出异常执行回滚操作,并且抛出异常
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
finally {
// C.结合传播属性进行理解,处理挂起的事务
cleanupTransactionInfo(txInfo);
// D.目标方法正常执行事务提交操作。
commitTransactionAfterReturning(txInfo);
return retVal;
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
else {
throw new ThrowableHolderException(ex);
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
finally {
cleanupTransactionInfo(txInfo);
// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
return result;
catch (ThrowableHolderException ex) {
throw ex.getCause();
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
throw ex2;
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
throw ex2;
A.获取事务详情,开启事务TransactionAspectSupport.createTransactionIfNecessary()(包含当前事务全部信息,以及上层挂起事务)
上图为TransactionAspectSupport.createTransactionIfNecessary()方法的流程图,下面将通过源码一步一步分析,可结合上图看下文
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
// 获取当前事务的及时状态
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// a、获取事务状态对象
status = tm.getTransaction(txAttr);
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
// b、准备事务信息
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
a.首先看获取当前事务的及时状态tm.getTransaction(txAttr),调用AbstractPlatformTransactionManager.getTransaction()
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
// a1、获取事务会话(封装了ConnectionHolder连接)
Object transaction = doGetTransaction();
// Cache debug flag to avoid repeated checks.
boolean debugEnabled = logger.isDebugEnabled();
if (definition == null) {
// Use defaults if no transaction definition given.
definition = new DefaultTransactionDefinition();
// 是否存活跃的ConnectionHolder,如果是最外层事务此处为false,如果是内层事务此处为true
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
// a2.处理已经存在的事务
return handleExistingTransaction(definition, transaction, debugEnabled);
// Check definition settings for new transaction.
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// a3.当传播行为是PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED时且a1中获取到的transaction为未启动状态,即最外层事务方法才能执行到此。
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 获取新的事务及时对象,并设置newTransaction=true
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 为事务注入连接,并设置autoCommit=false;
doBegin(transaction, definition);
// 将新事务对象的名称、隔离级别、是否只读等属性保存到TransactionSynchronizationManager
prepareSynchronization(status, definition);
return status;
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
else {
// 非事务传播行执行的逻辑为如PROPAGATION_NOT_SUPPORTED和PROPAGATION_NEVER
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
a1、然后看具体TransactionManager的doGetTransaction()实现此处是JpaTransactionManager
@Override
protected Object doGetTransaction() {
// 创建Jpa事务对象包装类
JpaTransactionObject txObject = new JpaTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
// 尝试从TransactionSynchronizationManager获取EntityManager持有类,如果是最上层事务此处应该是获取不到的。
EntityManagerHolder emHolder = (EntityManagerHolder)
TransactionSynchronizationManager.getResource(obtainEntityManagerFactory());
if (emHolder != null) {
if (logger.isDebugEnabled()) {
logger.debug("Found thread-bound EntityManager [" + emHolder.getEntityManager() +
"] for JPA transaction");
// 如果获取到EntityManager持有类保存到Jpa事务对象包装类中,由于使用的上层事务中初始化的EntityManager所以并标记为非新。
txObject.setEntityManagerHolder(emHolder, false);
// JpaTransactionManager在创建时设置了DataSource属性所以此处为true
if (getDataSource() != null) {
// 尝试从TransactionSynchronizationManager获取Connection持有类,如果是最上层事务此处应该是获取不到的。
ConnectionHolder conHolder = (ConnectionHolder)
TransactionSynchronizationManager.getResource(getDataSource());
// 设置到Jpa事务对象包装类中
txObject.setConnectionHolder(conHolder);
return txObject;
}
TransactionSynchronizationManager的属性如下图,显而易见TransactionSynchronizationManager就是利用这些ThreadLocal类型属性来实现当前线程下的事务同步管理功能。在当前事务方法的生命周期内其涉及的数据库资源都存在TransactionSynchronizationManager内。
继续看a、步骤AbstractPlatformTransactionManager.getTransaction()方法,a1步骤分析了doGetTransaction();方法获取了事务会话,接下来有两种情况
@Transactional
public void method1(){
method2();
@Transactional
public void method2(){
}
a2、内层事务method2执行到此处,处理现有事务AbstractPlatformTransactionManager.handleExistingTransaction()方法
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
// 如果事务的传播行为为REQUIRES_NEW时
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
// 挂起当前事务,清空当前事务中Connection与当前线程在TransactionSynchronizationManager中ThreadLocal中的绑定关系
//SuspendedResourcesHolder 上层事务切面中的Connection,也是刚刚被清除挂起的那个
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 创建新的事务,此事务对象包含新的Connection连接和上层老的Connection连接,所以当传播行为为REQUIRES_NEW时会消耗多个数据库连接
// 由于newTransaction=true 所以当前事务可以执行commit,与最上层切面事务互不相关单独提交
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 注入新连接,开启事务,创建并绑定新Connection和EntityManager当前线程关系
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
// 如果事务的传播行为为PROPAGATION_NESTED时(嵌套事务)
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
if (useSavepointForNestedTransaction()) {
// 获取当前方法事务的及时状态对象,设置newTransaction=false,后面commit时只会commit newTransaction=true的事务
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
// 设置保存点,如果有保存点的时候,利用保存点进行回滚,commit后清除保存点(利用保存点做为回滚点回滚)
status.createAndHoldSavepoint();
return status;
else {
// 这里是用来处理分布式事务JTA事务的Nested方案的,暂不考虑
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
if (debugEnabled) {
logger.debug("Participating in existing transaction");
if (isValidateExistingTransaction()) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
"(unknown)"));
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 获取当前方法事务的及时状态对象,设置newTransaction=false,后面commit时只会commit newTransaction=true的事务
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
这里根据事务传播行为又分为三种情况,这三种比较常用和特殊
1)、REQUIRES_NEW(handleExistingTransaction方法的REQUIRES_NEW传播行为处理代码块)
// 如果事务的传播行为为REQUIRES_NEW时
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
// 挂起当前事务,清空当前事务中Connection与当前线程在TransactionSynchronizationManager中ThreadLocal中的绑定关系
//SuspendedResourcesHolder 上层事务切面中的Connection,也是刚刚被清除挂起的那个
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 创建最终事务包装类,此事务对象包含新的Connection连接和上层老的Connection连接,所以当传播行为为REQUIRES_NEW时会消耗多个数据库连接
// 由于newTransaction=true 所以当前事务可以执行commit,与最上层切面事务互不相关单独提交
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 注入新连接,开启事务,并绑定新Connection和新EntityManager与当前线程关系
doBegin(transaction, definition);
// 将新事务对象的名称、隔离级别、是否只读等属性保存到TransactionSynchronizationManager
prepareSynchronization(status, definition);
return status;
catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
看AbstractPlatformTransactionManager.suspend(transaction);
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
Object suspendedResources = null;
if (transaction != null) {
// 挂起当前事务
suspendedResources = doSuspend(transaction);
// 将TransactionSynchronizationManager中当前事务的各项属性置空,并封装保存到暂停事务资源持有类中暂存SuspendedResourcesHolder
String name = TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.setCurrentTransactionName(null);
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
TransactionSynchronizationManager.setActualTransactionActive(false);
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
catch (RuntimeException | Error ex) {
// doSuspend failed - original transaction is still active...
doResumeSynchronization(suspendedSynchronizations);
throw ex;
else if (transaction != null) {
// Transaction active but no synchronization active.
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
else {
// Neither transaction nor synchronization active.
return null;
}
核心方法JpaTransactionManager.doSuspend(transaction)
@Override
protected Object doSuspend(Object transaction) {
JpaTransactionObject txObject = (JpaTransactionObject) transaction;
// 将Jpa事务对象包装类的EntityManager置空
txObject.setEntityManagerHolder(null, false);
// 清空TransactionSynchronizationManager的resources属性中的EntityManager
EntityManagerHolder entityManagerHolder = (EntityManagerHolder)
TransactionSynchronizationManager.unbindResource(obtainEntityManagerFactory());
// 将Jpa事务对象包装类的Connection置空
txObject.setConnectionHolder(null);
ConnectionHolder connectionHolder = null;
if (getDataSource() != null && TransactionSynchronizationManager.hasResource(getDataSource())) {
// 清空TransactionSynchronizationManager的resources属性中的Connection
connectionHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(getDataSource());
// 将当前事务的Connection和EntityManager封装并暂存到SuspendedResourcesHolder对象里
return new SuspendedResourcesHolder(entityManagerHolder, connectionHolder);
}
完成当前事务挂起后,将创建一个新的事务封装对象DefaultTransactionStatus这个里面包含了挂起的Connection和EntityManager会话资源, 下面的doBegin方法是hibernate与JPA整合后与spring的声明式事务挂钩的核心逻辑,也是我们JPA事务管理器构建要关心的核心代码 JpaTransactionManager.doBegin
protected void doBegin(Object transaction, TransactionDefinition definition) {
JpaTransactionObject txObject = (JpaTransactionObject) transaction;
if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
throw new IllegalTransactionStateException(
"Pre-bound JDBC Connection found! JpaTransactionManager does not support " +
"running within DataSourceTransactionManager if told to manage the DataSource itself. " +
"It is recommended to use a single JpaTransactionManager for all transactions " +
"on a single DataSource, no matter whether JPA or JDBC access.");
try {
if (!txObject.hasEntityManagerHolder() ||
txObject.getEntityManagerHolder().isSynchronizedWithTransaction()) {
// 调用AbstractEntityManagerFactoryBean.createNativeEntityManager创建EntityManager
EntityManager newEm = createEntityManagerForTransaction();
if (logger.isDebugEnabled()) {
logger.debug("Opened new EntityManager [" + newEm + "] for JPA transaction");
// 给jap事务包装类设置新的EntityManager
txObject.setEntityManagerHolder(new EntityManagerHolder(newEm), true);
EntityManager em = txObject.getEntityManagerHolder().getEntityManager();
// Delegate to JpaDialect for actual transaction begin.
final int timeoutToUse = determineTimeout(definition);
// 初始化EntityManager中的Connection并开启JDBC事务返回JDBC事务对象,初始化的最终调用的LogicalConnectionManagedImpl.getPhysicalConnection方法
Object transactionData = getJpaDialect().beginTransaction(em,
new JpaTransactionDefinition(definition, timeoutToUse, txObject.isNewEntityManagerHolder()));
// 给jap事务包装类设置具体ORM厂商对JDBC事务的具体实现类,这里是Hibernate的
txObject.setTransactionData(transactionData);
// Register transaction timeout.
if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getEntityManagerHolder().setTimeoutInSeconds(timeoutToUse);
// Register the JPA EntityManager's JDBC Connection for the DataSource, if set.
if (getDataSource() != null) {
// 获取EntityManage中的Connection
ConnectionHandle conHandle = getJpaDialect().getJdbcConnection(em, definition.isReadOnly());
if (conHandle != null) {
ConnectionHolder conHolder = new ConnectionHolder(conHandle);
if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) {
conHolder.setTimeoutInSeconds(timeoutToUse);
if (logger.isDebugEnabled()) {
logger.debug("Exposing JPA transaction as JDBC [" + conHandle + "]");
// 将EntityManage中的Connection保存到TransactionSynchronizationManager中
TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
txObject.setConnectionHolder(conHolder);
else {
if (logger.isDebugEnabled()) {
logger.debug("Not exposing JPA transaction [" + em + "] as JDBC transaction because " +
"JpaDialect [" + getJpaDialect() + "] does not support JDBC Connection retrieval");
// Bind the entity manager holder to the thread.
if (txObject.isNewEntityManagerHolder()) {
// 将EntityManage也保存到TransactionSynchronizationManager中,我们平时开发中通过@PersistenceContext注入EntityManager是个代理类,
// 当其执行时真正进行增删改查调用的是TransactionSynchronizationManager中的这个EntityManager(具体可以见 SpringDataJPA+Hibernate框架源码剖析(四)@PersistenceContext和@Autowired注入EntityManager的区别 ),这样就能保证同一个声明式事务
// 内EntityManager对数据库操作的原子性。
// 而且上面EntityManager中的Connection也在TransactionSynchronizationManager中,就是项目中还有Mybatis等其他ORM框架,其在同一个声明式事务内
// 也共同使用一个Connection,所以只要与Spring事务挂钩的ORM框架在同一个声明式事务内都可以保证数据库操作的原子性。
TransactionSynchronizationManager.bindResource(
obtainEntityManagerFactory(), txObject.getEntityManagerHolder());
txObject.getEntityManagerHolder().setSynchronizedWithTransaction(true);
catch (TransactionException ex) {
closeEntityManagerAfterFailedBegin(txObject);
throw ex;
catch (Throwable ex) {
closeEntityManagerAfterFailedBegin(txObject);
throw new CannotCreateTransactionException("Could not open JPA EntityManager for transaction", ex);
}
2)、PROPAGATION_NESTED(handleExistingTransaction方法的PROPAGATION_NESTED传播行为处理代码块)
// 如果事务的传播行为为PROPAGATION_NESTED时(嵌套事务)
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
if (useSavepointForNestedTransaction()) {
// 创建最终事务包装类,设置newTransaction=false,后面commit时只会commit newTransaction=true的事务,因为要保证原子性所以只有最外层事务方法完成后才能commit。
// 相对于NEW传播行为transaction对象不做处理,内部的Connection和
// EntityManager都用TransactionSynchronizationManager中的,transaction在步骤a1.1获取
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
// 设置保存点,如果有保存点的时候,利用保存点进行回滚,commit后清除保存点(利用保存点做为回滚点回滚)
status.createAndHoldSavepoint();
return status;
保存点概念科普:一个事务刚刚开启的时候默认就会有一个保存点,默认的rollback也是回滚到最开始的保存点。在整个事务过程中都可以设置保存点,rollback可以指定保存点进行回滚如下。
select * from t_user; -- 开始的开始 18岁 踌躇满志
Savepoint a; -- a回滚点 18岁
update t_user set u_age ='30' where id='1'; -- 一事无成,已到中年
Savepoint b; -- b回滚点 30岁
update t_user set u_age ='50' where id='1'; -- 年过半百 仍旧一事无成 知天命了
Rollback To a; -- 心有不甘,重回18岁
rollback to b; -- 心有不甘,回到30岁
rollback; -- 人生太失败,全部回滚
commit; -- 算了,人生不可复制 就这样吧
3)、PROPAGATION_REQUIRED(handleExistingTransaction方法的PROPAGATION_REQUIRED传播行为处理代码块,即最后一行)
// 创建最终事务包装类,设置newTransaction=false,后面commit时只会commit newTransaction=true的事务;相对于NEW传播行为transaction对象不做处理,内部的Connection和
// EntityManager都用TransactionSynchronizationManager中的,transaction在步骤a1获取
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
a3.外层事务method1执行到此处,创建新的事务(AbstractPlatformTransactionManager.getTransaction方法中a3行位置代码块)
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 当传播行为是PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED时且a1中获取到的transaction为未启动状态,即最外层事务方法才能执行到此。
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 创建最终事务包装类,并设置newTransaction=true
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 注入新连接,开启事务,创建并绑定新Connection和EntityManager当前线程关系,并设置autoCommit=false;
doBegin(transaction, definition);
// 将新事务对象的名称、隔离级别、是否只读等属性保存到TransactionSynchronizationManager
prepareSynchronization(status, definition);
return status;
}
到此TransactionAspectSupport.createTransactionIfNecessary()中步骤a的分析完毕,已经获取到当前事务的及时状态。(根据是否最外层事务以及不同传播行为 当前事务状态的获取步骤不同)。 接下来看下
b、准备事务信息TransactionAspectSupport.prepareTransactionInfo()
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, String joinpointIdentification,
@Nullable TransactionStatus status) {
// 创建事务封装对象,再次包装
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
// We need a transaction for this method...
if (logger.isTraceEnabled()) {
logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
// The transaction manager will flag an error if an incompatible tx already exists.
txInfo.newTransactionStatus(status);
else {
// The TransactionInfo.hasTransaction() method will return false. We created it only
// to preserve the integrity of the ThreadLocal stack maintained in this class.
if (logger.isTraceEnabled()) {
logger.trace("No need to create transaction for [" + joinpointIdentification +
"]: This method is not transactional.");
// 将当前方法事务与线程绑定,并且记录上级方法的事务详情备用,等当前方法事务结束后再将上级方法的事务与当前线程绑定。方便外部调用获取当下方法的事务。可以调用TransactionAspectSupport.currentTransactionStatus方法获取。
txInfo.bindToThread();
return txInfo;
看TransactionAspectSupport.TransactionInfo.bindToThread()
private void bindToThread() {
// 获取当前线程的当前栈桢方法的事务封装对象,赋值给oldTransactionInfo,如果是最外层事务时此处为null,
// 只有出现嵌套事务时采用的的到,
// 如:
// @Transactional
// public void method1(){
// ....
// AopContext.currentProxy().method2()
// @Transactional
// public void method2(){
// ...
// 当method1()被调用时此处 this=method1TransactionInfo ; this.oldTransactionInfo=transactionInfoHolder.get()=null;
// 当method2()被调用时此处 this=method2TransactionInfo ;this.oldTransactionInfo=transactionInfoHolder.get()=method1TransactionInfo;
this.oldTransactionInfo = transactionInfoHolder.get();
transactionInfoHolder.set(this);
}
至此整个步骤A完成,根据是否最外层事务以及事务的传播行为获取到当下的事务信息封装类。
接下来事务切面执行原方法。然后分为两种情况,如果原方法抛出异常则切面捕捉异常进行回滚或者标记回滚操作,如果原方法未抛出异常则进行事务提交处理。
首先看下原方法出现异常时事务切面的处理
B. 如果目标方法剖出异常执行回滚操作,并且抛出异常
TransactionAspectSupport.completeTransactionAfterThrowing(txInfo, ex),此方法首先判断当前异常是否触发回归,要知道spring的声明式事务默认只回归RuntimeException的下级异常,所以有的异常时不触发回归的,如果触发回归执行JpaTransactionManager的回归逻辑,不触发则执行提交逻辑。这里我们着重看回归逻辑,提交逻辑在步骤D中分析。
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
"] after exception: " + ex);
// 判断当前异常类型是否需要回滚
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
// 当前异常类型触发回滚
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
else {
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
try {
// 当前异常类型未触发回滚,执行commit
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);
throw ex2;
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by commit exception", ex);
throw ex2;
}
执行AbstractPlatformTransactionManager.rollback()
@Override
public final void rollback(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 回滚
processRollback(defStatus, false);
执行AbstractPlatformTransactionManager.processRollback()
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean unexpectedRollback = unexpected;
try {
triggerBeforeCompletion(status);
// 判断是否存在保存点(NESTED传播行为,在非最外层事务时会创建保存点用于回滚)
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
// 如果存在保存点,将保存点作为回滚点进行回滚
status.rollbackToHeldSavepoint();
// 判断是否是最外层事务
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
// b1.如果是最外层事务进行回滚
doRollback(status);
else {
// Participating in larger transaction
if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
//b2.不是最外层事务也不具备保存点,对ConnectionHolder进行回滚标记
doSetRollbackOnly(status);
else {
if (status.isDebug()) {
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
else {
logger.debug("Should roll back transaction but cannot - no transaction available");
// Unexpected rollback only matters here if we're asked to fail early
if (!isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = false;
catch (RuntimeException | Error ex) {
// b3:回滚成功后置处理,把TransactionSynchronizationManager.synchronizations中的事务同步对象遍历进行回滚。
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
// b3:回滚成功后置处理,把TransactionSynchronizationManager.synchronizations中的事务同步对象遍历进行回滚。
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
// Raise UnexpectedRollbackException if we had a global rollback-only marker
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
finally {
// b4:
// 1.如果是最外层事务(newTransaction=true)则清除ThreadLocal中的绑定关系,并关闭会话资源如:Connection放回连接池,
// 2.如果存在已经挂起事务,那就恢复Connection绑定
cleanupAfterCompletion(status);
b1、如果是最外层事务进行回滚(JpaTransactionManager.doRollback)
关于事务型和扩展型EntityManager的不同之处见 SpringDataJPA+Hibernate框架源码剖析(四)@PersistenceContext和@Autowired注入EntityManager的区别
@Override
protected void doRollback(DefaultTransactionStatus status) {
// 获取Jpa的事务对象
JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction();
if (status.isDebug()) {
logger.debug("Rolling back JPA transaction on EntityManager [" +
txObject.getEntityManagerHolder().getEntityManager() + "]");
try {
// 获取EntityTransaction调用rollback进行回滚操作
EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction();
if (tx.isActive()) {
tx.rollback();
catch (PersistenceException ex) {
throw new TransactionSystemException("Could not roll back JPA transaction", ex);
finally {
if (!txObject.isNewEntityManagerHolder()) {
// 对于事务型的EntityManager此判断始终为false,只有使用扩展型EntityManager开发时才会用到这个地方。因为事务型的EntityManager只有最外层事务才会进入doRollback这个方法,而最外层事务的EntityManager始终是新建的所以不会进这个判断。
// 调用EntityManager().clear()目的是清空当前EntityManager的持久化上下文persistenceContext,和待触发的动作队列actionQueue
txObject.getEntityManagerHolder().getEntityManager().clear();
}
b2、不是最外层事务也不具备保存点,对ConnectionHolder进行回滚标记
首先介绍下什么是回滚标记,先看下面的场景一、二,他们的区别就是场景一的method2标记@Transactional。他们的执行结果是:
- 场景一User保存失败并打印异常信息Transaction silently rolled back because it has been marked as rollback-only
- 场景二User保存成功
明明method2()中抛出的异常已经在method1()中处理了为什么method1()还是会回滚呢?
因为场景一的method2()标记有@Transactional在被调用时会进入事务切面TransactionInterceptor.invoke(),切面中执行完原方法后就会产生异常,事务切面捕捉到原方法异常后调用 步骤B ,而 步骤B 判断不是最外层事务进而调用 步骤b2 ,在b2中进行了回滚标记,这里标记的是Connection。虽然method1的事务切面能执行到步 骤D 事务提交操作,但是在提交时会判断这个Connection有没有被标记回归,如果被标记了就回归,所以method1也回滚;场景二因为没@Transactional不会进入事务切面也就没机会标记Connection为回滚,所以不会影响 method1。
***********************场景一****************************
@Transactional
public void method1(){
entityManager.merge(new User())
try{
AopContext.currentProxy().method2()
} catch (Exception e) {
e.printStackTrace();
@Transactional
public void method2(){
int a=1/0;
***********************场景二*****************************
@Transactional
public void method1(){
entityManager.merge(new User())
try{
AopContext.currentProxy().method2()
} catch (Exception e) {
e.printStackTrace();
public void method2(){
int a=1/0;
接下来看下JpaTransactionManager中的标记回滚接口干了什么
JpaTransactionManager.doSetRollbackOnly
@Override
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction();
if (status.isDebug()) {
logger.debug("Setting JPA transaction on EntityManager [" +
txObject.getEntityManagerHolder().getEntityManager() + "] rollback-only");
// 标会回滚
txObject.setRollbackOnly();
}
JpaTransactionObject.setRollbackOnly()
public void setRollbackOnly() {
// 获取EntityTransaction进行回滚标记
EntityTransaction tx = getEntityManagerHolder().getEntityManager().getTransaction();
if (tx.isActive()) {
tx.setRollbackOnly();
if (hasConnectionHolder()) {
// 获取Connection进行回滚标记
getConnectionHolder().setRollbackOnly();
}
b3、回滚成功后置处理,把TransactionSynchronizationManager.synchronizations中的事务同步对象遍历进行回滚。
AbstractPlatformTransactionManager.triggerAfterCompletion
private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {
if (status.isNewSynchronization()) {
// 获取TransactionSynchronizationManager.Synchronizations属性中保存的事务同步对象
List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations();
TransactionSynchronizationManager.clearSynchronization();
if (!status.hasTransaction() || status.isNewTransaction()) {
if (status.isDebug()) {
logger.trace("Triggering afterCompletion synchronization");
// 后置处理核心方法
invokeAfterCompletion(synchronizations, completionStatus);
else if (!synchronizations.isEmpty()) {
// Existing transaction that we participate in, controlled outside
// of the scope of this Spring transaction manager -> try to register
// an afterCompletion callback with the existing (JTA) transaction.
registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations);
}
TransactionSynchronizationUtils.invokeAfterCompletion()
public static void invokeAfterCompletion(@Nullable List<TransactionSynchronization> synchronizations,
int completionStatus) {
if (synchronizations != null) {
for (TransactionSynchronization synchronization : synchronizations) {
try {
// 遍历TransactionSynchronization进行后置处理,也不是所以的都是回滚操作,不同TransactionSynchronization可以有不同重写.
synchronization.afterCompletion(completionStatus);
catch (Throwable tsex) {
logger.error("TransactionSynchronization.afterCompletion threw exception", tsex);
}
这里分析TransactionSynchronization的其中一个实现,也是和Jpa相关的即扩展型EntityManager的事务同步对象。(至于什么时候将TransactionSynchronization注入TransactionSynchronizationManager.Synchronizations中的可以看 SpringDataJPA+Hibernate框架源码剖析(四)@PersistenceContext和@Autowired注入EntityManager的区别 )
ExtendedEntityManagerCreator.afterCompletion()
public void afterCompletion(int status) {
try {
super.afterCompletion(status);
if (status != STATUS_COMMITTED) {
// Haven't had an afterCommit call: trigger a rollback.
try {
// 进行回滚操作
this.entityManager.getTransaction().rollback();
catch (RuntimeException ex) {
throw convertException(ex);
finally {
if (this.closeOnCompletion) {
EntityManagerFactoryUtils.closeEntityManager(this.entityManager);
}
b4、 解除当前事务ThreadLocal绑定销毁资源 或者 恢复挂起事务
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
status.setCompleted();
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
if (status.isNewTransaction()) {
// 如果是最外层事务(newTransaction=true)则清除ThreadLocal中的绑定关系,并关闭会话资源如:Connection放回连接池
doCleanupAfterCompletion(status.getTransaction());
if (status.getSuspendedResources() != null) {
if (status.isDebug()) {
logger.debug("Resuming suspended transaction after completion of inner transaction");
// status.getSuspendedResources() 只有在传播行为REQUIRES_NEW时存在(在步骤a2中可以看到细节)。
// 如果存在已经挂起事务,那就恢复绑定
// 获取现有事务对象transaction
Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
}
1)、 如果是最外层事务(newTransaction=true)则清除ThreadLocal中的绑定关系,并关闭会话资源如:Connection放回连接池
JpaTransactionManager.doCleanupAfterCompletion
@Override
protected void doCleanupAfterCompletion(Object transaction) {
JpaTransactionObject txObject = (JpaTransactionObject) transaction;
// 如果EntityManager是当前事务创建的,即当前事务是最外层事务
if (txObject.isNewEntityManagerHolder()) {
// 将EntityManager从TransactionSynchronizationManager中剔除,与当前线程解绑
TransactionSynchronizationManager.unbindResourceIfPossible(obtainEntityManagerFactory());
txObject.getEntityManagerHolder().clear();
// Remove the JDBC connection holder from the thread, if exposed.
if (getDataSource() != null && txObject.hasConnectionHolder()) {
// 将Connection从TransactionSynchronizationManager中剔除,与当前线程解绑
TransactionSynchronizationManager.unbindResource(getDataSource());
ConnectionHandle conHandle = txObject.getConnectionHolder().getConnectionHandle();
if (conHandle != null) {
try {
// 释放EntityManager中的Connection返换给数据池
getJpaDialect().releaseJdbcConnection(conHandle,
txObject.getEntityManagerHolder().getEntityManager());
catch (Exception ex) {
// Just log it, to keep a transaction-related exception.
logger.error("Could not close JDBC connection after transaction", ex);
getJpaDialect().cleanupTransaction(txObject.getTransactionData());
// Remove the entity manager holder from the thread.
if (txObject.isNewEntityManagerHolder()) {
EntityManager em = txObject.getEntityManagerHolder().getEntityManager();
if (logger.isDebugEnabled()) {
logger.debug("Closing JPA EntityManager [" + em + "] after transaction");
// 关闭当前EntityManager
EntityManagerFactoryUtils.closeEntityManager(em);
else {
logger.debug("Not closing pre-bound JPA EntityManager after transaction");
}
2)、如果存在已经挂起事务即(当前事务为传播REQUIRES_NEW的内层事务),那就恢复已挂起事务的绑定
AbstractPlatformTransactionManager.resume()
protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
throws TransactionException {
if (resourcesHolder != null) {
Object suspendedResources = resourcesHolder.suspendedResources;
if (suspendedResources != null) {
// 将被挂起的资源放入TransactionSynchronizationManager
doResume(transaction, suspendedResources);
// 获取被挂起的事务同步对象
List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
if (suspendedSynchronizations != null) {
// 替换TransactionSynchronizationManager中的各个属性
TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
// 变量被挂起的事务同步对象注册到TransactionSynchronizationManager.synchronizations中
doResumeSynchronization(suspendedSynchronizations);
}
看下JpaTransactionManager.doResume
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder) suspendedResources;
// 将被挂起的EntityManager放入TransactionSynchronizationManager中
TransactionSynchronizationManager.bindResource(
obtainEntityManagerFactory(), resourcesHolder.getEntityManagerHolder());
if (getDataSource() != null && resourcesHolder.getConnectionHolder() != null) {
// 将被挂起的Connection放入TransactionSynchronizationManager中
TransactionSynchronizationManager.bindResource(getDataSource(), resourcesHolder.getConnectionHolder());
}
到此步骤B的回归操作分析完毕
C.结合传播属性进行理解,切换当前事务
TransactionAspectSupport.cleanupTransactionInfo()
protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
if (txInfo != null) {
// 将被挂起的链接与当前线程绑定
txInfo.restoreThreadLocalStatus();
}
TransactionInfo.restoreThreadLocalStatus();
此处可以结合A步骤中的 b步骤理解
private void restoreThreadLocalStatus() {
// 因为method2()方法即将执行完毕所以将当前线程的当前栈桢方法为method2的事务封装对象设置为上层method1事务封装对象。
// 只有出现嵌套事务时采用的的到,
// 如:
// @Transactional
// public void method1(){
// ....
// AopContext.currentProxy().method2()
// @Transactional
// public void method2(){
// ...
// 当method1()被调用时此处 this=transactionInfoHolder.get()=method1TransactionInfo ; this.oldTransactionInfo=null;
// 当method2()被调用时此处 this=transactionInfoHolder.get()=method2TransactionInfo ;this.oldTransactionInfo=method1TransactionInfo;
// 将被挂起的链接与当前线程绑定
transactionInfoHolder.set(this.oldTransactionInfo);
}
D.目标方法正常执行事务提交操作。
TransactionAspectSupport.commitTransactionAfterReturning(txInfo);
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
// commit
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
AbstractPlatformTransactionManager.commit(),在commit时如果判断该事务已经被标记回滚,会进行全局回滚。回滚的逻辑在步骤B已经分析过了,这里我们主要关注processCommit方法。
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
processRollback(defStatus, false);
return;
// 如果ConnectionHolder被标记了isRollbackOnly=true,此时会触发全局回滚
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
// 回滚
processRollback(defStatus, true);
return;
// 事务提交
processCommit(defStatus);
}
AbstractPlatformTransactionManager.processCommit(),此方法过程很多小分支在步骤B中都分析过,都是同一个方法不同参数罢了这里就不贴了。主要明白四个地方
- NESTED的传播模式在提交事务时其实是调用此处清空保存点,然后等待最外层事务一起提交或者回滚
- 判断是否最外层事务,多层声明式事务方法嵌套时只commit最上层、最外层切面的事务(第一个创建的事务)
- 在外层事务commit完成后遍历TransactionSynchronizationManager的synchronizations中事务同步对象调用其afterCommit方法进行提交的后置处理
- 解除当前事务ThreadLocal绑定销毁资源 或者 恢复挂起事务
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
boolean unexpectedRollback = false;
prepareForCommit(status);
// 遍历TransactionSynchronizationManager的synchronizations中事务同步对象调用其beforeCommit方法进行提交的前置处理
triggerBeforeCommit(status);
// 遍历TransactionSynchronizationManager的synchronizations中事务同步对象调用其beforeCompletion方法进行提交的前置处理
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
// 判断是否存在保存点
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
unexpectedRollback = status.isGlobalRollbackOnly();
// 清除保存点
//1. NESTED的传播模式在提交事务时其实是调用此处清空保存点,然后等待最外层事务一起提交或者回滚
status.releaseHeldSavepoint();
//2. 判断是否最外层事务,多层声明式事务方法嵌套时只commit最上层、最外层切面的事务(第一个创建的事务)
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
unexpectedRollback = status.isGlobalRollbackOnly();
// 进行commit,调用JpaTransactionManager的doCommit
doCommit(status);
else if (isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = status.isGlobalRollbackOnly();
// Throw UnexpectedRollbackException if we have a global rollback-only
// marker but still didn't get a corresponding exception from commit.
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction silently rolled back because it has been marked as rollback-only");
catch (UnexpectedRollbackException ex) {
// can only be caused by doCommit
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
catch (TransactionException ex) {
// can only be caused by doCommit
if (isRollbackOnCommitFailure()) {
doRollbackOnCommitException(status, ex);
else {
// 遍历TransactionSynchronizationManager的synchronizations中事务同步对象调用其afterCompletion方法进行提交的后置处理
* TransactionSynchronization=STATUS_ROLLED_BACK或STATUS_UNKNOWN
* 时后置处理会触发回滚操作,且清空EntityManager的持久化上下文PersistenceContext和待触发的动作队列actionQueue
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
catch (RuntimeException | Error ex) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(status);
doRollbackOnCommitException(status, ex);
throw ex;
try {
// 3. 遍历TransactionSynchronizationManager的synchronizations中事务同步对象调用其afterCommit方法进行提交的后置处理
triggerAfterCommit(status);
finally {
// 遍历TransactionSynchronizationManager的synchronizations中事务同步对象调用其afterCompletion方法进行提交的后置处理
* TransactionSynchronization=STATUS_ROLLED_BACK或STATUS_UNKNOWN
* 时后置处理会触发回滚操作,且清空EntityManager的持久化上下文PersistenceContext和待触发的动作队列actionQueue
* 此处为STATUS_COMMITTED不会清空持久化上下文
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
finally {