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.
Related
I am looking for the right way to set a run-time parameter when a database connection is open. My run-time parameter is actually a time zone, but I think this should work for an arbitrary parameter.
I've found following solutions, but I feel like none of these is the right thing.
JdbcInterceptor
Because Spring Boot has Apache Tomcat connection pool as default I can use org.apache.tomcat.jdbc.pool.JdbcInterceptor to intercept connections.
I don't think this interceptor provides a reliable way to perform a statement when connection is open. Possibility to intercept every statement provided by this interceptor is unnecessary to set a parameter that should be set only once.
initSQL property
Apache's pooled connection has a build-in ability to initialise itself by a statement provided by PoolProperties.initSQL parameter. This is executed in ConnectionPool.createConnection(...) method.
Unfortunately official support for this parameter has been removed from Spring and no equivalent functionality has been introduced since then.
I mean, I can still use a datasource builder like in an example below, and then hack the property into a connection pool, but this is not a good looking solution.
// Thank's to property binders used while creating custom datasource,
// the datasource.initSQL parameter will be passed to an underlying connection pool.
#Bean
#ConfigurationProperties(prefix = "datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
Update
I was testing this in a Spring Boot 1.x application. Above statements are no more valid for Spring Boot 2 applications, because:
Default Tomcat datasource was replaced by Hikari which supports spring.datasource.hikari.connection-init-sql property. It's documentation says Get the SQL string that will be executed on all new connections when they are created, before they are added to the pool.
It seems that similar property was reintroduced for Tomcat datasource as spring.datasource.tomcat.init-s-q-l.
ConnectionPreparer & AOP
This is not an actual solution. It is more like an inspiration. The connection preparer was a mechanism used to initialise Oracle connections in Spring Data JDBC Extensions project. This thing has its own problems and is no more maintained but possibly can be used as a base for similar solution.
If your parameter is actually a time zone, why don't you find a way to set this property.
For example if you want to store or read a DateTime with a predefined timestamp the right way to do this is to set property hibernate.jdbc.time_zone in hibernate entityManager or spring.jpa.properties.hibernate.jdbc.time_zone in application.properties
I have a doubt of how the spring boot JDBC template works. I have read the documentation , but could not understand clearly :( When does the template opens connection , when does it gets closed . How does the transactions are handled . Does it gets opened and closed for every query execution ?
When does the template opens connection, when does it gets closed
For building JdbcTemplate you should specify the JDBC DataSource to obtain connections from:
public JdbcTemplate(DataSource dataSource)
Or:
public JdbcTemplate()
JdbcAccessor.setDataSource(javax.sql.DataSource)
Conclusively, JdbcTemplate works with this DataSource.
DataSource, depending on the implementation, may return new standard Connection objects that are not pooled or Connection objects that participate in connection pooling which can be an be recycled.
JdbcTemplate has pooled connections and releases them back to DataSource.
How does the transactions are handled
JdbcTemplate relies on database transactions.
If you want to operate transactions on service layer/business logic you need transaction management.
The simplest way is to annotate services with #Transactional or use org.springframework.transaction.support.TransactionTemplate.
In a very large project where do we set up the database connection so that it is available across all the modules?
Suppose the requirement is like this:
LoginPage.html -> LoginServlet.java -> LoginService.java ==> Takes DB help to check the credentials.
Now, since the actual credentials are stored in DB, where do we set up the database so that the connection is available to all the modules?
In big projects, is database connection made as and when needed or database connections setup at the time when application is run and made available across all the modules.
If DB connections are made available to all the modules (which need DB connectivity), how is this achieved?
Thanks for your help and inputs.
Since you're not using an IoC approach (Spring), the alternative would be to have a static class (or a singleton) that has a reference to the DataSource. Whenever you need a Connection you only have to get it from that class:
public class JdbcUtils{
private static DataSource dataSource;
static{
dataSource = new DB2SimpleDataSource();
dataSource.setDatabaseName("DBNAME");
dataSource.setServerName("xxx.xxx.xxx.xxx");
dataSource.setPortNumber(447);
dataSource.setUser("USER");
dataSource.setPassword("PASS");
dataSource.setDriverType(4);
dataSource.setCurrentSchema("SCHEMA");
//OR even better get the DataSource through JNDI lookup if defined on server
}
public static Connection getConnection() throws SQLException{
return dataSource.getConnection()
}
}
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();
if i create a new instance of JdbcTemplate like so;
JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSource());
by passing the datasource as a param (the datasource retrieves a connection from server connection pool) am i required to close the connection when im finished with it?
In other words, if i have a pool of connections will the previous code cause my application to create a new connection each time a request executes the code
No. That's the whole deal. Use the JdbcTemplate and it will manage the ressources (Connection, PreparedStatement, ResultSet). It is an implementation of the template method design pattern.
Javadoc:
It simplifies the use of JDBC and helps to avoid common errors. It
executes core JDBC workflow, leaving
application code to provide SQL and
extract results.
What I did, was to extend the JdbcTemplate and override the execute method to use the connection pool (a particular case).