Class DeferredConnectionProxyDataSourceWrapper

java.lang.Object
io.mats3.util.wrappers.DataSourceWrapper
io.mats3.util.wrappers.DeferredConnectionProxyDataSourceWrapper
All Implemented Interfaces:
MatsFactory.MatsWrapper<DataSource>, Wrapper, CommonDataSource, DataSource
Direct Known Subclasses:
JmsMatsTransactionManager_JmsAndSpringManagedSqlTx.DeferredConnectionProxyDataSourceWrapper_InfrastructureProxy

public class DeferredConnectionProxyDataSourceWrapper extends DataSourceWrapper
DataSource wrapper which returns thin Connection proxies (currently employing Java's "dynamic proxy" functionality) which do not actually fetch a Connection until it is needed. It defers as long as possible, "holding back" calls to setAutoCommit(..), setTransactionIsolation(..), setReadOnly(..), and ignores any commit() and rollback(), as well as handling some surrounding methods like toString(), equals(), hashCode() etc, until the user code e.g. creates a Statement or PreparedStatement - i.e. not until the user code actually needs to talk to the database. This deferring results in a situation where if the user code opens a transaction, but does not need to talk to the database after all, and then commits the transaction, the entire operation is elided - saving several round-trips over the wire.

The use of Java Dynamic Proxies is a simple way to ensure that the implementation is future proof, in that any method that appears on the Connection in any Java version will be handled by triggering actual Connection fetching and subsequent call-through to the actual method. Only the methods that are used in standard transaction management are specially handled to defer the getting of the actual Connection.

Note that it is assumed that the AutoCommit, TransactionIsolation and ReadOnly values are identical for all fetched Connections (that is, the pool resets them to some default when connection.close() is invoked). The default values for these properties are retrieved from the very first Connection that is actually fetched. The deferring works as such: If you set one of these value on the returned proxied Connection, this will be recorded, and will subsequently be set on the actual Connection once it is fetched because it is needed (e.g. when a PreparedStatement is created). However, as a further performance optimization, when about to set the value, it is compared against those default values gotten from the first Connection, and if they are equal, the actual setting-invocation is elided.

Inspired by Spring's LazyConnectionDataSourceProxy, but with the additional feature that you can query the Connection proxy for whether the underlying Connection was actually gotten, since it is a DeferredConnectionProxy (extends Connection). It also has the method actualConnectionWasRetrieved(proxy, actualConnection) which can be interesting for extensions. It also has the method methodInvoked(..), which is invoked after every method invoked on the returned DeferredConnectionProxys, which primarily is interesting for testing, but might have other uses.

If in a Spring environment, the returned Connection instances furthermore implements org.springframework.jdbc.datasource.ConnectionProxy.

  • Field Details

    • _autoCommitFromWrappedDataSource

      protected volatile Boolean _autoCommitFromWrappedDataSource
    • _transactionIsolationFromWrappedDataSource

      protected volatile Integer _transactionIsolationFromWrappedDataSource
    • _readOnlyFromWrappedDataSource

      protected volatile Boolean _readOnlyFromWrappedDataSource
  • Constructor Details

    • DeferredConnectionProxyDataSourceWrapper

      protected DeferredConnectionProxyDataSourceWrapper()
    • DeferredConnectionProxyDataSourceWrapper

      protected DeferredConnectionProxyDataSourceWrapper(DataSource targetDataSource)
  • Method Details