org.springframework.jdbc.datasource
Class LazyConnectionDataSourceProxy

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

public class LazyConnectionDataSourceProxy
extends DelegatingDataSource

Proxy for a target DataSource, fetching actual JDBC Connections lazily, i.e. not until first creation of a Statement. Connection initialization properties like auto-commit mode, transaction isolation and read-only mode will be kept and applied to the actual JDBC Connection as soon as an actual Connection is fetched (if ever). Consequently, commit and rollback calls will be ignored if no Statements have been created.

This DataSource proxy allows to avoid fetching JDBC Connections from a pool unless actually necessary. JDBC transaction control can happen without fetching a Connection from the pool or communicating with the database; this will be done lazily on first creation of a JDBC Statement.

If you configure both a LazyConnectionDataSourceProxy and a TransactionAwareDataSourceProxy, make sure that the latter is the outermost DataSource. In such a scenario, data access code will talk to the transaction-aware DataSource, which will in turn work with the LazyConnectionDataSourceProxy.

Lazy fetching of physical JDBC Connections is particularly beneficial in a generic transaction demarcation environment. It allows you to demarcate transactions on all methods that could potentially perform data access, without paying a performance penalty if no actual data access happens.

This DataSource proxy gives you behavior analogous to JTA and a transactional JNDI DataSource (as provided by the J2EE server), even with a local transaction strategy like DataSourceTransactionManager or HibernateTransactionManager. It does not add value with Spring's JtaTransactionManager as transaction strategy.

Lazy fetching of JDBC Connections is also recommended for read-only operations with Hibernate, in particular if the chances of resolving the result in the second-level cache are high. This avoids the need to communicate with the database at all for such read-only operations. You will get the same effect with non-transactional reads, but lazy fetching of JDBC Connections allows you to still perform reads in transactions.

NOTE: This DataSource proxy needs to return wrapped Connections to handle lazy fetching of an actual JDBC Connection. 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.4
Author:
Juergen Hoeller
See Also:
ConnectionProxy, DataSourceTransactionManager, HibernateTransactionManager, NativeJdbcExtractor

Nested Class Summary
private  class LazyConnectionDataSourceProxy.LazyConnectionInvocationHandler
          Invocation handler that defers fetching an actual JDBC Connection until first creation of a Statement.
 
Field Summary
private static Constants constants
          Constants instance for TransactionDefinition
private  java.lang.Boolean defaultAutoCommit
           
private  java.lang.Integer defaultTransactionIsolation
           
private static Log logger
           
 
Constructor Summary
LazyConnectionDataSourceProxy()
          Create a new LazyConnectionDataSourceProxy.
LazyConnectionDataSourceProxy(javax.sql.DataSource targetDataSource)
          Create a new LazyConnectionDataSourceProxy.
 
Method Summary
 void afterPropertiesSet()
          Invoked by a BeanFactory after it has set all bean properties supplied (and satisfied BeanFactoryAware and ApplicationContextAware).
protected  void checkDefaultConnectionProperties(java.sql.Connection con)
          Check the default connection properties (auto-commit, transaction isolation), keeping them to be able to expose them correctly without fetching an actual JDBC Connection from the target DataSource.
protected  java.lang.Boolean defaultAutoCommit()
          Expose the default auto-commit value.
protected  java.lang.Integer defaultTransactionIsolation()
          Expose the default transaction isolation value.
 java.sql.Connection getConnection()
          Return a Connection handle that lazily fetches an actual JDBC Connection when asked for a Statement (or PreparedStatement or CallableStatement).
 java.sql.Connection getConnection(java.lang.String username, java.lang.String password)
          Return a Connection handle that lazily fetches an actual JDBC Connection when asked for a Statement (or PreparedStatement or CallableStatement).
 void setDefaultAutoCommit(boolean defaultAutoCommit)
          Set the default auto-commit mode to expose when no target Connection has been fetched yet (-> actual JDBC Connection default not known yet).
 void setDefaultTransactionIsolation(int defaultTransactionIsolation)
          Set the default transaction isolation level to expose when no target Connection has been fetched yet (-> actual JDBC Connection default not known yet).
 void setDefaultTransactionIsolationName(java.lang.String constantName)
          Set the default transaction isolation level by the name of the corresponding constant in Connection, e.g.
 
Methods inherited from class org.springframework.jdbc.datasource.DelegatingDataSource
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

constants

private static final Constants constants
Constants instance for TransactionDefinition


logger

private static final Log logger

defaultAutoCommit

private java.lang.Boolean defaultAutoCommit

defaultTransactionIsolation

private java.lang.Integer defaultTransactionIsolation
Constructor Detail

LazyConnectionDataSourceProxy

public LazyConnectionDataSourceProxy()
Create a new LazyConnectionDataSourceProxy.

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

LazyConnectionDataSourceProxy

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

Parameters:
targetDataSource - the target DataSource
Method Detail

setDefaultAutoCommit

public void setDefaultAutoCommit(boolean defaultAutoCommit)
Set the default auto-commit mode to expose when no target Connection has been fetched yet (-> actual JDBC Connection default not known yet).

If not specified, the default gets determined by checking a target Connection on startup. If that check fails, the default will be determined lazily on first access of a Connection.

See Also:
Connection.setAutoCommit(boolean)

setDefaultTransactionIsolation

public void setDefaultTransactionIsolation(int defaultTransactionIsolation)
Set the default transaction isolation level to expose when no target Connection has been fetched yet (-> actual JDBC Connection default not known yet).

This property accepts the int constant value (e.g. 8) as defined in the Connection interface; it is mainly intended for programmatic use. Consider using the "defaultTransactionIsolationName" property for setting the value by name (e.g. "TRANSACTION_SERIALIZABLE").

If not specified, the default gets determined by checking a target Connection on startup. If that check fails, the default will be determined lazily on first access of a Connection.

See Also:
setDefaultTransactionIsolationName(java.lang.String), Connection.setTransactionIsolation(int)

setDefaultTransactionIsolationName

public void setDefaultTransactionIsolationName(java.lang.String constantName)
Set the default transaction isolation level by the name of the corresponding constant in Connection, e.g. "TRANSACTION_SERIALIZABLE".

Parameters:
constantName - name of the constant
See Also:
setDefaultTransactionIsolation(int), Connection.TRANSACTION_READ_UNCOMMITTED, Connection.TRANSACTION_READ_COMMITTED, Connection.TRANSACTION_REPEATABLE_READ, Connection.TRANSACTION_SERIALIZABLE

afterPropertiesSet

public void afterPropertiesSet()
Description copied from interface: InitializingBean
Invoked by a BeanFactory after it has set all bean properties supplied (and satisfied BeanFactoryAware and ApplicationContextAware).

This method allows the bean instance to perform initialization only possible when all bean properties have been set and to throw an exception in the event of misconfiguration.

Specified by:
afterPropertiesSet in interface InitializingBean
Overrides:
afterPropertiesSet in class DelegatingDataSource

checkDefaultConnectionProperties

protected void checkDefaultConnectionProperties(java.sql.Connection con)
                                         throws java.sql.SQLException
Check the default connection properties (auto-commit, transaction isolation), keeping them to be able to expose them correctly without fetching an actual JDBC Connection from the target DataSource.

This will be invoked once on startup, but also for each retrieval of a target Connection. If the check failed on startup (because the database was down), we'll lazily retrieve those settings.

Parameters:
con - the Connection to use for checking
Throws:
java.sql.SQLException - if thrown by Connection methods

defaultAutoCommit

protected java.lang.Boolean defaultAutoCommit()
Expose the default auto-commit value.


defaultTransactionIsolation

protected java.lang.Integer defaultTransactionIsolation()
Expose the default transaction isolation value.


getConnection

public java.sql.Connection getConnection()
                                  throws java.sql.SQLException
Return a Connection handle that lazily fetches an actual JDBC Connection when asked for a Statement (or PreparedStatement or CallableStatement).

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 lazy Connection handle
Throws:
java.sql.SQLException
See Also:
ConnectionProxy.getTargetConnection()

getConnection

public java.sql.Connection getConnection(java.lang.String username,
                                         java.lang.String password)
                                  throws java.sql.SQLException
Return a Connection handle that lazily fetches an actual JDBC Connection when asked for a Statement (or PreparedStatement or CallableStatement).

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
Parameters:
username - the per-Connection username
password - the per-Connection password
Returns:
a lazy Connection handle
Throws:
java.sql.SQLException
See Also:
ConnectionProxy.getTargetConnection()