简体   繁体   中英

Unwrapping Jdbc4Connection from SessionFactoryImpl

I want to use CopyManager from postgres JDBC for one of my project. However I'm having a problem with getting an instance of this object from a sessionFactory in a Grails project.

This is my current approach:

SessionFactoryImpl sessionFactoryImpl = (sessionFactory.currentSessionFactory as SessionFactoryImpl)
LazyConnectionDataSourceProxy lcdsProxy = java.lang.reflect.Proxy.getInvocationHandler(sessionFactoryImpl.connectionProvider.connection).targetDataSource
DisposableConnectionFacade dcFacade = java.lang.reflect.Proxy.getInvocationHandler(lcdsProxy.targetDataSource.connection)
Jdbc4Connection jdbc4Connection = dcFacade.next.connection.connection
CopyManager cm = (jdbc4Connection as BaseConnection).copyAPI

I'm sure there must be simpler way how to unwrap JDBC4 connection from session factory.

Unfortunately since the DataSource is proxied 3 times, to get the real implementation of the connection and Postgres Jdbc4Connection, you either need to dig down through the DataSource proxies, or the connection proxies. I'd use more idiomatic Groovy though and skip using the 'current' session factory, since the sessionFactory proxy will pass all calls to the real instance (plus I'm pretty sure that would fail in a WAR file since this is only active in dev to support reloading):

import java.lang.reflect.Proxy

def lcdsProxy = Proxy.getInvocationHandler(sessionFactory.connectionProvider.connection).targetDataSource
def dcFacade = Proxy.getInvocationHandler(lcdsProxy.targetDataSource.connection)
def jdbc4Connection = dcFacade.next.connection.connection
CopyManager cm = jdbc4Connection.copyAPI

My preference would be to get the connection from the current session, not the current session factory, since that's what holds the connection, and one of those 3 proxies is a org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy to ensure that the connection being used by the current session would be returned from the DataSource as a 'new' connection. So one approach there would be

def connection = sessionFactory.currentSession.connection()
def jdbc4Connection = connection.targetConnection.targetConnection.connection
CopyManager cm = jdbc4Connection.copyAPI

or if this is the only reason you need the sessionFactory , you could use withSession :

AnyDomainClass.withSession { session ->
   def connection = session.connection()
   def jdbc4Connection = connection.targetConnection.targetConnection.connection
   CopyManager cm = jdbc4Connection.copyAPI
}

or even skip that and go to the DataSource (dependency-injected with def dataSource ) since one of the datasource proxies is a TransactionAwareDataSourceProxy :

def connection = ctx.dataSource.connection
def jdbc4Connection = connection.targetConnection.targetConnection.connection
CopyManager cm = jdbc4Connection.copyAPI

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM