Package org.springframework.jdbc.datasource

# Class DataSourceTransactionManager

java.lang.Object
org.springframework.transaction.support.AbstractPlatformTransactionManager
org.springframework.jdbc.datasource.DataSourceTransactionManager

All Implemented Interfaces:
  `Serializable`, `org.springframework.beans.factory.InitializingBean`, `org.springframework.transaction.ConfigurableTransactionManager`, `org.springframework.transaction.PlatformTransactionManager`, `org.springframework.transaction.support.ResourceTransactionManager`, `org.springframework.transaction.TransactionManager`

Direct Known Subclasses:
  `JdbcTransactionManager`

public class DataSourceTransactionManager extends org.springframework.transaction.support.AbstractPlatformTransactionManager implements org.springframework.transaction.support.ResourceTransactionManager, org.springframework.beans.factory.InitializingBean
`PlatformTransactionManager` implementation for a single JDBC `DataSource`. This class is capable of working in any environment with any JDBC driver, as long as the setup uses a `javax.sql.DataSource` as its `Connection` factory mechanism. Binds a JDBC `Connection` from the specified `DataSource` to the current thread, potentially allowing for one thread-bound `Connection` per `DataSource`.

Note: The `DataSource` that this transaction manager operates on needs to return independent `Connection`s. The `Connection`s typically come from a connection pool but the `DataSource` must not return specifically scoped or constrained `Connection`s. This transaction manager will associate `Connection`s with thread-bound transactions, according to the specified propagation behavior. It assumes that a separate, independent `Connection` can be obtained even during an ongoing transaction.

Application code is required to retrieve the JDBC `Connection` via `DataSourceUtils.getConnection(DataSource)` instead of a standard EE-style `DataSource.getConnection()` call. Spring classes such as `JdbcTemplate` use this strategy implicitly. If not used in combination with this transaction manager, the `DataSourceUtils` lookup strategy behaves exactly like the native `DataSource` lookup; it can thus be used in a portable fashion.

Alternatively, you can allow application code to work with the standard EE-style lookup pattern `DataSource.getConnection()`, for example for legacy code that is not aware of Spring at all. In that case, define a `TransactionAwareDataSourceProxy` for your target `DataSource`, and pass that proxy `DataSource` to your DAOs which will automatically participate in Spring-managed transactions when accessing it.

Supports custom isolation levels, and timeouts which get applied as appropriate JDBC statement timeouts. To support the latter, application code must either use `JdbcTemplate`, call `DataSourceUtils.applyTransactionTimeout(java.sql.Statement, javax.sql.DataSource)` for each created JDBC `Statement`, or go through a `TransactionAwareDataSourceProxy` which will create timeout-aware JDBC `Connection`s and `Statement`s automatically.

Consider defining a `LazyConnectionDataSourceProxy` for your target `DataSource`, pointing both this transaction manager and your DAOs to it. This will lead to optimized handling of "empty" transactions, i.e. of transactions without any JDBC statements executed. A `LazyConnectionDataSourceProxy` will not fetch an actual JDBC `Connection` from the target `DataSource` until a `Statement` gets executed, lazily applying the specified transaction settings to the target `Connection`.

This transaction manager supports nested transactions via the JDBC `Savepoint` mechanism. The `"nestedTransactionAllowed"` flag defaults to "true", since nested transactions will work without restrictions on JDBC drivers that support savepoints (such as the Oracle JDBC driver).

This transaction manager can be used as a replacement for the `JtaTransactionManager` in the single resource case, as it does not require a container that supports JTA, typically in combination with a locally defined JDBC `DataSource` (for example, a Hikari connection pool). Switching between this local strategy and a JTA environment is just a matter of configuration!

As of 4.3.4, this transaction manager triggers flush callbacks on registered transaction synchronizations (if synchronization is generally active), assuming resources operating on the underlying JDBC `Connection`. This allows for setup analogous to `JtaTransactionManager`, in particular with respect to lazily registered ORM resources (for example, a Hibernate `Session`).

NOTE: As of 5.3, `JdbcTransactionManager` is available as an extended subclass which includes commit/rollback exception translation, aligned with `JdbcTemplate`.

Since:
  02.05.2003
Author:
  Juergen Hoeller
See Also:
  - `AbstractPlatformTransactionManager.setNestedTransactionAllowed(boolean)`
  - `Savepoint`
  - `DataSourceUtils.getConnection(javax.sql.DataSource)`
  - `DataSourceUtils.applyTransactionTimeout(java.sql.Statement, javax.sql.DataSource)`
  - `DataSourceUtils.releaseConnection(java.sql.Connection, javax.sql.DataSource)`
  - `TransactionAwareDataSourceProxy`
  - `LazyConnectionDataSourceProxy`
  - `JdbcTemplate`
  - `JdbcTransactionManager`
  - Serialized Form

## Nested Class Summary

## Nested classes/interfaces inherited from class org.springframework.transaction.support.AbstractPlatformTransactionManager

`org.springframework.transaction.support.AbstractPlatformTransactionManager.SuspendedResourcesHolder`

## Field Summary

### Fields inherited from class org.springframework.transaction.support.AbstractPlatformTransactionManager

`logger, SYNCHRONIZATION_ALWAYS, SYNCHRONIZATION_NEVER, SYNCHRONIZATION_ON_ACTUAL_TRANSACTION`

## Constructor Summary

Constructors
Constructor
Description
`DataSourceTransactionManager()`
Create a new `DataSourceTransactionManager` instance.
`DataSourceTransactionManager(DataSource dataSource)`
Create a new `DataSourceTransactionManager` instance.

## Method Summary

Modifier and Type
Method
Description
`void`
`afterPropertiesSet()`
`protected void`
`doBegin(Object transaction, org.springframework.transaction.TransactionDefinition definition)`
`protected void`
`doCleanupAfterCompletion(Object transaction)`
`protected void`
`doCommit(org.springframework.transaction.support.DefaultTransactionStatus status)`
`protected Object`
`doGetTransaction()`
`protected void`
`doResume(Object transaction, Object suspendedResources)`
`protected void`
`doRollback(org.springframework.transaction.support.DefaultTransactionStatus status)`
`protected void`
`doSetRollbackOnly(org.springframework.transaction.support.DefaultTransactionStatus status)`
`protected Object`
`doSuspend(Object transaction)`
`DataSource`
`getDataSource()`
Return the JDBC `DataSource` that this instance manages transactions for.
`Object`
`getResourceFactory()`
`boolean`
`isEnforceReadOnly()`
Return whether to enforce the read-only nature of a transaction through an explicit statement on the transactional connection.
`protected boolean`
`isExistingTransaction(Object transaction)`
`protected DataSource`
`obtainDataSource()`
Obtain the `DataSource` for actual use.
`protected void`
`prepareTransactionalConnection(Connection con, org.springframework.transaction.TransactionDefinition definition)`
Prepare the transactional `Connection` right after transaction begin.
`void`
`setDataSource(DataSource dataSource)`
Set the JDBC `DataSource` that this instance should manage transactions for.
`void`
`setEnforceReadOnly(boolean enforceReadOnly)`
Specify whether to enforce the read-only nature of a transaction (as indicated by `TransactionDefinition.isReadOnly()`) through an explicit statement on the transactional connection: "SET TRANSACTION READ ONLY" as understood by Oracle, MySQL and Postgres.
`protected RuntimeException`
`translateException(String task, SQLException ex)`
Translate the given JDBC commit/rollback exception to a common Spring exception to propagate from the `AbstractPlatformTransactionManager.commit(org.springframework.transaction.TransactionStatus)`/`AbstractPlatformTransactionManager.rollback(org.springframework.transaction.TransactionStatus)` call.

### Methods inherited from class org.springframework.transaction.support.AbstractPlatformTransactionManager

`commit, determineTimeout, getDefaultTimeout, getTransaction, getTransactionExecutionListeners, getTransactionSynchronization, invokeAfterCompletion, isFailEarlyOnGlobalRollbackOnly, isGlobalRollbackOnParticipationFailure, isNestedTransactionAllowed, isRollbackOnCommitFailure, isValidateExistingTransaction, prepareForCommit, prepareSynchronization, registerAfterCompletionWithExistingTransaction, resume, rollback, setDefaultTimeout, setFailEarlyOnGlobalRollbackOnly, setGlobalRollbackOnParticipationFailure, setNestedTransactionAllowed, setRollbackOnCommitFailure, setTransactionExecutionListeners, setTransactionSynchronization, setTransactionSynchronizationName, setValidateExistingTransaction, shouldCommitOnGlobalRollbackOnly, suspend, triggerBeforeCommit, triggerBeforeCompletion, useSavepointForNestedTransaction`

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

### Methods inherited from interface org.springframework.transaction.ConfigurableTransactionManager

`addListener`

### Methods inherited from interface org.springframework.transaction.PlatformTransactionManager

`commit, getTransaction, rollback`

## Constructor Details

### DataSourceTransactionManager

public DataSourceTransactionManager()
Create a new `DataSourceTransactionManager` instance. A `DataSource` has to be set to be able to use it.

See Also:
  - `setDataSource(javax.sql.DataSource)`

### DataSourceTransactionManager

public DataSourceTransactionManager(DataSource dataSource)
Create a new `DataSourceTransactionManager` instance.

Parameters:
  `dataSource` - the JDBC DataSource to manage transactions for

## Method Details

### setDataSource

public void setDataSource(@Nullable DataSource dataSource)
Set the JDBC `DataSource` that this instance should manage transactions for.

This will typically be a locally defined `DataSource`, for example a Hikari connection pool. Alternatively, you can also manage transactions for a non-XA `DataSource` fetched from JNDI. For an XA `DataSource`, use `JtaTransactionManager` instead.

The `DataSource` specified here should be the target `DataSource` to manage transactions for, not a `TransactionAwareDataSourceProxy`. Only data access code may work with `TransactionAwareDataSourceProxy` while the transaction manager needs to work on the underlying target `DataSource`. If there is nevertheless a `TransactionAwareDataSourceProxy` passed in, it will be unwrapped to extract its target `DataSource`.

The `DataSource` passed in here needs to return independent `Connection`s. The `Connection`s typically come from a connection pool but the `DataSource` must not return specifically scoped or constrained `Connection`s, just possibly lazily fetched.

See Also:
  - `LazyConnectionDataSourceProxy`

### getDataSource

@Nullable public DataSource getDataSource()
Return the JDBC `DataSource` that this instance manages transactions for.

### obtainDataSource

protected DataSource obtainDataSource()
Obtain the `DataSource` for actual use.

Returns:
  the DataSource (never `null`)
Throws:
  `IllegalStateException` - in case of no DataSource set
Since:
  5.0

### setEnforceReadOnly

public void setEnforceReadOnly(boolean enforceReadOnly)
Specify whether to enforce the read-only nature of a transaction (as indicated by `TransactionDefinition.isReadOnly()`) through an explicit statement on the transactional connection: "SET TRANSACTION READ ONLY" as understood by Oracle, MySQL and Postgres.

The exact treatment, including any SQL statement executed on the connection, can be customized through `prepareTransactionalConnection(java.sql.Connection, org.springframework.transaction.TransactionDefinition)`.

This mode of read-only handling goes beyond the `Connection.setReadOnly(boolean)` hint that Spring applies by default. In contrast to that standard JDBC hint, "SET TRANSACTION READ ONLY" enforces an isolation-level-like connection mode where data manipulation statements are strictly disallowed. Also, on Oracle, this read-only mode provides read consistency for the entire transaction.

Note that older Oracle JDBC drivers (9i, 10g) used to enforce this read-only mode even for `Connection.setReadOnly(true`. However, with recent drivers, this strong enforcement needs to be applied explicitly, for example, through this flag.

Since:
  4.3.7
See Also:
  - `prepareTransactionalConnection(java.sql.Connection, org.springframework.transaction.TransactionDefinition)`

### isEnforceReadOnly

public boolean isEnforceReadOnly()
Return whether to enforce the read-only nature of a transaction through an explicit statement on the transactional connection.

Since:
  4.3.7
See Also:
  - `setEnforceReadOnly(boolean)`

### afterPropertiesSet

public void afterPropertiesSet()

Specified by:
  `afterPropertiesSet` in interface `org.springframework.beans.factory.InitializingBean`

### getResourceFactory

public Object getResourceFactory()

Specified by:
  `getResourceFactory` in interface `org.springframework.transaction.support.ResourceTransactionManager`

### doGetTransaction

protected Object doGetTransaction()

Specified by:
  `doGetTransaction` in class `org.springframework.transaction.support.AbstractPlatformTransactionManager`

### isExistingTransaction

protected boolean isExistingTransaction(Object transaction)

Overrides:
  `isExistingTransaction` in class `org.springframework.transaction.support.AbstractPlatformTransactionManager`

### doBegin

protected void doBegin(Object transaction, org.springframework.transaction.TransactionDefinition definition)

Specified by:
  `doBegin` in class `org.springframework.transaction.support.AbstractPlatformTransactionManager`

### doSuspend

protected Object doSuspend(Object transaction)

Overrides:
  `doSuspend` in class `org.springframework.transaction.support.AbstractPlatformTransactionManager`

### doResume

protected void doResume(@Nullable Object transaction, Object suspendedResources)

Overrides:
  `doResume` in class `org.springframework.transaction.support.AbstractPlatformTransactionManager`

### doCommit

protected void doCommit(org.springframework.transaction.support.DefaultTransactionStatus status)

Specified by:
  `doCommit` in class `org.springframework.transaction.support.AbstractPlatformTransactionManager`

### doRollback

protected void doRollback(org.springframework.transaction.support.DefaultTransactionStatus status)

Specified by:
  `doRollback` in class `org.springframework.transaction.support.AbstractPlatformTransactionManager`

### doSetRollbackOnly

protected void doSetRollbackOnly(org.springframework.transaction.support.DefaultTransactionStatus status)

Overrides:
  `doSetRollbackOnly` in class `org.springframework.transaction.support.AbstractPlatformTransactionManager`

### doCleanupAfterCompletion

protected void doCleanupAfterCompletion(Object transaction)

Overrides:
  `doCleanupAfterCompletion` in class `org.springframework.transaction.support.AbstractPlatformTransactionManager`

### prepareTransactionalConnection

protected void prepareTransactionalConnection(Connection con, org.springframework.transaction.TransactionDefinition definition) throws SQLException
Prepare the transactional `Connection` right after transaction begin.

The default implementation executes a "SET TRANSACTION READ ONLY" statement if the `"enforceReadOnly"` flag is set to `true` and the transaction definition indicates a read-only transaction.

The "SET TRANSACTION READ ONLY" is understood by Oracle, MySQL and Postgres and may work with other databases as well. If you'd like to adapt this treatment, override this method accordingly.

Parameters:
  `con` - the transactional JDBC Connection
  `definition` - the current transaction definition
Throws:
  `SQLException` - if thrown by JDBC API
Since:
  4.3.7
See Also:
  - `setEnforceReadOnly(boolean)`

### translateException

protected RuntimeException translateException(String task, SQLException ex)
Translate the given JDBC commit/rollback exception to a common Spring exception to propagate from the `AbstractPlatformTransactionManager.commit(org.springframework.transaction.TransactionStatus)`/`AbstractPlatformTransactionManager.rollback(org.springframework.transaction.TransactionStatus)` call.

The default implementation throws a `TransactionSystemException`. Subclasses may specifically identify concurrency failures etc.

Parameters:
  `task` - the task description (commit or rollback)
  `ex` - the SQLException thrown from commit/rollback
Returns:
  the translated exception to throw, either a `DataAccessException` or a `TransactionException`
Since:
  5.3