目录
  1. doGetTransaction
  2. isExistingTransaction
  3. doBegin
  4. doSuspend
  5. doResume
  6. 1、PROPAGATION_REQUIRED
  7. 2、PROPAGATION_SUPPORTS
  8. 3、PROPAGATION_MANDATORY
  9. 4、PROPAGATION_REQUIRES_NEW
  10. 5、PROPAGATION_NOT_SUPPORTED
  11. 6、PROPAGATION_NEVER
  12. 7、PROPAGATION_NESTED
  13. 当前事务不存在
    1. PROPAGATION_MANDATORY = 2
    2. PROPAGATION_REQUIRED = 0;PROPAGATION_REQUIRES_NEW = 3;PROPAGATION_NESTED = 6;
  14. PROPAGATION_SUPPORTS = 1;PROPAGATION_NOT_SUPPORTED = 4;PROPAGATION_NEVER = 5;
  15. 当前事务存在
    1. PROPAGATION_NEVER = 5;
    2. PROPAGATION_NOT_SUPPORTED = 4;
    3. PROPAGATION_REQUIRES_NEW = 3;
    4. PROPAGATION_NESTED = 6;
  16. PROPAGATION_REQUIRED = 0;PROPAGATION_MANDATORY = 2;PROPAGATION_SUPPORTS = 1;
Spring-TX【三】getTransaction之Spring事务传播行为与数据源连接绑定

DataSourceTransactionManager类中的方法是继承自父类AbstractPlatformTransactionManager。
现在分析方法:getTransaction(@Nullable TransactionDefinition definition)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/**
* 此实现处理传播行为。
* 委托给 {@code doGetTransaction}, {@code isExistingTransaction} and {@code doBegin}.
*
* @see #doGetTransaction
* @see #isExistingTransaction
* @see #doBegin
*/
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
//子类实现
Object transaction = doGetTransaction();

// 缓存调试标志以避免重复检查。
boolean debugEnabled = logger.isDebugEnabled();

if (definition == null) {
// 如果没有给出事务定义,则使用缺省值。
// propagationBehavior = PROPAGATION_REQUIRED,支持当前事务;如果不存在,创建一个新的。
// isolationLevel = ISOLATION_DEFAULT,使用底层数据存储的默认隔离级别。
// timeout = TIMEOUT_DEFAULT,使用底层事务系统的默认超时,如果不支持超时,则使用none。
// readOnly = false;
definition = new DefaultTransactionDefinition();
}

//isExistingTransaction由子类实现,检查事务是否已经启动
if (isExistingTransaction(transaction)) {
// 已找到的事务->检查传播行为,以找出如何行为。
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());
}

//没有找到现有的事务->检查传播行为,以找出如何继续。
// PROPAGATION_MANDATORY = 2; 支持当前事务;如果当前事务不存在,则抛出异常
// mandatory:强制的
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
//没有为标记为传播“mandatory”的事务找到现有事务
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
// required,nested:嵌套的
// PROPAGATION_REQUIRED = 0; 支持当前事务;如果不存在,创建一个新的。
// PROPAGATION_REQUIRES_NEW = 3; 创建一个新事务,如果存在当前事务,则挂起当前事务。
// PROPAGATION_NESTED = 6; 如果当前事务存在,则在嵌套事务中执行,否则行为类似PROPAGATION_REQUIRED。
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 暂停给定的事务。首先挂起事务同步,然后委托给 doSuspend模板方法。
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
//getTransactionSynchronization():返回此事务管理器是否应激活线程绑定事务同步支持。
//SYNCHRONIZATION_NEVER:2,永远不要进行活动事务同步,即使对于实际事务也是如此。
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
//创建DefaultTransactionStatus对象
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//根据给定的事务定义使用语义开始一个新的事务。
//由子类实现
doBegin(transaction, definition);
//根据需要初始化事务同步。
prepareSynchronization(status, definition);
return status;
} catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
// PROPAGATION_SUPPORTS = 1;支持当前事务;如果不存在非事务执行。
// PROPAGATION_NOT_SUPPORTED = 4;不支持当前事务;而是始终以非事务方式执行。
// PROPAGATION_NEVER = 5; 不支持当前事务;如果当前事务存在,则抛出异常。
// supports,never
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
// 创建“空”事务:没有实际事务,但可能同步。
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);
}
}

/**
* 为现有事务创建一个TransactionStatus。
*/
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {

// PROPAGATION_NEVER = 5; 不支持当前事务;如果当前事务存在,则抛出异常。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
//为标记为传播“never”的事务找到的现有事务
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}

// PROPAGATION_NOT_SUPPORTED = 4;不支持当前事务;而是始终以非事务方式执行。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
// 暂停给定的事务。首先挂起事务同步,然后委托给{@code doSuspend}模板方法。
Object suspendedResources = suspend(transaction);
// SYNCHRONIZATION_ALWAYS:始终激活事务同步,即使对于没有任何后端事务的“空”事务,也要激活它。
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}

// PROPAGATION_REQUIRES_NEW = 3; 创建一个新事务,如果存在当前事务,则挂起当前事务。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
// 暂停给定的事务。首先挂起事务同步,然后委托给{@code doSuspend}模板方法。
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
//SYNCHRONIZATION_NEVER:永远不要进行活动事务同步,即使对于实际事务也是如此。
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//根据给定的事务定义使用语义开始一个新的事务
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
} catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}

// PROPAGATION_NESTED = 6; 如果当前事务存在,则在嵌套事务中执行,否则行为类似PROPAGATION_REQUIRED。
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()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
//创建一个保存点,并为事务保存它。
status.createAndHoldSavepoint();
return status;
} else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
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");
}
}
}
//SYNCHRONIZATION_NEVER: 永远不要进行活动事务同步,即使对于实际事务也是如此。
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

/**
* Create a new TransactionStatus for the given arguments,
* also initializing transaction synchronization as appropriate.
*
* @see #newTransactionStatus
* @see #prepareTransactionStatus
*/
protected final DefaultTransactionStatus prepareTransactionStatus(
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {

DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);
prepareSynchronization(status, definition);
return status;
}
/**
* 暂停给定的事务。首先挂起事务同步,然后委托给{@code doSuspend}模板方法。
*
* @param transaction 当前事务对象(或{@code null},以暂停活动同步,如果有的话)
* @return 一个持有挂起资源的对象(或者{@code null},如果事务和同步都不是活动的)
* @see #doSuspend
* @see #resume
*/
@Nullable
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);
}
//数据保持,便于后期恢复
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) {
// 事务活动,但没有同步活动。
// 挂起,由子类实现
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
} else {
// 事务和同步都不是活动的。
return null;
}
}
/**
* 恢复给定的事务。首先委托给{@code doResume}模板方法,然后恢复事务同步。
*
* @param transaction 当前事务对象
* @param resourcesHolder 持有挂起资源的对象,由{@code suspend}(或{@code null}返回,以便恢复同步,如果有的话)
* @see #doResume
* @see #suspend
*/
protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
throws TransactionException {

if (resourcesHolder != null) {
Object suspendedResources = resourcesHolder.suspendedResources;
if (suspendedResources != null) {
//子类实现
doResume(transaction, suspendedResources);
}
List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
if (suspendedSynchronizations != null) {
TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
//重新激活当前线程的事务同步,并恢复所有给定的同步。
doResumeSynchronization(suspendedSynchronizations);
}
}
}

这里主要是spring对其七种事务传播行为的处理,比较复杂。
其中涉及到五个方法需要子类实现:

doGetTransaction

1
2
3
4
5
6
7
8
9
10
11
12
@Override
protected Object doGetTransaction() {
//数据源事务对象,表示ConnectionHolder。
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
//是否允许嵌套事务。
txObject.setSavepointAllowed(isNestedTransactionAllowed());
//获取实际使用的数据源。
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
txObject.setConnectionHolder(conHolder, false);
return txObject;
}

obtainDataSource方法获取实际的数据源:

1
2
3
4
5
6
protected DataSource obtainDataSource() {
//返回此实例为其管理事务的JDBC数据源。
DataSource dataSource = getDataSource();
Assert.state(dataSource != null, "No DataSource set");
return dataSource;
}

isExistingTransaction

1
2
3
4
5
6
@Override
protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
//返回该holder是否表示一个活动的、jdbc管理的事务。
return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}

doBegin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* 此实现设置隔离级别,但忽略超时。
*/
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
//看到这个很有亲切感
Connection con = null;

try {
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}

txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();

//如果是只读的话,con.setReadOnly(true);
//设置隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);

// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
con.setAutoCommit(false);
}

//只读处理:con.createStatement().executeUpdate("SET TRANSACTION READ ONLY");
prepareTransactionalConnection(con, definition);
txObject.getConnectionHolder().setTransactionActive(true);

int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}

// Bind the connection holder to the thread.
if (txObject.isNewConnectionHolder()) {
//绑定线程
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
} catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}

doSuspend

1
2
3
4
5
6
7
@Override
protected Object doSuspend(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
txObject.setConnectionHolder(null);
//从当前线程中解绑定资源。
return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}

doResume

1
2
3
4
5
@Override
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
//绑定线程
TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);
}

简单总结:
getTransaction方法的主要功能就是应用Spring的7种事务传播行为,之后获取真实使用的数据源,打连接,与本线程绑定。

这里再分析一下Spring的7种事务传播行为:

事务传播行为类型 说明
PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

事务传播行为解释:
事务方法A,调用事务方法B时,此时事务方法B该如何处理事务,就按照事务方法B所设置的事务传播行为来处理。
事务方法A不是必须要开启事务的。

1、PROPAGATION_REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。

1
2
3
4
5
6
7
8
9
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
methodB();
// do something
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
// do something
}

当单独调用方法B时,因为上下文不存在事务,所以新建一个事务。
当通过调用方法A而调用到方法B时,方法B发现上下文有事务,则加入到这个事务中,即发生了传播。

2、PROPAGATION_SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行。

1
2
3
4
5
6
7
8
9
10
11
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
methodB();
// do something
}

// 事务属性为SUPPORTS
@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() {
// do something
}

当单独调用方法B时,因为上下文不存在事务,就以非事务方式执行。
当通过调用方法A而调用到方法B时,方法B发现上下文有事务,则加入到这个事务中。

3、PROPAGATION_MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。

1
2
3
4
5
6
7
8
9
10
11
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
methodB();
// do something
}

// 事务属性为MANDATORY
@Transactional(propagation = Propagation.MANDATORY)
public void methodB() {
// do something
}

当单独调用方法B时,因为上下文不存在事务,就抛出异常。
当通过调用方法A而调用到方法B时,方法B发现上下文有事务,则加入到这个事务中。

4、PROPAGATION_REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
doSomeThingA();
methodB();
doSomeThingB();
// do something
}

// 事务属性为MANDATORY
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// do something
}

当单独调用方法B时,因为上下文不存在事务,新建事务。
当通过调用方法A而调用到方法B时,方法B发现上下文有事务T1,则挂起上下文中的事务T1,新建事务T2执行方法B,
新的事务T2提交之后,再唤醒以前的事务T1,这两个事务T1与T2相互独立。

5、PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
doSomeThingA();
methodB();
doSomeThingB();
// do something
}

// 事务属性为MANDATORY
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void methodB() {
// do something
}

当单独调用方法B时,因为上下文不存在事务,以非事务方式执行操作。
当通过调用方法A而调用到方法B时,方法B发现上下文有事务T1,则挂起上下文中的事务T1,以非事务方式执行方法B,
执行完之后,再唤醒以前的事务T1。

6、PROPAGATION_NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。

1
2
3
4
5
6
7
8
9
10
11
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
methodB();
// do something
}

// 事务属性为MANDATORY
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void methodB() {
// do something
}

当单独调用方法B时,因为上下文不存在事务,以非事务方式执行。
当通过调用方法A而调用到方法B时,方法B发现上下文有事务T1,则抛出异常。

7、PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
doSomeThingA();
methodB();
doSomeThingB();
// do something
}

// 事务属性为MANDATORY
@Transactional(propagation = Propagation.NEWSTED)
public void methodB() {
// do something
}

当单独调用方法B时,因为上下文不存在事务,开启新的事务。
当通过调用方法A而调用到方法B时,方法B发现上下文有事务T1,调用setSavepoint方法,保存当前的状态到savepoint。
外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。

网上找了找资料,加上自己的理解,总结了一下这些传播行为。
当然上述所有的代码实现都在AbstractPlatformTransactionManager的方法getTransaction中:
简略地总结一下:

当前事务不存在

PROPAGATION_MANDATORY = 2

抛出异常。

1
2
3
4
5
6
7
// PROPAGATION_MANDATORY = 2; 支持当前事务;如果当前事务不存在,则抛出异常
// mandatory:强制的
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
//没有为标记为传播“mandatory”的事务找到现有事务
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
PROPAGATION_REQUIRED = 0;PROPAGATION_REQUIRES_NEW = 3;PROPAGATION_NESTED = 6;

新建事务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// required,nested:嵌套的
// PROPAGATION_REQUIRED = 0; 支持当前事务;如果不存在,创建一个新的。
// PROPAGATION_REQUIRES_NEW = 3; 创建一个新事务,如果存在当前事务,则挂起当前事务。
// PROPAGATION_NESTED = 6; 如果当前事务存在,则在嵌套事务中执行,否则行为类似PROPAGATION_REQUIRED。
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 暂停给定的事务。首先挂起事务同步,然后委托给 doSuspend模板方法。
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
//getTransactionSynchronization():返回此事务管理器是否应激活线程绑定事务同步支持。
//SYNCHRONIZATION_NEVER:2,永远不要进行活动事务同步,即使对于实际事务也是如此。
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
//创建DefaultTransactionStatus对象
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//根据给定的事务定义使用语义开始一个新的事务。
//由子类实现
doBegin(transaction, definition);
//根据需要初始化事务同步。
prepareSynchronization(status, definition);
return status;
} catch (RuntimeException | Error ex) {
//恢复
resume(null, suspendedResources);
throw ex;
}
}

如果新建的事务出现问题,直接回滚。

PROPAGATION_SUPPORTS = 1;PROPAGATION_NOT_SUPPORTED = 4;PROPAGATION_NEVER = 5;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// PROPAGATION_SUPPORTS = 1;支持当前事务;如果不存在非事务执行。
// PROPAGATION_NOT_SUPPORTED = 4;不支持当前事务;而是始终以非事务方式执行。
// PROPAGATION_NEVER = 5; 不支持当前事务;如果当前事务存在,则抛出异常。
// supports,never
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
// 创建“空”事务:没有实际事务,但可能同步。
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);
}

以非事务方式进行。

当前事务存在

在方法handleExistingTransaction中实现:

PROPAGATION_NEVER = 5;
1
2
3
4
5
6
// PROPAGATION_NEVER = 5; 不支持当前事务;如果当前事务存在,则抛出异常。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
//为标记为传播“never”的事务找到的现有事务
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
PROPAGATION_NOT_SUPPORTED = 4;
1
2
3
4
5
6
7
8
9
10
11
12
// PROPAGATION_NOT_SUPPORTED = 4;不支持当前事务;而是始终以非事务方式执行。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
// 暂停给定的事务。首先挂起事务同步,然后委托给{@code doSuspend}模板方法。
Object suspendedResources = suspend(transaction);
// SYNCHRONIZATION_ALWAYS:始终激活事务同步,即使对于没有任何后端事务的“空”事务,也要激活它。
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
PROPAGATION_REQUIRES_NEW = 3;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// PROPAGATION_REQUIRES_NEW = 3; 创建一个新事务,如果存在当前事务,则挂起当前事务。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
// 暂停给定的事务。首先挂起事务同步,然后委托给{@code doSuspend}模板方法。
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
//SYNCHRONIZATION_NEVER:永远不要进行活动事务同步,即使对于实际事务也是如此。
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//根据给定的事务定义使用语义开始一个新的事务
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
} catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
PROPAGATION_NESTED = 6;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// PROPAGATION_NESTED = 6; 如果当前事务存在,则在嵌套事务中执行,否则行为类似PROPAGATION_REQUIRED。
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()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
//创建一个保存点,并为事务保存它。
status.createAndHoldSavepoint();
return status;
} else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
//根据给定的事务定义使用语义开始一个新的事务
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
}

PROPAGATION_REQUIRED = 0;PROPAGATION_MANDATORY = 2;PROPAGATION_SUPPORTS = 1;

加入到上下文中的事务中执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//返回在参与现有事务之前是否应该验证它们。
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");
}
}
}
//SYNCHRONIZATION_NEVER: 永远不要进行活动事务同步,即使对于实际事务也是如此。
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);

tencent.jpg

文章作者: ClawHub
文章链接: https://www.clawhub.club/posts/2019/08/22/Spring%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/Spring-TX%E3%80%90%E4%B8%89%E3%80%91getTransaction%E4%B9%8BSpring%E4%BA%8B%E5%8A%A1%E4%BC%A0%E6%92%AD%E8%A1%8C%E4%B8%BA%E4%B8%8E%E6%95%B0%E6%8D%AE%E6%BA%90%E8%BF%9E%E6%8E%A5%E7%BB%91%E5%AE%9A/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ClawHub的博客
打赏
  • 微信
  • 支付宝
扫一扫关注ClawHub公众号,专注Java、技术分享、面试资源。