80
80
* transaction definitions for vendor-specific attributes.
81
81
*
82
82
* @author Mark Paluch
83
+ * @author Juergen Hoeller
83
84
* @since 5.3
84
85
* @see ConnectionFactoryUtils#getConnection(ConnectionFactory)
85
86
* @see ConnectionFactoryUtils#releaseConnection
@@ -149,7 +150,7 @@ protected ConnectionFactory obtainConnectionFactory() {
149
150
* transactional connection: "SET TRANSACTION READ ONLY" as understood by Oracle,
150
151
* MySQL and Postgres.
151
152
* <p>The exact treatment, including any SQL statement executed on the connection,
152
- * can be customized through through {@link #prepareTransactionalConnection}.
153
+ * can be customized through {@link #prepareTransactionalConnection}.
153
154
* @see #prepareTransactionalConnection
154
155
*/
155
156
public void setEnforceReadOnly (boolean enforceReadOnly ) {
@@ -209,8 +210,9 @@ protected Mono<Void> doBegin(TransactionSynchronizationManager synchronizationMa
209
210
connectionMono = Mono .just (txObject .getConnectionHolder ().getConnection ());
210
211
}
211
212
212
- return connectionMono .flatMap (con -> prepareTransactionalConnection (con , definition , transaction )
213
+ return connectionMono .flatMap (con -> switchAutoCommitIfNecessary (con , transaction )
213
214
.then (Mono .from (doBegin (definition , con )))
215
+ .then (prepareTransactionalConnection (con , definition ))
214
216
.doOnSuccess (v -> {
215
217
txObject .getConnectionHolder ().setTransactionActive (true );
216
218
Duration timeout = determineTimeout (definition );
@@ -375,6 +377,24 @@ protected Mono<Void> doCleanupAfterCompletion(TransactionSynchronizationManager
375
377
});
376
378
}
377
379
380
+ private Mono <Void > switchAutoCommitIfNecessary (Connection con , Object transaction ) {
381
+ ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject ) transaction ;
382
+ Mono <Void > prepare = Mono .empty ();
383
+
384
+ // Switch to manual commit if necessary. This is very expensive in some R2DBC drivers,
385
+ // so we don't want to do it unnecessarily (for example if we've explicitly
386
+ // configured the connection pool to set it already).
387
+ if (con .isAutoCommit ()) {
388
+ txObject .setMustRestoreAutoCommit (true );
389
+ if (logger .isDebugEnabled ()) {
390
+ logger .debug ("Switching R2DBC Connection [" + con + "] to manual commit" );
391
+ }
392
+ prepare = prepare .then (Mono .from (con .setAutoCommit (false )));
393
+ }
394
+
395
+ return prepare ;
396
+ }
397
+
378
398
/**
379
399
* Prepare the transactional {@link Connection} right after transaction begin.
380
400
* <p>The default implementation executes a "SET TRANSACTION READ ONLY" statement if the
@@ -385,33 +405,16 @@ protected Mono<Void> doCleanupAfterCompletion(TransactionSynchronizationManager
385
405
* override this method accordingly.
386
406
* @param con the transactional R2DBC Connection
387
407
* @param definition the current transaction definition
388
- * @param transaction the transaction object
408
+ * @since 5.3.22
389
409
* @see #setEnforceReadOnly
390
410
*/
391
- protected Mono <Void > prepareTransactionalConnection (
392
- Connection con , TransactionDefinition definition , Object transaction ) {
393
-
394
- ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject ) transaction ;
395
-
411
+ protected Mono <Void > prepareTransactionalConnection (Connection con , TransactionDefinition definition ) {
396
412
Mono <Void > prepare = Mono .empty ();
397
-
398
413
if (isEnforceReadOnly () && definition .isReadOnly ()) {
399
414
prepare = Mono .from (con .createStatement ("SET TRANSACTION READ ONLY" ).execute ())
400
415
.flatMapMany (Result ::getRowsUpdated )
401
416
.then ();
402
417
}
403
-
404
- // Switch to manual commit if necessary. This is very expensive in some R2DBC drivers,
405
- // so we don't want to do it unnecessarily (for example if we've explicitly
406
- // configured the connection pool to set it already).
407
- if (con .isAutoCommit ()) {
408
- txObject .setMustRestoreAutoCommit (true );
409
- if (logger .isDebugEnabled ()) {
410
- logger .debug ("Switching R2DBC Connection [" + con + "] to manual commit" );
411
- }
412
- prepare = prepare .then (Mono .from (con .setAutoCommit (false )));
413
- }
414
-
415
418
return prepare ;
416
419
}
417
420
@@ -452,21 +455,20 @@ protected RuntimeException translateException(String task, R2dbcException ex) {
452
455
* to R2DBC drivers when starting a transaction.
453
456
*/
454
457
private record ExtendedTransactionDefinition (@ Nullable String transactionName ,
455
- boolean readOnly ,
456
- @ Nullable IsolationLevel isolationLevel ,
457
- Duration lockWaitTimeout ) implements io .r2dbc .spi .TransactionDefinition {
458
+ boolean readOnly , @ Nullable IsolationLevel isolationLevel , Duration lockWaitTimeout )
459
+ implements io .r2dbc .spi .TransactionDefinition {
458
460
459
461
private ExtendedTransactionDefinition (@ Nullable String transactionName , boolean readOnly ,
460
462
@ Nullable IsolationLevel isolationLevel , Duration lockWaitTimeout ) {
463
+
461
464
this .transactionName = transactionName ;
462
465
this .readOnly = readOnly ;
463
466
this .isolationLevel = isolationLevel ;
464
467
this .lockWaitTimeout = lockWaitTimeout ;
465
468
}
466
469
467
-
468
- @ Override
469
470
@ SuppressWarnings ("unchecked" )
471
+ @ Override
470
472
public <T > T getAttribute (Option <T > option ) {
471
473
return (T ) doGetValue (option );
472
474
}
0 commit comments