I need to set some specific Oracle JDBC connection properties in order to speed up batch INSERT
s (defaultBatchValue
) and mass SELECT
s (defaultRowPrefetch
).
I got suggestions how to achieve this with DBCP (Thanks to M. Deinum) but I would like to:
- keep the default Tomcat jdbc connection pool
- keep application.yml for configuration
I was thinking about a feature request to support spring.datasource.custom_connection_properties
or similar in the future and because of this tried to pretent this was already possible. I did this by passing the relevant information while creating the DataSource and manipulated the creation of the DataSource like this:
@Bean
public DataSource dataSource() {
DataSource ds = null;
try {
Field props = DataSourceBuilder.class.getDeclaredField("properties");
props.setAccessible(true);
DataSourceBuilder builder = DataSourceBuilder.create();
Map<String, String> properties = (Map<String, String>) props.get(builder);
properties.put("defaultRowPrefetch", "1000");
properties.put("defaultBatchValue", "1000");
ds = builder.url( "jdbc:oracle:thin:@xyz:1521:abc" ).username( "ihave" ).password( "wonttell" ).build();
properties = (Map<String, String>) props.get(builder);
log.debug("properties after: {}", properties);
} ... leaving out the catches ...
}
log.debug("We are using this datasource: {}", ds);
return ds;
}
In the logs I can see that I am creating the correct DataSource:
2016-01-18 14:40:32.924 DEBUG 31204 --- [ main] d.a.e.a.c.config.DatabaseConfiguration : We are using this datasource: org.apache.tomcat.jdbc.pool.DataSource@19f040ba{ConnectionPool[defaultAutoCommit=null; ...
2016-01-18 14:40:32.919 DEBUG 31204 --- [ main] d.a.e.a.c.config.DatabaseConfiguration : properties after: {password=wonttell, driverClassName=oracle.jdbc.OracleDriver, defaultRowPrefetch=1000, defaultBatchValue=1000, url=jdbc:oracle:thin:@xyz:1521:abc, username=ihave}
The actuator shows me that my code replaced the datasource:
But the settings are not activated, which I can see while profiling the application. The defaultRowPrefetch
is still at 10
which causes my SELECT
s to be much slower than they would be if 1000
was activated.
Some additional information to complement the answer by @Cyril. If you want to upvote use his answer, not mine.
I was a little bit puzzled how easy it is to set additional connection properties that in the end get used while creating the database connection. So I did a little bit of research.
spring.datasource.connectionProperties
is not mentioned in the reference. I created an issue because of this. If I had used the Spring Boot YML editor, I would have seen which properties are supported. Here is what STS suggests when you create anapplication.yml
and hit Ctrl+Space:The dash does not matter because of relaxed binding but if you interpret it literally the propertys name is
spring.datasource.connection-properties
.The correct setup in application.yml looks like this:
This gets honored which is proven by my perf4j measurements of mass
SELECT
s.Before:
After:
The time taken to complete the SQL statement drops from 1377ms to 147, which is an enormous gain in performance.
After digging around in the Tomcat code for a bit, I found that the
dataSource.getPoolProperties().getDbProperties()
is theProperties
object that will actually get used to generate connections for the pool.If you use the
BeanPostProcessor
approach mentioned by @m-deinum, but instead use it to populate thedbProperties
like so, you should be able to add the properties in a way that makes them stick and get passed to the Oracle driver.Setting the pools connectionProperties should work. Those will be passed to the JDBC driver. Add this to application.properties:
Edit (some background information):
source: spring-boot documentation