diff --git a/framework-docs/modules/ROOT/pages/data-access/dao.adoc b/framework-docs/modules/ROOT/pages/data-access/dao.adoc
index 4c2844e9549..9ca9666f541 100644
--- a/framework-docs/modules/ROOT/pages/data-access/dao.adoc
+++ b/framework-docs/modules/ROOT/pages/data-access/dao.adoc
@@ -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]
======
diff --git a/framework-docs/modules/ROOT/pages/data-access/jdbc/advanced.adoc b/framework-docs/modules/ROOT/pages/data-access/jdbc/advanced.adoc
index ce43becb612..04533c9cb82 100644
--- a/framework-docs/modules/ROOT/pages/data-access/jdbc/advanced.adoc
+++ b/framework-docs/modules/ROOT/pages/data-access/jdbc/advanced.adoc
@@ -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]
======
diff --git a/framework-docs/modules/ROOT/pages/data-access/jdbc/connections.adoc b/framework-docs/modules/ROOT/pages/data-access/jdbc/connections.adoc
index e8e60ac527f..7ebb4a44a68 100644
--- a/framework-docs/modules/ROOT/pages/data-access/jdbc/connections.adoc
+++ b/framework-docs/modules/ROOT/pages/data-access/jdbc/connections.adoc
@@ -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.
diff --git a/framework-docs/modules/ROOT/pages/data-access/jdbc/core.adoc b/framework-docs/modules/ROOT/pages/data-access/jdbc/core.adoc
index 31bbecce2f2..4112a918a47 100644
--- a/framework-docs/modules/ROOT/pages/data-access/jdbc/core.adoc
+++ b/framework-docs/modules/ROOT/pages/data-access/jdbc/core.adoc
@@ -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) {
diff --git a/framework-docs/modules/ROOT/pages/data-access/jdbc/packages.adoc b/framework-docs/modules/ROOT/pages/data-access/jdbc/packages.adoc
index e6719fec871..4eba396012b 100644
--- a/framework-docs/modules/ROOT/pages/data-access/jdbc/packages.adoc
+++ b/framework-docs/modules/ROOT/pages/data-access/jdbc/packages.adoc
@@ -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
diff --git a/framework-docs/modules/ROOT/pages/data-access/orm/jpa.adoc b/framework-docs/modules/ROOT/pages/data-access/orm/jpa.adoc
index 0f60323febc..9dbf42a56d7 100644
--- a/framework-docs/modules/ROOT/pages/data-access/orm/jpa.adoc
+++ b/framework-docs/modules/ROOT/pages/data-access/orm/jpa.adoc
@@ -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
diff --git a/framework-docs/modules/ROOT/pages/data-access/r2dbc.adoc b/framework-docs/modules/ROOT/pages/data-access/r2dbc.adoc
index f5735720ad5..65e30ce8ae0 100644
--- a/framework-docs/modules/ROOT/pages/data-access/r2dbc.adoc
+++ b/framework-docs/modules/ROOT/pages/data-access/r2dbc.adoc
@@ -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.
diff --git a/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/annotations.adoc b/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/annotations.adoc
index a43d6e06fb4..8a762b791c5 100644
--- a/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/annotations.adoc
+++ b/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/annotations.adoc
@@ -124,7 +124,6 @@ In XML configuration, the `` tag provides similar conveni
----
<1> The line that makes the bean instance transactional.
-
TIP: You can omit the `transaction-manager` attribute in the ``
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:
----
-
+
...
-
+
...
-
+
...
diff --git a/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/R2dbcTransactionManager.java b/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/R2dbcTransactionManager.java
index 9fe2e1140e6..26e6bc75477 100644
--- a/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/R2dbcTransactionManager.java
+++ b/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/R2dbcTransactionManager.java
@@ -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 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