Unwrap NewProxyConnection and GetConnection from NewProxyConnection - java

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.

Related

Create Entity Manger runtime with connection pooling in Spring and eclipse Link JPA

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();
}

Java JPA, setting transaction isolation level using an entity manager

I'm trying to set a transaction isolation level for the connection associated with a given entity manager (TRANSACTION_SERIALIZABLE etc.).
I have scoured the internet for a solution and found a few. However, none of them seem to work.
When I try to do the following :
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("BankingPU");
public EntityManager em = emfactory.createEntityManager();
java.sql.Connection connection = (java.sql.Connection) em.getDelegate();
connection.setTransactionIsolation(TRANSACTION_SERIALIZABLE);
I get the following exception:
Exception in thread "main" java.lang.ClassCastException:
org.eclipse.persistence.internal.jpa.EntityManagerImpl cannot be cast to java.sql.Connection
When I do
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("BankingPU");
public EntityManager em = emfactory.createEntityManager();
java.sql.Connection connection = em.unwrap(java.sql.Connection.class);
The value stored to connection is null.
I ran the following in order to find out more:
Object obj = em.getDelegate();
The class type stored in obj is org.eclipse.persistence.internal.jpa.EntityManagerImpl
Edit: (oops, guess I could have told that from the exception)
Edit2:
I have managed to obtain the session (i think) by calling :
Session session = ((EntityManagerImpl) em).getSession();
However, neither the connection(), nor the DoWork() methods are present in it.
Any idea how to follow up on this and set the transaction isolation level?
JPA API does not have transaction (TX) isolation level management API. So it is not possible do it via entity manager.
If you want to use the same entity manager than you need, as it already mentioned in Neil Stockton comment, your JPA provider specific code to get JDBC access for changing TX isolation level.
Adam Bien almost answered on your question at his blog post.
Isolation Levels can be set on java.sql.Connection level. In a Java EE environment isolation levels can be configured on Data Source / Connection Pool (see e.g. Glassfish).
As workaround, if you want use only JPA API, you may create in your application server the several data sources for the same database with required isolation level.
However you need to understand that you will have the several 1st level caches (in different entity managers) and you should manage your entities state in appropriate way.
I have found the solution:
emfactory = Persistence.createEntityManagerFactory("BankingPU");
em = emfactory.createEntityManager();
Session session = ((EntityManagerImpl) em).getSession();
DatabaseLogin databaseLogin = (DatabaseLogin) session.getDatasourceLogin();
databaseLogin.setTransactionIsolation(DatabaseLogin.TRANSACTION_SERIALIZABLE);

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

How to use Postresql Large Object API with Spring's JdbcTemplate

I need to access a Large Object using postgresql API. This is done like this:
PGConnection pgConn=(PGConnection)c
LargeObjectManager lobj =pgConn.getLargeObjectAPI();
LargeObject obj = lobj.open(imageOid, LargeObjectManager.READ);
InputStram is=obj.getInputStream();
I need to run this code from my DAO while using Spring's JdbcTemplate. How can I get access to the connection I'm using?
Assuming that DataSource has been configured correctly,
PGConnection pgConn = (PGConnection) jdbcTemplate.getDataSource().getConnection();

How to get current Connection object in Spring JDBC

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.

Categories

Resources