adding prepare statement before calling getconnection () function from the connection pool - spring

I want to add a prepare statement before calling the getconnection() from my hibernate hikariCP connection pool.
the statement is dbms_session.set_identifier("Current User");
I've been trying to do so with spring AOP without any success.
Then i thought trying to wrap the hikariCP connection provider, but i can't find a good example or guidline how to do it
can someone help please ?

Related

Set default schema = SOMETHING in oracle using Spring Boot and Spring JDBC

I am working now with oracle and spring jdbc but I don't want to use the schema in my sql statements:
Example: Select * from SCHEMA.table
Is there any way to set default schema in application.properties or application.yml?
Assuming you define your database connections using spring datasources, you can set the default schema when defining the datasource configuration:
spring.datasource.schema = #value for your default schema to use in database
You can find more info here: Spring Boot Reference Guide. Appendix A. Common application properties
After doing some research, looks like Oracle driver doesn't let you set a default schema to work with, as noted here:
Default Schema in Oracle Connection URL
From that post, you have two options:
Execute this statement before executing your statements:
ALTER SESSION SET CURRENT_SCHEMA=yourSchema
Create synonyms for your tables/views/etc (which I find really cumbersome if we're talking about lots of elements in your database).
I would advice using the first option. From what I see, Spring boot doesn't offer a simple way to execute a statement when retrieving the connection, so the best bet will be to use an aspect around the getConnection method (or the method that retrieves the connection from the data source) and execute the statement there.
From your comment, an easier way to solve it is by using a script in spring.datasource.schema:
spring.datasource.schema = schema.sql
And then a file squema.sql with the following:
ALTER SESSION SET CURRENT_SCHEMA=mySchema
In spring boot, I've found another way of doing it,
#Bean
#ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource(#Value("${spring.datasource.schema}") String schema) {
DataSource datasource = DataSourceBuilder.create().build();
if(!schema.isEmpty() && datasource instanceof org.apache.tomcat.jdbc.pool.DataSource){
((org.apache.tomcat.jdbc.pool.DataSource) datasource).setInitSQL("ALTER SESSION SET CURRENT_SCHEMA=" + schema);
}
return datasource;
}
I found another way to get around this by updating entity class with
#Table(schema = "SCHEMA_NAME" ,name = "TABLE_NAME")
If you are using hikari, use spring.datasource.hikari.schema=YOUR_SCHEMA.
Works for me with SpringBoot + tomcat using Oracle.
I was having issues with the currently accepted answer; specifically, the schema would only be changed from the initial connection. If your app uses a connection pool, you need to configure the pool to apply SQL for each connection.
For instance, using the default jdbc pool in Spring Boot 1.5.x (Tomcat):
spring.datasource.tomcat.init-s-q-l = ALTER SESSION SET CURRENT_SCHEMA=mySchema
Connecting to the database as your user, you can create a trigger that will change the schema each time you login:
CREATE OR REPLACE TRIGGER LOGON_TRG
AFTER LOGON ON SCHEMA
BEGIN
EXECUTE IMMEDIATE 'ALTER SESSION SET CURRENT_SCHEMA = foo';
EXCEPTION
when others
then null;
END;
/
Another option is to create a datasource wrapper. Create the datasource as normal and then create the wrapper that forwards all methods except for the getConnection methods. For those I just added SQL to set the schema. We have multiple datasources and this allowed us to specify a different schema for each datasource. If anyone knows if there's an issue with this I'd love comments. Or if there's an alternative that uses the properties.

Spring jdbctemplate is it required to close the connection

I am fetching the connection in jdbctemplate in below fashion:-
getJdbcTemplate().getDataSource().getConnection()
Is it necessary to close the connection fetched in the above manner? The spring JDBCTemplate API states that connection closures will be handled automatically , so I am not sure if this is happening correctly.
http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/jdbc.html
When you are obtaining the DataSource from the JdbcTemplate and use that to obtain a Connection you are basically completely bypassing the JdbcTemplate. You now have a very complex way of obtaining a new Connection. Because this connection isn't managed by Spring but yourself you also need to close it and apply exception handling.
It is better to use the ConnectionCallback instead to get a Connection. The JdbcTemplate will then manage the Connection and do all resource handling.
getJdbcTemplate().execute(new ConnectionCallback<Void>() {
public Void doInConnection(Connection conn) {
// Your JDBC code here.
}
});
It would even better to use one of the other JdbcTemplate methods and write proper code which would save you from messing with plain JDBC code at all.

Spring Hibernate Connection from database not released

I am getting the following error below
Unexpected error
org.springframework.transaction.CannotCreateTransactionException:
**CannotCreateTransactionException:** Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.GenericJDBC
Exception: Could not open connection
Here is the scenario in which it occurs :
I have recently moved some table from mysql to mongo. The code is written in such a way that either data would be taken from mongo/mysql.
The code is written in a method block which is annotated with #Transactional provided by spring framework.
There is hibernate layer which is using transaction provided by spring. c3p0 is the connection pool.
The parameter of connection pool is
hibernate.c3p0.min_size=5
hibernate.c3p0.timeout=1200
hibernate.c3p0.max_size=35
hibernate.c3p0.max_statements=50
The problem comes when we try to pull the data from mongo.Looks like the transaction is not getting closed because of mongo operation.The database connection is not getting released .It reaches the max size defined in the pool.
Tried the query in DB to find out the connection
show status like '%onn%';
Any suggestion to resolve this would really help.
Thanks

Is there a way to overcome DSRA9010E "'setReadOnly' is not supported on the WebSphere" exception?

our application is using Spring for TX management and is marking certain transactions as readonly. When deploying our application on websphere (8.5.5.3) with a Oracle JDBC Connection we are getting exceptions like the following:
Caused by: java.sql.SQLException: DSRA9010E: 'setReadOnly' is not supported on the WebSphere java.sql.Connection implementation.
at com.ibm.ws.rsadapter.spi.InternalOracleDataStoreHelper.setReadOnly(InternalOracleDataStoreHelper.java:371)
at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.setReadOnly(WSJdbcConnection.java:3646)
at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.getTargetConnection(LazyConnectionDataSourceProxy.java:410)
at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.invoke(LazyConnectionDataSourceProxy.java:376)
at com.sun.proxy.$Proxy476.getMetaData(Unknown Source)
at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:619)
at org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy$TransactionAwareInvocationHandler.invoke(TransactionAwareDataSourceProxy.java:239)
at com.sun.proxy.$Proxy476.getMetaData(Unknown Source)
I know what websphere is trying to tell me but I was wondering if there is a way to disable this check so that Connection.setReadonly calls are just ignored instead of throwing an exception.
Of course I could also change the application to not use readonly transactions but that would be much more complicated.
Try to unwrap the connection object like this:
Context ic = new InitialContext();
DataSource ds = (DataSource)ic.lookup("jdbc/OracleDS");
Connection conn = ds.getConnection();
if (conn.isWrapperFor(oracle.jdbc.OracleConnection.class)) {
// Returns an object that implements the given interface to
// allow access to non-standard methods, or standard methods
// not exposed by the proxy.
oracle.jdbc.OracleConnection oraCon = conn.unwrap(oracle.jdbc.OracleConnection.class);
// Do some Oracle-specific work here.
oraCon.setReadOnly(readOnly);
....
}
conn.close();
See WebSphere Application Server and the JDBC 4.0 Wrapper Pattern
Oracle JDBC (12c onwards; perhaps 11g as well?) can be tricky to use with readonly -
according to https://marschall.github.io/2017/01/28/oracle-read-only.html:
Calling Connection.setReadOnly(true) with the 12c driver no longer establishes a read only transaction
This means that Spring (before version 4.3.7) also struggles to set read only transactions with Oracle JDBC (see previous link).
To overcome this, you need to manually include SET TRANSACTION READ ONLY in your SQL, instead of relying on Spring's #Transactional(readOnly=true).
However, from Spring 4.3.7, the transaction now acts correctly, and so you should no longer see this issue (https://github.com/spring-projects/spring-framework/issues/19774)

Perform commit(), rollabck(), setAutoCommit(false) on JDBC Connection from CMT JTA

I have created glassfish connection pool with ResourceType as ConnectionPoolDataSource.So, glassfish will use the native connection pool implementation for connection pooling. I am not using XADatasource ResourceType as I don't want to perform any distributed transactions.
My application requires the use of TEMPERORY MYSQL table creation at run time. So I am using
the below code to get the connection from JNDI Datasource of glassfish.
#Resource(mappedName = "jdbc/xxxxx")
private DataSource dataSource;
public Connection getConnection() throws SQLException {
Connection con = dataSource.getConnection();
return con;
}
Now, My question is, Can I perform setAutoCommit(false), commit() and rollback(), close() on this Connection object????
In forum, I read that, we should not call these methods on Connection object, if we get the Connection from Container Managed Distributed Transaction (XADataSource) as its involved in distributed transactions.
But, I am getting this connection from non-distributed transactions.So, I can call those methods right???
Other question is, after performing db operations, If I call con.close(), will this connection go back to the connection pool again?

Resources