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
Related
I'm using Hibernate 5.4.18 with HikariCP 3.4.5. My configuration is programmatic, and I set underlying DataSource of Hibernate with hibernate.connection.datasource-property. Strangely, when I then call EntityManagerFactory.close()-function, it doesn't call close()-method of HikariDataSource, and connection will leave open. Is this a desired behavior? Oracle documentation says that EntityManagerFactory.close() will "Close the factory, releasing any resources that it holds".
Minimum example with Kotlin:
fun main() {
val emf = Persistence.createEntityManagerFactory("default", getJpaProperties())
// Fetch underlying HikariDataSource
val ds = emf.unwrap(SessionFactoryImpl::class.java)
.serviceRegistry
.getService<ConnectionProvider>(ConnectionProvider::class.java)
.unwrap(HikariDataSource::class.java)
emf.close()
println(ds.isClosed) // prints "false"
}
private fun getJpaProperties(): Map<String, Any> {
val dataSource = HikariDataSource().apply {
username = "sa"
password = ""
jdbcUrl = "jdbc:h2:mem:test_db"
}
return mapOf(
"hibernate.dialect" to "org.hibernate.dialect.H2Dialect",
"hibernate.connection.datasource" to dataSource
)
}
It's because you are providing an instance of a datasource. If you initialise a DS, there's a big chance you'll use it in other parts of your code, so closing the datasource would introduce an unexpected behaviour. This is actually a good practice, that the "module" that creates a resource is also responsible for disposing of it.
Hibernate will close the datasource if you provide the details of it (username, password, class name, etc), as it will be managed by Hibernate.
For a bit of history, in the old days, a DS would be created in by a J2EE container (e.g. Tomcat) and then shared across many apps inside that container. And the property hibernate.connection.datasource would be a JNDI location pointing to the datasource.
I am trying to create a entity manager at runtime which will have connection pooling.
Data base details will be provided by user and based on that we need to create one entity manager which will have connection pooling.
I am using spring MVC , Eclipse Link JPA.
I tried some solution but either they are working with #configuration annotation which is not ideal for me.
One solution is working fine but i am not able to maintain connection pooling.
below is code which is working fine but not able to add support for connection pooling.
public static EntityManager getEntityManager(){
EntityManagerFactory emf;
Map properties = new HashMap();
properties.put("eclipselink.jdbc.driver", "com.mysql.jdbc.Driver");
properties.put("eclipselink.jdbc.url", "jdbc:mysql://localhost:3306/SampleDB");
properties.put("eclipselink.jdbc.user", "root");
properties.put("eclipselink.jdbc.password", "root");
//emf = Persistence.createEntityManagerFactory("jpablogPUnit");
emf = Persistence.createEntityManagerFactory("datajpa",properties);
return (EntityManager) emf.createEntityManager();
}
I am using a hibernate java application which uses a sessionfactory to create connections and sessions. As i am using it with a postgresql database i pass the proper jdbc connectionstring to build the sessionfactory and get my sessions from it afterwards. The only thing im able to access is the jdbc4connection.
How am i able to read which ciphersuite is used within the secured connection, which SSL protocol is used etc?
Here is how i initialize my sessionfactory:
Configuration configuration = new Configuration();
Properties p = configuration.getProperties();
p.setProperty("hibernate.connection.url","jdbc:postgresql://127.0.0.1:5432/postgres?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory");
p.setProperty("hibernate.connection.username", "myusername");
p.setProperty("hibernate.connection.password", "mypassword");
p.setProperty("hibernate.connection.driver_class",
"org.postgresql.Driver");
p.setProperty("hibernate.dialect",
"org.hibernate.dialect.PostgreSQLDialect");
ServiceRegistry serviceRegistryWebOnkys = new StandardServiceRegistryBuilder()
.applySettings(p).build();
SessionFactory sessionFactory = configuration
.buildSessionFactory(serviceRegistryWebOnkys);
If you can find out how to do it with via regular JDBC (I don't know how it's done), then you can do the same thing with Hibernate.
session.doWork(new Work() {
#Override
public void execute(Connection connection) throws SQLException {
// access the connection here and perform regular jdbc operations.
}
});
This is what I had to do when I had set some Oracle specific properties that could be set only on "OracleConnection.java" instances.
oracle.jdbc.driver.OracleConnection oc = (oracle.jdbc.driver.OracleConnection) connection.getMetaData().getConnection()
I have the following structure:
A layer with Hibernate 4.0.1, using C3P0 as connection Pool.
I don't have datasources configured, I use a dynamic configuration of datasource like it:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("persitenceUnit", createMap(ds));
'ds' is a object with my database properties, like user, password, url, ...
I get Entitymanager this way:
EntityManager em = emf.createEntityManager();
I try get connection this way:
EntityManagerImpl entityManagerImpl = (EntityManagerImpl)em;
SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl)entityManagerImpl.getSession().getSessionFactory();
Connection con = sessionFactoryImpl.getConnectionProvider().getConnection();
But, con is a NewProxyConnection instance. I need execute a procedure that return an ORAData and con.prepareCall(sqlToProcedure) return a NewProxyCallableStatment that no have a getOraData, ie, this code don't work:
OracleCallableStatment ocs = (OracleCallableStatment)con.prepareCall('{call stp_test(?)}');
ocs.excute();
TestObjectodf to = ocs.getOraDATA(1, TestObject.getOraDataFactory());
The error happens in
OracleCallableStatment ocs = (OracleCallableStatment)con.prepareCall('{call stp_test(?)}');
I try:
NewProxyConnection npCon = sessionFactoryImpl.getConnectionProvider().getConnection();
Connection con = npCon.unwrap(Connection.class);
But don't work.
The unwrap() method will work, if you upgrade to the latest c3p0-0.9.5 prerelease version. unwrap() is a JDBC4 method, supported by c3p0 as of c3p0-0.9.5. Since you want an OracleCallableStatement, you will probably want to call the unwrap() method of a CallableStatement, rather than the unwrap() method of a Connection, as you try above.
Alternatively (and a bit more safely), with almost any version of the library, you can use c3p0's raw statement operations. See the docs.
How can I get the current Connection object for an Oracle database? I'm using the JDBC module in Spring 3.0.5.
Obtain the Connection from the DataSource bean.
You can access the dataSource by using Spring dependency injection to inject it into your bean, or by accessing ApplicationContext statically:
DataSource ds = (DataSource)ApplicationContextProvider.getApplicationContext().getBean("dataSource");
Connection c = ds.getConnection();
Just an Info :
I am using Spring JDBC Template, which holds the current connection object for me, which can be received as follows.
Connection con;
con = getJdbcTemplate().getDataSource().getConnection();
Use DataSourceUtils.getConnection().
It returns connection associated with the current transaction, if any.
I'm not sure if this method was available when this question was originally posted, however, it seems the preferred way to do it in the latest version of Spring is with JdbcTemplate and PreparedStatementCreator. See https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html#query-org.springframework.jdbc.core.PreparedStatementCreator-org.springframework.jdbc.core.PreparedStatementSetter-org.springframework.jdbc.core.ResultSetExtractor- or any of the other query methods that take a PreparedStatementCreator as the first param:
jdbcTemplate.query(con -> {
// add required logic here
return con.prepareStatement("sql");
}, rs -> {
//process row
});
This has the advantage over the other provided answers (DataSourceUtils.getConnection() or jdbcTemplate.getDataSource().getConnection() as a new connection is not allocated, it uses the same connection management it would as calling any of the other jdbcTemplate querying methods. You also therefore do not need to worry about closing / releasing the connection, since spring will handle it.