Class LazyConnectionDataSourceProxy

java.lang.Object
org.springframework.jdbc.datasource.DelegatingDataSource
org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy
All Implemented Interfaces:
Wrapper, CommonDataSource, 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, read-only mode, catalog, schema, holdability, client info, and network timeout 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.

Once a property has been set, the corresponding getter method returns the set value until the actual Connection is fetched. If the property has not been set, invoking the getter triggers a fetch of the actual connection in order to obtain the default value.

Although client info is listed among the deferred properties above, the following methods are exceptions to the lazy acquisition behavior and force immediate acquisition of the underlying Connection. The Connection.getClientInfo() and Connection.getClientInfo(java.lang.String) methods are read operations whose values cannot be reliably cached due to driver defaults, remnants from pooled connections, or external session modifications.

The Connection.setClientInfo(java.util.Properties) method also forces immediate acquisition. JDBC driver implementations are inconsistent: some treat it as an overwrite, while others treat it as an append/merge. To guarantee behavior identical to that of a non-lazy DataSource across all drivers, the proxy does not cache or replay it, thereby avoiding any risk of semantic mismatch.

As of 6.1.2, there is also special support for a read-only DataSource to use during a read-only transaction, in addition to the regular target DataSource.

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. As a bonus, this allows for taking the transaction-synchronized read-only flag and/or isolation level into account in a routing DataSource (for example, IsolationLevelDataSourceRouter).

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. As of 6.1.2, LazyConnectionDataSourceProxy will initialize its default connection characteristics on first Connection access; to enforce this on startup, call checkDefaultConnectionProperties().

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 Jakarta EE 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.

As of 6.2.6, this DataSource proxy also suppresses a rollback attempt in case of a timeout where the connection has been closed in the meantime.

NOTE: This DataSource proxy needs to return wrapped Connections (which implement the ConnectionProxy interface) in order to handle lazy fetching of an actual JDBC Connection. Use Wrapper.unwrap(Class) to retrieve the native JDBC Connection.

Since:
1.1.4
Author:
Juergen Hoeller, Sam Brannen, Chengang Guan
See Also: