Merge branch '6.0.x'
This commit is contained in:
commit
1218e65ca1
|
|
@ -151,10 +151,10 @@ Kotlin::
|
|||
----
|
||||
======
|
||||
|
||||
The last example we show here is for typical JDBC support. You could have the
|
||||
`DataSource` injected into an initialization method or a constructor, where you would create a
|
||||
`JdbcTemplate` and other data access support classes (such as `SimpleJdbcCall` and others) by using
|
||||
this `DataSource`. The following example autowires a `DataSource`:
|
||||
The last example we show here is for typical JDBC support. You could have the `DataSource`
|
||||
injected into an initialization method or a constructor, where you would create a `JdbcTemplate`
|
||||
and other data access support classes (such as `SimpleJdbcCall` and others) by using this
|
||||
`DataSource`. The following example autowires a `DataSource`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ to the database.
|
|||
[[jdbc-batch-classic]]
|
||||
== Basic Batch Operations with `JdbcTemplate`
|
||||
|
||||
You accomplish `JdbcTemplate` batch processing by implementing two methods of a special
|
||||
interface, `BatchPreparedStatementSetter`, and passing that implementation in as the second parameter
|
||||
You accomplish `JdbcTemplate` batch processing by implementing two methods of a special interface,
|
||||
`BatchPreparedStatementSetter`, and passing that implementation in as the second parameter
|
||||
in your `batchUpdate` method call. You can use the `getBatchSize` method to provide the size of
|
||||
the current batch. You can use the `setValues` method to set the values for the parameters of
|
||||
the prepared statement. This method is called the number of times that you
|
||||
specified in the `getBatchSize` call. The following example updates the `t_actor` table
|
||||
based on entries in a list, and the entire list is used as the batch:
|
||||
the prepared statement. This method is called the number of times that you specified in the
|
||||
`getBatchSize` call. The following example updates the `t_actor` table based on entries in a list,
|
||||
and the entire list is used as the batch:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ This section covers:
|
|||
* xref:data-access/jdbc/connections.adoc#jdbc-SingleConnectionDataSource[Using `SingleConnectionDataSource`]
|
||||
* xref:data-access/jdbc/connections.adoc#jdbc-DriverManagerDataSource[Using `DriverManagerDataSource`]
|
||||
* xref:data-access/jdbc/connections.adoc#jdbc-TransactionAwareDataSourceProxy[Using `TransactionAwareDataSourceProxy`]
|
||||
* xref:data-access/jdbc/connections.adoc#jdbc-DataSourceTransactionManager[Using `DataSourceTransactionManager`]
|
||||
* xref:data-access/jdbc/connections.adoc#jdbc-DataSourceTransactionManager[Using `DataSourceTransactionManager` / `JdbcTransactionManager`]
|
||||
|
||||
|
||||
[[jdbc-datasource]]
|
||||
|
|
@ -125,8 +125,12 @@ The following example shows C3P0 configuration:
|
|||
== Using `DataSourceUtils`
|
||||
|
||||
The `DataSourceUtils` class is a convenient and powerful helper class that provides
|
||||
`static` methods to obtain connections from JNDI and close connections if necessary. It
|
||||
supports thread-bound connections with, for example, `DataSourceTransactionManager`.
|
||||
`static` methods to obtain connections from JNDI and close connections if necessary.
|
||||
It supports a thread-bound JDBC `Connection` with `DataSourceTransactionManager` but
|
||||
also with `JtaTransactionManager` and `JpaTransactionManager`.
|
||||
|
||||
Note that `JdbcTemplate` implies `DataSourceUtils` connection access, using it
|
||||
behind every JDBC operation, implicitly participating in an ongoing transaction.
|
||||
|
||||
|
||||
[[jdbc-SmartDataSource]]
|
||||
|
|
@ -165,7 +169,6 @@ In contrast to `DriverManagerDataSource`, it reuses the same connection all the
|
|||
avoiding excessive creation of physical connections.
|
||||
|
||||
|
||||
|
||||
[[jdbc-DriverManagerDataSource]]
|
||||
== Using `DriverManagerDataSource`
|
||||
|
||||
|
|
@ -201,29 +204,44 @@ javadoc for more details.
|
|||
|
||||
|
||||
[[jdbc-DataSourceTransactionManager]]
|
||||
== Using `DataSourceTransactionManager`
|
||||
== Using `DataSourceTransactionManager` / `JdbcTransactionManager`
|
||||
|
||||
The `DataSourceTransactionManager` class is a `PlatformTransactionManager`
|
||||
implementation for single JDBC data sources. It binds a JDBC connection from the
|
||||
specified data source to the currently executing thread, potentially allowing for one
|
||||
thread connection per data source.
|
||||
implementation for a single JDBC `DataSource`. It binds a JDBC `Connection`
|
||||
from the specified `DataSource` to the currently executing thread, potentially
|
||||
allowing for one thread-bound `Connection` per `DataSource`.
|
||||
|
||||
Application code is required to retrieve the JDBC connection through
|
||||
`DataSourceUtils.getConnection(DataSource)` instead of Jakarta EE's standard
|
||||
Application code is required to retrieve the JDBC `Connection` through
|
||||
`DataSourceUtils.getConnection(DataSource)` instead of Java EE's standard
|
||||
`DataSource.getConnection`. It throws unchecked `org.springframework.dao` exceptions
|
||||
instead of checked `SQLExceptions`. All framework classes (such as `JdbcTemplate`) use this
|
||||
strategy implicitly. If not used with this transaction manager, the lookup strategy
|
||||
behaves exactly like the common one. Thus, it can be used in any case.
|
||||
instead of checked `SQLExceptions`. All framework classes (such as `JdbcTemplate`) use
|
||||
this strategy implicitly. If not used with a transaction manager, the lookup strategy
|
||||
behaves exactly like `DataSource.getConnection` and can therefore be used in any case.
|
||||
|
||||
The `DataSourceTransactionManager` class supports custom isolation levels and timeouts
|
||||
that get applied as appropriate JDBC statement query timeouts. To support the latter,
|
||||
application code must either use `JdbcTemplate` or call the
|
||||
`DataSourceUtils.applyTransactionTimeout(..)` method for each created statement.
|
||||
The `DataSourceTransactionManager` class supports savepoints (`PROPAGATION_NESTED`),
|
||||
custom isolation levels, and timeouts that get applied as appropriate JDBC statement
|
||||
query timeouts. To support the latter, application code must either use `JdbcTemplate` or
|
||||
call the `DataSourceUtils.applyTransactionTimeout(..)` method for each created statement.
|
||||
|
||||
You can use this implementation instead of `JtaTransactionManager` in the single-resource
|
||||
case, as it does not require the container to support JTA. Switching between
|
||||
both is just a matter of configuration, provided you stick to the required connection lookup
|
||||
pattern. JTA does not support custom isolation levels.
|
||||
You can use `DataSourceTransactionManager` instead of `JtaTransactionManager` in the
|
||||
single-resource case, as it does not require the container to support a JTA transaction
|
||||
coordinator. Switching between these transaction managers is just a matter of configuration,
|
||||
provided you stick to the required connection lookup pattern. Note that JTA does not support
|
||||
savepoints or custom isolation levels and has a different timeout mechanism but otherwise
|
||||
exposes similar behavior in terms of JDBC resources and JDBC commit/rollback management.
|
||||
|
||||
NOTE: As of 5.3, Spring provides an extended `JdbcTransactionManager` variant which adds
|
||||
exception translation capabilities on commit/rollback (aligned with `JdbcTemplate`).
|
||||
Where `DataSourceTransactionManager` will only ever throw `TransactionSystemException`
|
||||
(analogous to JTA), `JdbcTransactionManager` translates database locking failures etc to
|
||||
corresponding `DataAccessException` subclasses. Note that application code needs to be
|
||||
prepared for such exceptions, not exclusively expecting `TransactionSystemException`.
|
||||
In scenarios where that is the case, `JdbcTransactionManager` is the recommended choice.
|
||||
|
||||
In terms of exception behavior, `JdbcTransactionManager` is roughly equivalent to
|
||||
`JpaTransactionManager` and also to `R2dbcTransactionManager`, serving as an immediate
|
||||
companion/replacement for each other. `DataSourceTransactionManager` on the other hand
|
||||
is equivalent to `JtaTransactionManager` and can serve as a direct replacement there.
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -718,12 +718,22 @@ See also xref:data-access/jdbc/core.adoc#jdbc-JdbcTemplate-idioms[`JdbcTemplate`
|
|||
between ``SQLException``s and Spring's own `org.springframework.dao.DataAccessException`,
|
||||
which is agnostic in regard to data access strategy. Implementations can be generic (for
|
||||
example, using SQLState codes for JDBC) or proprietary (for example, using Oracle error
|
||||
codes) for greater precision.
|
||||
codes) for greater precision. This exception translation mechanism is used behind the
|
||||
the common `JdbcTemplate` and `JdbcTransactionManager` entry points which do not
|
||||
propagate `SQLException` but rather `DataAccessException`.
|
||||
|
||||
NOTE: As of 6.0, the default exception translator is `SQLExceptionSubclassTranslator`,
|
||||
detecting JDBC 4 `SQLException` subclasses with a few extra checks, and with a fallback
|
||||
to `SQLState` introspection through `SQLStateSQLExceptionTranslator`. This is usually
|
||||
sufficient for common database access and does not require vendor-specific detection.
|
||||
For backwards compatibility, consider using `SQLErrorCodeSQLExceptionTranslator` as
|
||||
described below, potentially with custom error code mappings.
|
||||
|
||||
`SQLErrorCodeSQLExceptionTranslator` is the implementation of `SQLExceptionTranslator`
|
||||
that is used by default. This implementation uses specific vendor codes. It is more
|
||||
precise than the `SQLState` implementation. The error code translations are based on
|
||||
codes held in a JavaBean type class called `SQLErrorCodes`. This class is created and
|
||||
that is used by default when a file named `sql-error-codes.xml` is present in the root
|
||||
of the classpath. This implementation uses specific vendor codes. It is more precise than
|
||||
`SQLState` or `SQLException` subclass translation. The error code translations are based
|
||||
on codes held in a JavaBean type class called `SQLErrorCodes`. This class is created and
|
||||
populated by an `SQLErrorCodesFactory`, which (as the name suggests) is a factory for
|
||||
creating `SQLErrorCodes` based on the contents of a configuration file named
|
||||
`sql-error-codes.xml`. This file is populated with vendor codes and based on the
|
||||
|
|
@ -744,8 +754,8 @@ The `SQLErrorCodeSQLExceptionTranslator` applies matching rules in the following
|
|||
translator. If this translation is not available, the next fallback translator is
|
||||
the `SQLStateSQLExceptionTranslator`.
|
||||
|
||||
NOTE: The `SQLErrorCodesFactory` is used by default to define `Error` codes and custom exception
|
||||
translations. They are looked up in a file named `sql-error-codes.xml` from the
|
||||
NOTE: The `SQLErrorCodesFactory` is used by default to define error codes and custom
|
||||
exception translations. They are looked up in a file named `sql-error-codes.xml` from the
|
||||
classpath, and the matching `SQLErrorCodes` instance is located based on the database
|
||||
name from the database metadata of the database in use.
|
||||
|
||||
|
|
@ -784,12 +794,12 @@ Kotlin::
|
|||
----
|
||||
======
|
||||
|
||||
In the preceding example, the specific error code (`-12345`) is translated, while other errors are
|
||||
left to be translated by the default translator implementation. To use this custom
|
||||
translator, you must pass it to the `JdbcTemplate` through the method
|
||||
`setExceptionTranslator`, and you must use this `JdbcTemplate` for all of the data access
|
||||
processing where this translator is needed. The following example shows how you can use this custom
|
||||
translator:
|
||||
In the preceding example, the specific error code (`-12345`) is translated while
|
||||
other errors are left to be translated by the default translator implementation.
|
||||
To use this custom translator, you must pass it to the `JdbcTemplate` through the
|
||||
method `setExceptionTranslator`, and you must use this `JdbcTemplate` for all of the
|
||||
data access processing where this translator is needed. The following example shows
|
||||
how you can use this custom translator:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
|
@ -800,7 +810,6 @@ Java::
|
|||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
|
||||
// create a JdbcTemplate and set data source
|
||||
this.jdbcTemplate = new JdbcTemplate();
|
||||
this.jdbcTemplate.setDataSource(dataSource);
|
||||
|
|
@ -809,7 +818,6 @@ Java::
|
|||
CustomSQLErrorCodesTranslator tr = new CustomSQLErrorCodesTranslator();
|
||||
tr.setDataSource(dataSource);
|
||||
this.jdbcTemplate.setExceptionTranslator(tr);
|
||||
|
||||
}
|
||||
|
||||
public void updateShippingCharge(long orderId, long pct) {
|
||||
|
|
|
|||
|
|
@ -3,30 +3,30 @@
|
|||
|
||||
The Spring Framework's JDBC abstraction framework consists of four different packages:
|
||||
|
||||
* `core`: The `org.springframework.jdbc.core` package contains the `JdbcTemplate` class and its
|
||||
various callback interfaces, plus a variety of related classes. A subpackage named
|
||||
`org.springframework.jdbc.core.simple` contains the `SimpleJdbcInsert` and
|
||||
* `core`: The `org.springframework.jdbc.core` package contains the `JdbcTemplate` class
|
||||
and its various callback interfaces, plus a variety of related classes. A subpackage
|
||||
named `org.springframework.jdbc.core.simple` contains the `SimpleJdbcInsert` and
|
||||
`SimpleJdbcCall` classes. Another subpackage named
|
||||
`org.springframework.jdbc.core.namedparam` contains the `NamedParameterJdbcTemplate`
|
||||
class and the related support classes. See xref:data-access/jdbc/core.adoc[Using the JDBC Core Classes to Control Basic JDBC Processing and Error Handling], xref:data-access/jdbc/advanced.adoc[JDBC Batch Operations], and
|
||||
xref:data-access/jdbc/simple.adoc[Simplifying JDBC Operations with the `SimpleJdbc` Classes].
|
||||
|
||||
* `datasource`: The `org.springframework.jdbc.datasource` package contains a utility class for easy
|
||||
`DataSource` access and various simple `DataSource` implementations that you can use for
|
||||
testing and running unmodified JDBC code outside of a Jakarta EE container. A subpackage
|
||||
named `org.springfamework.jdbc.datasource.embedded` provides support for creating
|
||||
* `datasource`: The `org.springframework.jdbc.datasource` package contains a utility class
|
||||
for easy `DataSource` access and various simple `DataSource` implementations that you can
|
||||
use for testing and running unmodified JDBC code outside of a Jakarta EE container. A subpackage
|
||||
named `org.springframework.jdbc.datasource.embedded` provides support for creating
|
||||
embedded databases by using Java database engines, such as HSQL, H2, and Derby. See
|
||||
xref:data-access/jdbc/connections.adoc[Controlling Database Connections] and xref:data-access/jdbc/embedded-database-support.adoc[Embedded Database Support].
|
||||
|
||||
* `object`: The `org.springframework.jdbc.object` package contains classes that represent RDBMS
|
||||
queries, updates, and stored procedures as thread-safe, reusable objects. See
|
||||
* `object`: The `org.springframework.jdbc.object` package contains classes that represent
|
||||
RDBMS queries, updates, and stored procedures as thread-safe, reusable objects. See
|
||||
xref:data-access/jdbc/object.adoc[Modeling JDBC Operations as Java Objects]. This approach is modeled by JDO, although objects returned by queries
|
||||
are naturally disconnected from the database. This higher-level of JDBC abstraction
|
||||
depends on the lower-level abstraction in the `org.springframework.jdbc.core` package.
|
||||
|
||||
* `support`: The `org.springframework.jdbc.support` package provides `SQLException` translation
|
||||
functionality and some utility classes. Exceptions thrown during JDBC processing are
|
||||
translated to exceptions defined in the `org.springframework.dao` package. This means
|
||||
* `support`: The `org.springframework.jdbc.support` package provides `SQLException`
|
||||
translation functionality and some utility classes. Exceptions thrown during JDBC processing
|
||||
are translated to exceptions defined in the `org.springframework.dao` package. This means
|
||||
that code using the Spring JDBC abstraction layer does not need to implement JDBC or
|
||||
RDBMS-specific error handling. All translated exceptions are unchecked, which gives you
|
||||
the option of catching the exceptions from which you can recover while letting other
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ features supported by Spring, usually in a vendor-specific manner:
|
|||
* Applying specific transaction semantics (such as custom isolation level or transaction
|
||||
timeout)
|
||||
* Retrieving the transactional JDBC `Connection` (for exposure to JDBC-based DAOs)
|
||||
* Advanced translation of `PersistenceExceptions` to Spring `DataAccessExceptions`
|
||||
* Advanced translation of `PersistenceException` to Spring's `DataAccessException`
|
||||
|
||||
This is particularly valuable for special transaction semantics and for advanced
|
||||
translation of exception. The default implementation (`DefaultJpaDialect`) does
|
||||
|
|
|
|||
|
|
@ -718,19 +718,15 @@ javadoc for more details.
|
|||
=== Using `R2dbcTransactionManager`
|
||||
|
||||
The `R2dbcTransactionManager` class is a `ReactiveTransactionManager` implementation for
|
||||
single R2DBC data sources. It binds an R2DBC connection from the specified connection factory
|
||||
to the subscriber `Context`, potentially allowing for one subscriber connection for each
|
||||
connection factory.
|
||||
a single R2DBC `ConnectionFactory`. It binds an R2DBC `Connection` from the specified
|
||||
`ConnectionFactory` to the subscriber `Context`, potentially allowing for one subscriber
|
||||
`Connection` for each `ConnectionFactory`.
|
||||
|
||||
Application code is required to retrieve the R2DBC connection through
|
||||
Application code is required to retrieve the R2DBC `Connection` through
|
||||
`ConnectionFactoryUtils.getConnection(ConnectionFactory)`, instead of R2DBC's standard
|
||||
`ConnectionFactory.create()`.
|
||||
|
||||
All framework classes (such as `DatabaseClient`) use this strategy implicitly.
|
||||
If not used with this transaction manager, the lookup strategy behaves exactly like the common one.
|
||||
Thus, it can be used in any case.
|
||||
|
||||
The `R2dbcTransactionManager` class supports custom isolation levels that get applied to the connection.
|
||||
`ConnectionFactory.create()`. All framework classes (such as `DatabaseClient`) use this
|
||||
strategy implicitly. If not used with a transaction manager, the lookup strategy behaves
|
||||
exactly like `ConnectionFactory.create()` and can therefore be used in any case.
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@ In XML configuration, the `<tx:annotation-driven/>` tag provides similar conveni
|
|||
----
|
||||
<1> The line that makes the bean instance transactional.
|
||||
|
||||
|
||||
TIP: You can omit the `transaction-manager` attribute in the `<tx:annotation-driven/>`
|
||||
tag if the bean name of the `TransactionManager` that you want to wire in has the name
|
||||
`transactionManager`. If the `TransactionManager` bean that you want to dependency-inject
|
||||
|
|
@ -522,17 +521,17 @@ The following listing shows the bean declarations:
|
|||
----
|
||||
<tx:annotation-driven/>
|
||||
|
||||
<bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
|
||||
<bean id="transactionManager1" class="org.springframework.jdbc.support.JdbcTransactionManager">
|
||||
...
|
||||
<qualifier value="order"/>
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
|
||||
<bean id="transactionManager2" class="org.springframework.jdbc.support.JdbcTransactionManager">
|
||||
...
|
||||
<qualifier value="account"/>
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager3" class="org.springframework.data.r2dbc.connectionfactory.R2dbcTransactionManager">
|
||||
<bean id="transactionManager3" class="org.springframework.data.r2dbc.connection.R2dbcTransactionManager">
|
||||
...
|
||||
<qualifier value="reactive-account"/>
|
||||
</bean>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import org.springframework.beans.factory.InitializingBean;
|
|||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.CannotCreateTransactionException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.reactive.AbstractReactiveTransactionManager;
|
||||
import org.springframework.transaction.reactive.GenericReactiveTransaction;
|
||||
import org.springframework.transaction.reactive.TransactionSynchronizationManager;
|
||||
|
|
@ -170,7 +169,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction(TransactionSynchronizationManager synchronizationManager) throws TransactionException {
|
||||
protected Object doGetTransaction(TransactionSynchronizationManager synchronizationManager) {
|
||||
ConnectionFactoryTransactionObject txObject = new ConnectionFactoryTransactionObject();
|
||||
ConnectionHolder conHolder = (ConnectionHolder) synchronizationManager.getResource(obtainConnectionFactory());
|
||||
txObject.setConnectionHolder(conHolder, false);
|
||||
|
|
@ -184,7 +183,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
|||
|
||||
@Override
|
||||
protected Mono<Void> doBegin(TransactionSynchronizationManager synchronizationManager, Object transaction,
|
||||
TransactionDefinition definition) throws TransactionException {
|
||||
TransactionDefinition definition) {
|
||||
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) transaction;
|
||||
|
||||
|
|
@ -275,9 +274,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Mono<Object> doSuspend(TransactionSynchronizationManager synchronizationManager, Object transaction)
|
||||
throws TransactionException {
|
||||
|
||||
protected Mono<Object> doSuspend(TransactionSynchronizationManager synchronizationManager, Object transaction) {
|
||||
return Mono.defer(() -> {
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) transaction;
|
||||
txObject.setConnectionHolder(null);
|
||||
|
|
@ -287,7 +284,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
|||
|
||||
@Override
|
||||
protected Mono<Void> doResume(TransactionSynchronizationManager synchronizationManager,
|
||||
@Nullable Object transaction, Object suspendedResources) throws TransactionException {
|
||||
@Nullable Object transaction, Object suspendedResources) {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
synchronizationManager.bindResource(obtainConnectionFactory(), suspendedResources);
|
||||
|
|
@ -297,7 +294,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
|||
|
||||
@Override
|
||||
protected Mono<Void> doCommit(TransactionSynchronizationManager TransactionSynchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
|
|
@ -309,7 +306,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
|||
|
||||
@Override
|
||||
protected Mono<Void> doRollback(TransactionSynchronizationManager TransactionSynchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
|
|
@ -321,7 +318,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
|||
|
||||
@Override
|
||||
protected Mono<Void> doSetRollbackOnly(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
return Mono.fromRunnable(() -> {
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) status.getTransaction();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -31,10 +31,10 @@ import org.springframework.lang.Nullable;
|
|||
* template methods for specific states of the underlying transaction,
|
||||
* for example: begin, suspend, resume, commit.
|
||||
*
|
||||
* <p>The default implementations of this strategy interface are
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager} and
|
||||
* {@link org.springframework.jdbc.datasource.DataSourceTransactionManager},
|
||||
* which can serve as an implementation guide for other transaction strategies.
|
||||
* <p>A classic implementation of this strategy interface is
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager}. However,
|
||||
* in common single-resource scenarios, Spring's specific transaction managers
|
||||
* for e.g. JDBC, JPA, JMS are preferred choices.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
|
|
@ -81,12 +81,9 @@ public interface PlatformTransactionManager extends TransactionManager {
|
|||
* <p>Note that when the commit call completes, no matter if normally or
|
||||
* throwing an exception, the transaction must be fully completed and
|
||||
* cleaned up. No rollback call should be expected in such a case.
|
||||
* <p>If this method throws an exception other than a TransactionException,
|
||||
* then some before-commit error caused the commit attempt to fail. For
|
||||
* example, an O/R Mapping tool might have tried to flush changes to the
|
||||
* database right before commit, with the resulting DataAccessException
|
||||
* causing the transaction to fail. The original exception will be
|
||||
* propagated to the caller of this commit method in such a case.
|
||||
* <p>Depending on the concrete transaction manager setup, {@code commit}
|
||||
* may propagate {@link org.springframework.dao.DataAccessException} as well,
|
||||
* either from before-commit flushes or from the actual commit step.
|
||||
* @param status object returned by the {@code getTransaction} method
|
||||
* @throws UnexpectedRollbackException in case of an unexpected rollback
|
||||
* that the transaction coordinator initiated
|
||||
|
|
@ -110,6 +107,8 @@ public interface PlatformTransactionManager extends TransactionManager {
|
|||
* The transaction will already have been completed and cleaned up when commit
|
||||
* returns, even in case of a commit exception. Consequently, a rollback call
|
||||
* after commit failure will lead to an IllegalTransactionStateException.
|
||||
* <p>Depending on the concrete transaction manager setup, {@code rollback}
|
||||
* may propagate {@link org.springframework.dao.DataAccessException} as well.
|
||||
* @param status object returned by the {@code getTransaction} method
|
||||
* @throws TransactionSystemException in case of rollback or system errors
|
||||
* (typically caused by fundamental resource failures)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -46,6 +46,8 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
|||
* <p>An exception to the above rule is the read-only flag, which should be
|
||||
* ignored if no explicit read-only mode is supported. Essentially, the
|
||||
* read-only flag is just a hint for potential optimization.
|
||||
* <p>Note: In contrast to {@link PlatformTransactionManager}, exceptions
|
||||
* are propagated through the reactive pipeline returned from this method.
|
||||
* @param definition the TransactionDefinition instance,
|
||||
* describing propagation behavior, isolation level, timeout etc.
|
||||
* @return transaction status object representing the new or current transaction
|
||||
|
|
@ -58,8 +60,7 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
|||
* @see TransactionDefinition#getTimeout
|
||||
* @see TransactionDefinition#isReadOnly
|
||||
*/
|
||||
Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition)
|
||||
throws TransactionException;
|
||||
Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition);
|
||||
|
||||
/**
|
||||
* Commit the given transaction, with regard to its status. If the transaction
|
||||
|
|
@ -69,14 +70,12 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
|||
* has been suspended to be able to create a new one, resume the previous
|
||||
* transaction after committing the new one.
|
||||
* <p>Note that when the commit call completes, no matter if normally or
|
||||
* throwing an exception, the transaction must be fully completed and
|
||||
* propagating an exception, the transaction must be fully completed and
|
||||
* cleaned up. No rollback call should be expected in such a case.
|
||||
* <p>If this method throws an exception other than a TransactionException,
|
||||
* then some before-commit error caused the commit attempt to fail. For
|
||||
* example, an O/R Mapping tool might have tried to flush changes to the
|
||||
* database right before commit, with the resulting DataAccessException
|
||||
* causing the transaction to fail. The original exception will be
|
||||
* propagated to the caller of this commit method in such a case.
|
||||
* <p>Note: In contrast to {@link PlatformTransactionManager}, exceptions
|
||||
* are propagated through the reactive pipeline returned from this method.
|
||||
* Also, depending on the transaction manager implementation, {@code commit}
|
||||
* may propagate {@link org.springframework.dao.DataAccessException} as well.
|
||||
* @param transaction object returned by the {@code getTransaction} method
|
||||
* @throws UnexpectedRollbackException in case of an unexpected rollback
|
||||
* that the transaction coordinator initiated
|
||||
|
|
@ -88,7 +87,7 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
|||
* is already completed (that is, committed or rolled back)
|
||||
* @see ReactiveTransaction#setRollbackOnly
|
||||
*/
|
||||
Mono<Void> commit(ReactiveTransaction transaction) throws TransactionException;
|
||||
Mono<Void> commit(ReactiveTransaction transaction);
|
||||
|
||||
/**
|
||||
* Perform a rollback of the given transaction.
|
||||
|
|
@ -96,16 +95,20 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
|||
* participation in the surrounding transaction. If a previous transaction
|
||||
* has been suspended to be able to create a new one, resume the previous
|
||||
* transaction after rolling back the new one.
|
||||
* <p><b>Do not call rollback on a transaction if commit threw an exception.</b>
|
||||
* <p><b>Do not call rollback on a transaction if commit failed.</b>
|
||||
* The transaction will already have been completed and cleaned up when commit
|
||||
* returns, even in case of a commit exception. Consequently, a rollback call
|
||||
* after commit failure will lead to an IllegalTransactionStateException.
|
||||
* <p>Note: In contrast to {@link PlatformTransactionManager}, exceptions
|
||||
* are propagated through the reactive pipeline returned from this method.
|
||||
* Also, depending on the transaction manager implementation, {@code rollback}
|
||||
* may propagate {@link org.springframework.dao.DataAccessException} as well.
|
||||
* @param transaction object returned by the {@code getTransaction} method
|
||||
* @throws TransactionSystemException in case of rollback or system errors
|
||||
* (typically caused by fundamental resource failures)
|
||||
* @throws IllegalTransactionStateException if the given transaction
|
||||
* is already completed (that is, committed or rolled back)
|
||||
*/
|
||||
Mono<Void> rollback(ReactiveTransaction transaction) throws TransactionException;
|
||||
Mono<Void> rollback(ReactiveTransaction transaction);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,9 +95,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* @see #doBegin
|
||||
*/
|
||||
@Override
|
||||
public final Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition)
|
||||
throws TransactionException {
|
||||
|
||||
public final Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition) {
|
||||
// Use defaults if no transaction definition given.
|
||||
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
|
||||
|
||||
|
|
@ -165,7 +163,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* Create a ReactiveTransaction for an existing transaction.
|
||||
*/
|
||||
private Mono<ReactiveTransaction> handleExistingTransaction(TransactionSynchronizationManager synchronizationManager,
|
||||
TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException {
|
||||
TransactionDefinition definition, Object transaction, boolean debugEnabled) {
|
||||
|
||||
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
|
||||
return Mono.error(new IllegalTransactionStateException(
|
||||
|
|
@ -277,7 +275,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* @see #resume
|
||||
*/
|
||||
private Mono<SuspendedResourcesHolder> suspend(TransactionSynchronizationManager synchronizationManager,
|
||||
@Nullable Object transaction) throws TransactionException {
|
||||
@Nullable Object transaction) {
|
||||
|
||||
if (synchronizationManager.isSynchronizationActive()) {
|
||||
Mono<List<TransactionSynchronization>> suspendedSynchronizations = doSuspendSynchronization(synchronizationManager);
|
||||
|
|
@ -325,8 +323,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* @see #suspend
|
||||
*/
|
||||
private Mono<Void> resume(TransactionSynchronizationManager synchronizationManager,
|
||||
@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
|
||||
throws TransactionException {
|
||||
@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder) {
|
||||
|
||||
Mono<Void> resume = Mono.empty();
|
||||
|
||||
|
|
@ -403,7 +400,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* @see #rollback
|
||||
*/
|
||||
@Override
|
||||
public final Mono<Void> commit(ReactiveTransaction transaction) throws TransactionException {
|
||||
public final Mono<Void> commit(ReactiveTransaction transaction) {
|
||||
if (transaction.isCompleted()) {
|
||||
return Mono.error(new IllegalTransactionStateException(
|
||||
"Transaction is already completed - do not call commit or rollback more than once per transaction"));
|
||||
|
|
@ -426,10 +423,9 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* Rollback-only flags have already been checked and applied.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status object representing the transaction
|
||||
* @throws TransactionException in case of commit failure
|
||||
*/
|
||||
private Mono<Void> processCommit(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
AtomicBoolean beforeCompletionInvoked = new AtomicBoolean();
|
||||
|
||||
|
|
@ -489,7 +485,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* @see #doSetRollbackOnly
|
||||
*/
|
||||
@Override
|
||||
public final Mono<Void> rollback(ReactiveTransaction transaction) throws TransactionException {
|
||||
public final Mono<Void> rollback(ReactiveTransaction transaction) {
|
||||
if (transaction.isCompleted()) {
|
||||
return Mono.error(new IllegalTransactionStateException(
|
||||
"Transaction is already completed - do not call commit or rollback more than once per transaction"));
|
||||
|
|
@ -505,7 +501,6 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* The completed flag has already been checked.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status object representing the transaction
|
||||
* @throws TransactionException in case of rollback failure
|
||||
*/
|
||||
private Mono<Void> processRollback(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) {
|
||||
|
|
@ -544,11 +539,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status object representing the transaction
|
||||
* @param ex the thrown application exception or error
|
||||
* @throws TransactionException in case of rollback failure
|
||||
* @see #doRollback
|
||||
*/
|
||||
private Mono<Void> doRollbackOnCommitException(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status, Throwable ex) throws TransactionException {
|
||||
GenericReactiveTransaction status, Throwable ex) {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
if (status.isNewTransaction()) {
|
||||
|
|
@ -716,14 +710,12 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* @return the current transaction object
|
||||
* @throws org.springframework.transaction.CannotCreateTransactionException
|
||||
* if transaction support is not available
|
||||
* @throws TransactionException in case of lookup or system errors
|
||||
* @see #doBegin
|
||||
* @see #doCommit
|
||||
* @see #doRollback
|
||||
* @see GenericReactiveTransaction#getTransaction
|
||||
*/
|
||||
protected abstract Object doGetTransaction(TransactionSynchronizationManager synchronizationManager)
|
||||
throws TransactionException;
|
||||
protected abstract Object doGetTransaction(TransactionSynchronizationManager synchronizationManager);
|
||||
|
||||
/**
|
||||
* Check if the given transaction object indicates an existing transaction
|
||||
|
|
@ -737,10 +729,9 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* Subclasses are of course encouraged to provide such support.
|
||||
* @param transaction the transaction object returned by doGetTransaction
|
||||
* @return if there is an existing transaction
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see #doGetTransaction
|
||||
*/
|
||||
protected boolean isExistingTransaction(Object transaction) throws TransactionException {
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -759,12 +750,11 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* @param transaction the transaction object returned by {@code doGetTransaction}
|
||||
* @param definition a TransactionDefinition instance, describing propagation
|
||||
* behavior, isolation level, read-only flag, timeout, and transaction name
|
||||
* @throws TransactionException in case of creation or system errors
|
||||
* @throws org.springframework.transaction.NestedTransactionNotSupportedException
|
||||
* if the underlying transaction does not support nesting (e.g. through savepoints)
|
||||
*/
|
||||
protected abstract Mono<Void> doBegin(TransactionSynchronizationManager synchronizationManager,
|
||||
Object transaction, TransactionDefinition definition) throws TransactionException;
|
||||
Object transaction, TransactionDefinition definition);
|
||||
|
||||
/**
|
||||
* Suspend the resources of the current transaction.
|
||||
|
|
@ -777,11 +767,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* (will be kept unexamined for passing it into doResume)
|
||||
* @throws org.springframework.transaction.TransactionSuspensionNotSupportedException
|
||||
* if suspending is not supported by the transaction manager implementation
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see #doResume
|
||||
*/
|
||||
protected Mono<Object> doSuspend(TransactionSynchronizationManager synchronizationManager,
|
||||
Object transaction) throws TransactionException {
|
||||
Object transaction) {
|
||||
|
||||
throw new TransactionSuspensionNotSupportedException(
|
||||
"Transaction manager [" + getClass().getName() + "] does not support transaction suspension");
|
||||
|
|
@ -798,11 +787,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* as returned by doSuspend
|
||||
* @throws org.springframework.transaction.TransactionSuspensionNotSupportedException
|
||||
* if suspending is not supported by the transaction manager implementation
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see #doSuspend
|
||||
*/
|
||||
protected Mono<Void> doResume(TransactionSynchronizationManager synchronizationManager,
|
||||
@Nullable Object transaction, Object suspendedResources) throws TransactionException {
|
||||
@Nullable Object transaction, Object suspendedResources) {
|
||||
|
||||
throw new TransactionSuspensionNotSupportedException(
|
||||
"Transaction manager [" + getClass().getName() + "] does not support transaction suspension");
|
||||
|
|
@ -832,11 +820,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* contained in the passed-in status.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status the status representation of the transaction
|
||||
* @throws TransactionException in case of commit or system errors
|
||||
* @see GenericReactiveTransaction#getTransaction
|
||||
*/
|
||||
protected abstract Mono<Void> doCommit(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException;
|
||||
GenericReactiveTransaction status);
|
||||
|
||||
/**
|
||||
* Perform an actual rollback of the given transaction.
|
||||
|
|
@ -845,11 +832,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* will be performed on the transaction object contained in the passed-in status.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status the status representation of the transaction
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see GenericReactiveTransaction#getTransaction
|
||||
*/
|
||||
protected abstract Mono<Void> doRollback(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException;
|
||||
GenericReactiveTransaction status);
|
||||
|
||||
/**
|
||||
* Set the given transaction rollback-only. Only called on rollback
|
||||
|
|
@ -859,10 +845,9 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* supported. Subclasses are of course encouraged to provide such support.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status the status representation of the transaction
|
||||
* @throws TransactionException in case of system errors
|
||||
*/
|
||||
protected Mono<Void> doSetRollbackOnly(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
throw new IllegalTransactionStateException(
|
||||
"Participating in existing transactions is not supported - when 'isExistingTransaction' " +
|
||||
|
|
@ -880,13 +865,12 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
|||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param transaction the transaction object returned by {@code doGetTransaction}
|
||||
* @param synchronizations a List of TransactionSynchronization objects
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see #invokeAfterCompletion(TransactionSynchronizationManager, List, int)
|
||||
* @see TransactionSynchronization#afterCompletion(int)
|
||||
* @see TransactionSynchronization#STATUS_UNKNOWN
|
||||
*/
|
||||
protected Mono<Void> registerAfterCompletionWithExistingTransaction(TransactionSynchronizationManager synchronizationManager,
|
||||
Object transaction, List<TransactionSynchronization> synchronizations) throws TransactionException {
|
||||
Object transaction, List<TransactionSynchronization> synchronizations) {
|
||||
|
||||
logger.debug("Cannot register Spring after-completion synchronization with existing transaction - " +
|
||||
"processing Spring after-completion callbacks immediately, with outcome status 'unknown'");
|
||||
|
|
|
|||
Loading…
Reference in New Issue