[
http://opensource.atlassian.com/projects/hibernate/browse/HHH-1737?page=c...
]
Steve Sarandos commented on HHH-1737:
-------------------------------------
I ran into this issue when trying to call a stored procedure that requires an array
argument. To pass an array using Oracle's JDBC driver you need to call
ArrayDescriptor.createDescriptor() passing the Oracle array type name. Calling this
method now fails with a ClassCastException due to the fact that the connection is
proxied.
To solve this I added a new getConnectionProxyInterfaces() method to the Dialect class.
The default implementation returns a Class array containing the java.sql.Connection class.
This essentially causing the BorrowedConnectionProxy class to behave as it does now. To
solve my Oracle-specific problem I overrode the getConnectionProxyInterfaces() method in
Oracle9Dialect and had it return an array of interface classes containing the
Oracle-specific connection interface(oracle.jdbc.OracleConnection). It uses interface
names and looks them up through reflection to prevent any dependency on the Oracle JDBC
driver:
public Class[] getConnectionProxyInterfaces() {
String[] interfaceNames = new String[] {"java.sql.Connection",
"oracle.jdbc.OracleConnection"};
Class[] interfaces = new Class[2];
for (int i = 0; i < interfaces.length; i++) {
try {
interfaces[i] = ReflectHelper.classForName(interfaceNames[i]);
} catch (Exception se) {
throw new HibernateException("Problem while trying to load Oracle connection
interfaces.",se);
}
}
return interfaces;
}
BorrowedConnectionProxy's generateProxy method changes to this:
public static Connection generateProxy(ConnectionManager connectionManager) {
BorrowedConnectionProxy handler = new BorrowedConnectionProxy( connectionManager );
Dialect dialect = connectionManager.getFactory().getDialect();
return ( Connection ) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
dialect.getConnectionProxyInterfaces(),
handler
);
}
This allows Hibernate to keep the protection of the proxy and still allow for access to
vendor specific functionality.
The new BorrowedConnectionProxy prevents users from accessing the
native connection
-----------------------------------------------------------------------------------
Key: HHH-1737
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-1737
Project: Hibernate3
Type: Bug
Components: core
Versions: 3.1.1, 3.1.2, 3.1.3
Environment: Hibernate 3.1.3, Oracle 9.2.0.4
Reporter: Nick Reid
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.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira