Executing native query with Hibernate 4.1 - oracle

I'm using Hibernate with C3P0 connection pool. In Hibernate 3 I could get access to wrapped C3P0ProxyConnection through BorrowedConnectionProxy and then perform rawConnectionOperation. From what I see BorrowedConnectionProxy is not a part of Hibernate 4.1 anymore.
Is it any way I can run vendor specific queries ? (An instance of proxy connection inside Work.execute does not work for me, I need to execute Oracle stored procedure that takes collection of custom object type).
Thank you .

You can get access to the unproxied Connection in Work by calling:
public void execute(Connection connection) throws SQLException {
Connection unproxiedConnection = connection.unwrap( Connection.class );
...
}
That form leverages the JDBC 4 unwrap method, we simply delegate that to the underlying connection. Or if you specifically need an OracleConnection:
public void execute(Connection connection) throws SQLException {
OracleConnection oracleConnection = connection.unwrap( OracleConnection.class );
...
}
You could also use:
public void execute(Connection connection) throws SQLException {
Connection unproxiedConnection = ( (JdbcWrapper<Connection>) connection ).getWrappedObject();
...
}
I have gone back and forth in terms of contemplating allowing the Work to signify that it wants an unproxied Connection, but given the availability of Connection#unwrap I am not so sure there is an real benefit.

Related

Spring #transactional with #async Timeout value is not working

I have created an asynchronous service for a long running stored procedure call. Things work good but the transaction is not getting timed out after the specified value given in the timeout attribute of the transactional annotation..The structure of the code is given below (not the real one...just skeleton...ignore semantics/syntax)
//asynchronous service
#override
#async("myCustomTaskExecutor")
#Transactional(rollbackfor=Exception.class,timeout=600)
public void serviceMethod(){
//repository method is invoked.
repository.callStoredProcedure();
}
//Repository method in the Repository class
#Transactional(rollbackfor=Exception.class,timeout=600)
public void callStoredProcedure(){
//Stored procedure is called from the private method using hibernate doWork implementation.
privateCallmethod();
}
private void privateCallmethod() throws ApplicationException{
Session session = null;
try{
session = entityManager.unwrap(Session.class);
session.doWork(new Work(){
#Override
public void execute(Connection connection) throws SQLException {
OracleCallableStatement statement =null;
try{
//using hibernate 4.x and ref cursors are used...so went on with this approach..
//suggest if there is some better approach.
String sqlString =“{begin storProcName(?,?)}”;
statement = connection.prepareCall(sqlString);
statement.setInt(1,5);
statement.setString(2,“userName5”);
statement.executeUpdate();
}
catch(Exception e){
throw RunTimeException(e.getMessage);
}
finally{
if(statement != null)
statement.close();
}
}
}
});
}
catch(Exception e){
throw ApplicationException(e.getMessage);
}
//Not using Final block to close the session.Is it an issue ?
}
delay is happening in the stored procedure side(Thread.sleep(700) are not used) yet transaction is not timed out...
Questions :
I guess #Transactional is enough on the service method alone...give little bit insight on correct approach of using #Transactional annotation
for this code setup.
Will the #Transactional works for the JDBC calls inside the doWork Interface implementation...is that whats the issue is ?
Some article suggest to use oracle.jdbc.readTimeout or setQueryTimeout in the CallableStatement... Is it the right way to achieve this.
Kindly point out the mistakes and explain the causes
If #Transactional Annotated method is not the entry point to the class, it will not be transactional unless you enable load time weaving (Spring default is Compile time weaving) https://stackoverflow.com/a/17698587/6785908
You should invoke callStoredProcedure() from outside this class, then it will be transactional. If you invoke serviceMethod() which in turn invokes callStoredProcedure(), then it will not be transactional
I used setQueryTimeout() approach to resolve the issue as #Transactional timeout does not work with the hibernate dowork() method...I guess its due to the hibernate work executes in different thread and it low level JDBC methods to invoke the store procedures...
NOTE: This particular application uses very spring 3.x version and hibernate 4.x with JPA 2.0 spec...little outdated versions

Spring Data JPA, how to get Connection used by the current transaction context

How do I get the java.sql.Connection used by the current transaction context? Or is the connection actually opened at the end of transaction?
Inject the entityManager then retrieve the current hibernate session
Session session = (Session) entityManager.getDelegate();
Then retrieve the jdbc connection from the session.
By using the doWork function you can actually retrieve the connection
session.doWork(new Work() {
#Override
public void execute(Connection connectionToUse) throws SQLException {
}
});

jdbc connection pool using ThreadpoolExecutor in spring boot

I have an application that runs through multiple databases and for each database runs select query on all tables and dumps it to hadoop.
My design is to create one datasource connection at a time and use the connection pool obtained to run select queries in multiple threads. Once done for this datasource, close the connection and create new one.
Here is the Async code
#Component
public class MySampleService {
private final static Logger LOGGER = Logger
.getLogger(MySampleService.class);
#Async
public Future<String> callAsync(JdbcTemplate template, String query) throws InterruptedException {
try {
jdbcTemplate.query(query);
//process the results
return new AsyncResult<String>("success");
}
catch (Exception ex){
return new AsyncResult<String>("failed");
}
}
Here is the caller
public String taskExecutor() throws InterruptedException, ExecutionException {
Future<String> asyncResult1 = mySampleService.callAsync(jdbcTemplate,query1);
Future<String> asyncResult2 = mySampleService.callAsync(jdbcTemplate,query2);
Future<String> asyncResult3 = mySampleService.callAsync(jdbcTemplate,query3);
Future<String> asyncResult4 = mySampleService.callAsync(jdbcTemplate,query4);
LOGGER.info(asyncResult1.get());
LOGGER.info(asyncResult2.get());
LOGGER.info(asyncResult3.get());
LOGGER.info( asyncResult4.get());
//now all threads finished, close the connection
jdbcTemplate.getConnection().close();
}
I am wondering if this is a right way to do it or do any exiting/optimized solution that out of box I am missing. I can't use spring-data-jpa since my queries are complex.
Thanks
Spring Boot docs:
Production database connections can also be auto-configured using a
pooling DataSource. Here’s the algorithm for choosing a specific
implementation:
We prefer the Tomcat pooling DataSource for its performance and concurrency, so if that is available we always choose it.
Otherwise, if HikariCP is available we will use it.
If neither the Tomcat pooling datasource nor HikariCP are available and if Commons DBCP is available we will use it, but we
don’t recommend it in production.
Lastly, if Commons DBCP2 is available we will use it.
If you use the spring-boot-starter-jdbc or
spring-boot-starter-data-jpa ‘starters’ you will automatically get a
dependency to tomcat-jdbc.
So you should be provided with sensible defaults.

Java Oracle JDBC Connection Timeout

I have developed some JSON web services using Servlets for my mobile app. I'm using (Oracle + Private Tomcat) hosting. I have one single class DBOperations.java which has a lot of static functions which are called in Servets for database operation. I use getConnection() method in each function to get Connection Object, create statement and execute queries. Issue is after some time connection get lost. I'm using the following code to re-establish the connection.
public static Connection conn;
Statement stmt;
public static Connection getConnection() throws SQLException {
if (conn == null || conn.isClosed() ) {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection(DB_URL, "username", "password");
return conn;
} catch (ClassNotFoundException | SQLException ex) {
}
} else {
return conn;
}
return conn;
}
I'm unable to figure out how I can handle the timeout/closed connection issue as the above code isn't re-establishing the connection. I need to restart Tomcat to get it back in working state. Any suggestions or help is highly appreciated.
You must use connection pooling, And let Tomcat server to handle everything. Create a JNDI datasource to achieve the same and you will never face such issue.
Used OraceDataSource for connection pooling and it's working perfectly.
public static OracleDataSource ods;
public static Connection getConnection() throws SQLException {
if (ods == null) {
ods = new OracleDataSource();
ods.setURL(DB_URL);
ods.setUser("username");
ods.setPassword("password");
}
return ods.getConnection();
}

Spring JDBC connection without dataSource

I had read several articles on obtaining Connection using Spring DataSource.
But in our Company Setup, connection object is obtained through already configured environment. Following the sample code:
String pool = PropertyFileReader.getPropertyValue("database.properties", "development.connectionPool");
Connection connection = RequestUtils.getConnection(pool);
Hence, After reading this tutorial
I am confused on using JDBCTemplate using connection object from above code.
I believe JdbcTemplate is not designed to work against a Connection as what you expected. As a workaround, if you are fine to create a separate JdbcTemplate for each connection you created, you may wrap your connection in a thin wrapper of DataSource, and feed it to JdbcTemplate.
I think it should work but I haven't tried it anyway...
class SingleConnectionDataSource implements DataSource {
private Connection connection;
public SingleConnectionDataSource(Connection connection) {
this.connection = connection;
}
public Connection getConnection() {
return this.connection;
}
public Connection getConnection(String username, String password) {
return this.connection;
}
}
// at the place you want to use JdbcTemplate
Connection conn = blablabla; // your own way to get it
JdbcTemplate jdbcTemplate = new JdbcTemplate(new SingleConnectionDataSource(conn));
Actually, Spring already provided SingleConnectionDataSource implementation (have seen in version 4.1.7).
It is even allows you to supress connection closing by template.

Resources