Learning from the document of HikariCP we know there is a property "dataSourceClassName" to define a class to create database connection, it works fine if I build the HikariCP in programming:
HikariConfig config = new HikariConfig();
config.setUsername("");
config.setDataSourceClassName("com.my.own.DataSource");
HikariDataSource hikariDs = new HikariDataSource(config);
// database accessing with hikariDs created above
// ...
But when I try to configure the data source class name in the application.yml file of a spring boot application, it can not work, here is the config:
spring:
datasource:
url: ${jdbc_url}
hikari:
dataSourceClassName: com.my.own.DataSource
maximum-pool-size: 64
And here is the error from HikariCP:
java.lang.IllegalStateException: cannot use driverClassName and dataSourceClassName together.
at com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:1011)
The error above is very clear, we can not set driverClassName and dataSourceClassName together, after check the source code of spring boot, I find out the the driverClassName is from property spring.datasource.url:
// org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration#createDataSource
private static <T> T createDataSource(JdbcConnectionDetails connectionDetails, Class<? extends DataSource> type,
ClassLoader classLoader) {
return (T) DataSourceBuilder.create(classLoader)
.type(type)
.driverClassName(connectionDetails.getDriverClassName())
.url(connectionDetails.getJdbcUrl())
.username(connectionDetails.getUsername())
.password(connectionDetails.getPassword())
.build();
}
// org.springframework.boot.jdbc.DataSourceBuilder#build
public T build() {
DataSourceProperties<T> properties = DataSourceProperties.forType(this.classLoader, this.type);
DataSourceProperties<DataSource> deriveFromProperties = getDeriveFromProperties();
Class<? extends T> instanceType = (this.type != null) ? this.type : properties.getDataSourceInstanceType();
T dataSource = BeanUtils.instantiateClass(instanceType);
Set<DataSourceProperty> applied = new HashSet<>();
for (DataSourceProperty property : DataSourceProperty.values()) {
String value = this.values.get(property);
if (value == null && deriveFromProperties != null && properties.canSet(property)) {
value = deriveFromProperties.get(this.deriveFrom, property);
}
if (value != null) {
properties.set(dataSource, property, value);
applied.add(property);
}
}
if (!applied.contains(DataSourceProperty.DRIVER_CLASS_NAME)
&& properties.canSet(DataSourceProperty.DRIVER_CLASS_NAME)
&& this.values.containsKey(DataSourceProperty.URL)) {
String url = this.values.get(DataSourceProperty.URL);
DatabaseDriver driver = DatabaseDriver.fromJdbcUrl(url);
properties.set(dataSource, DataSourceProperty.DRIVER_CLASS_NAME, driver.getDriverClassName());
}
return dataSource;
}
By reading above code, we can see that the driverClassName will be set if there is spring.datasource.url existing, and spring.datasource.url is a mandatory property if you are not using embedded database. So for my understanding, we can not set the data source class name in the application.yml, if I want to define a customized data source class, I need to do it in programming like this:
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setUsername("");
config.setDataSourceClassName("com.my.own.DataSource");
return new HikariDataSource(config);
}
Am I right?