Add a ConnectionWrapper interface to allow access to the underlying connection from a BorrowedConnectionProxy

Description

The borrowConnection functionality now prevents us from accessing the native connection to perform necessary operations (LOB handling, OAQ integration). Instead of just returning a simple proxy the implements java.sql.Connection the proxy could additionally implement an interface that allows users to access the wrapped connection returned by the ConnectionManager.

i.e.

public interface BorrowedConnection extends java.sql.Connection
{
java.sql.Connection getTargetConnection()
}

public class BorrowedConnectionProxy implements InvocationHandler {

private final ConnectionManager connectionManager;
private boolean useable = true;

public BorrowedConnectionProxy(ConnectionManager connectionManager) {
this.connectionManager = connectionManager;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( "close".equals( method.getName() ) ) {
connectionManager.releaseBorrowedConnection();
return null;
}
if ( "getTargetConnection".equals( method.getName() ) ) {
return connectionManager.getConnection();
}
// should probably no-op commit/rollback here, at least in JTA scenarios
if ( !useable ) {
throw new HibernateException( "connnection proxy not usable after transaction completion" );
}
try {
return method.invoke( connectionManager.getConnection(), args );
}
catch( InvocationTargetException e ) {
throw e.getTargetException();
}
}

public static Connection generateProxy(ConnectionManager connectionManager) {
BorrowedConnectionProxy handler = new BorrowedConnectionProxy( connectionManager );
return ( Connection ) Proxy.newProxyInstance(
Connection.class.getClassLoader(),
new Class[] { BorrowedConnection.class },
handler
);
}

public static void renderUnuseable(Connection connection) {
if ( connection != null && Proxy.isProxyClass( connection.getClass() ) ) {
InvocationHandler handler = Proxy.getInvocationHandler( connection );
if ( BorrowedConnectionProxy.class.isAssignableFrom( handler.getClass() ) ) {
( ( BorrowedConnectionProxy ) handler ).useable = false;
}
}
}
}

We could always get access to the connectionManager field of the invocation handler via reflection, but this is not supportable or maintainable.

Environment

Hibernate 3.1.3, Oracle 9.2.0.4

Assignee

Steve Ebersole

Reporter

Nick Reid

Fix versions

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

Priority

Major
Configure