org.springframework.jdbc.datasource
Class TransactionAwareDataSourceProxy

java.lang.Object
  extended by org.springframework.jdbc.datasource.DelegatingDataSource
      extended by org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
All Implemented Interfaces:
java.sql.Wrapper, javax.sql.CommonDataSource, javax.sql.DataSource, InitializingBean

public class TransactionAwareDataSourceProxy
extends DelegatingDataSource

Proxy for a target JDBC DataSource, adding awareness of Spring-managed transactions. Similar to a transactional JNDI DataSource as provided by a J2EE server.

Data access code that should remain unaware of Spring's data access support can work with this proxy to seamlessly participate in Spring-managed transactions. Note that the transaction manager, for example DataSourceTransactionManager, still needs to work with the underlying DataSource, not with this proxy.

Make sure that TransactionAwareDataSourceProxy is the outermost DataSource of a chain of DataSource proxies/adapters. TransactionAwareDataSourceProxy can delegate either directly to the target connection pool or to some intermediary proxy/adapter like LazyConnectionDataSourceProxy or UserCredentialsDataSourceAdapter.

Delegates to DataSourceUtils for automatically participating in thread-bound transactions, for example managed by DataSourceTransactionManager. getConnection calls and close calls on returned Connections will behave properly within a transaction, i.e. always operate on the transactional Connection. If not within a transaction, normal DataSource behavior applies.

This proxy allows data access code to work with the plain JDBC API and still participate in Spring-managed transactions, similar to JDBC code in a J2EE/JTA environment. However, if possible, use Spring's DataSourceUtils, JdbcTemplate or JDBC operation objects to get transaction participation even without a proxy for the target DataSource, avoiding the need to define such a proxy in the first place.

As a further effect, using a transaction-aware DataSource will apply remaining transaction timeouts to all created JDBC (Prepared/Callable)Statement. This means that all operations performed through standard JDBC will automatically participate in Spring-managed transaction timeouts.

NOTE: This DataSource proxy needs to return wrapped Connections (which implement the ConnectionProxy interface) in order to handle close calls properly. Therefore, the returned Connections cannot be cast to a native JDBC Connection type like OracleConnection or to a connection pool implementation type. Use a corresponding NativeJdbcExtractor to retrieve the native JDBC Connection.

Since:
1.1
Author:
Juergen Hoeller
See Also:
DataSource.getConnection(), Connection.close(), DataSourceUtils.doGetConnection(javax.sql.DataSource), DataSourceUtils.applyTransactionTimeout(java.sql.Statement, javax.sql.DataSource), DataSourceUtils.doReleaseConnection(java.sql.Connection, javax.sql.DataSource)

Nested Class Summary
private  class TransactionAwareDataSourceProxy.TransactionAwareInvocationHandler
          Invocation handler that delegates close calls on JDBC Connections to DataSourceUtils for being aware of thread-bound transactions.
 
Field Summary
private  boolean reobtainTransactionalConnections
           
 
Constructor Summary
TransactionAwareDataSourceProxy()
          Create a new TransactionAwareDataSourceProxy.
TransactionAwareDataSourceProxy(javax.sql.DataSource targetDataSource)
          Create a new TransactionAwareDataSourceProxy.
 
Method Summary
 java.sql.Connection getConnection()
          Delegates to DataSourceUtils for automatically participating in Spring-managed transactions.
protected  java.sql.Connection getTransactionAwareConnectionProxy(javax.sql.DataSource targetDataSource)
          Wraps the given Connection with a proxy that delegates every method call to it but delegates close() calls to DataSourceUtils.
 void setReobtainTransactionalConnections(boolean reobtainTransactionalConnections)
          Specify whether to reobtain the target Connection for each operation performed within a transaction.
protected  boolean shouldObtainFixedConnection(javax.sql.DataSource targetDataSource)
          Determine whether to obtain a fixed target Connection for the proxy or to reobtain the target Connection for each operation.
 
Methods inherited from class org.springframework.jdbc.datasource.DelegatingDataSource
afterPropertiesSet, getConnection, getLoginTimeout, getLogWriter, getParentLogger, getTargetDataSource, isWrapperFor, setLoginTimeout, setLogWriter, setTargetDataSource, unwrap
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

reobtainTransactionalConnections

private boolean reobtainTransactionalConnections
Constructor Detail

TransactionAwareDataSourceProxy

public TransactionAwareDataSourceProxy()
Create a new TransactionAwareDataSourceProxy.

See Also:
DelegatingDataSource.setTargetDataSource(javax.sql.DataSource)

TransactionAwareDataSourceProxy

public TransactionAwareDataSourceProxy(javax.sql.DataSource targetDataSource)
Create a new TransactionAwareDataSourceProxy.

Parameters:
targetDataSource - the target DataSource
Method Detail

setReobtainTransactionalConnections

public void setReobtainTransactionalConnections(boolean reobtainTransactionalConnections)
Specify whether to reobtain the target Connection for each operation performed within a transaction.

The default is "false". Specify "true" to reobtain transactional Connections for every call on the Connection proxy; this is advisable on JBoss if you hold on to a Connection handle across transaction boundaries.

The effect of this setting is similar to the "hibernate.connection.release_mode" value "after_statement".


getConnection

public java.sql.Connection getConnection()
                                  throws java.sql.SQLException
Delegates to DataSourceUtils for automatically participating in Spring-managed transactions. Throws the original SQLException, if any.

The returned Connection handle implements the ConnectionProxy interface, allowing to retrieve the underlying target Connection.

Specified by:
getConnection in interface javax.sql.DataSource
Overrides:
getConnection in class DelegatingDataSource
Returns:
a transactional Connection if any, a new one else
Throws:
java.sql.SQLException
See Also:
DataSourceUtils.doGetConnection(javax.sql.DataSource), ConnectionProxy.getTargetConnection()

getTransactionAwareConnectionProxy

protected java.sql.Connection getTransactionAwareConnectionProxy(javax.sql.DataSource targetDataSource)
Wraps the given Connection with a proxy that delegates every method call to it but delegates close() calls to DataSourceUtils.

Parameters:
targetDataSource - DataSource that the Connection came from
Returns:
the wrapped Connection
See Also:
Connection.close(), DataSourceUtils.doReleaseConnection(java.sql.Connection, javax.sql.DataSource)

shouldObtainFixedConnection

protected boolean shouldObtainFixedConnection(javax.sql.DataSource targetDataSource)
Determine whether to obtain a fixed target Connection for the proxy or to reobtain the target Connection for each operation.

The default implementation returns true for all standard cases. This can be overridden through the "reobtainTransactionalConnections" flag, which enforces a non-fixed target Connection within an active transaction. Note that non-transactional access will always use a fixed Connection.

Parameters:
targetDataSource - the target DataSource