Commit 800eb010 authored by Stephane Nicoll's avatar Stephane Nicoll

Change the default JDBC connection pool to Hikari

Closes gh-6013
parent 2e491dfa
...@@ -126,9 +126,10 @@ public class PublicMetricsAutoConfigurationTests { ...@@ -126,9 +126,10 @@ public class PublicMetricsAutoConfigurationTests {
} }
@Test @Test
public void autoDataSource() { public void autoDataSource() throws SQLException {
load(DataSourceAutoConfiguration.class); load(DataSourceAutoConfiguration.class);
PublicMetrics bean = this.context.getBean(DataSourcePublicMetrics.class); PublicMetrics bean = this.context.getBean(DataSourcePublicMetrics.class);
this.context.getBean(DataSource.class).getConnection().close();
Collection<Metric<?>> metrics = bean.metrics(); Collection<Metric<?>> metrics = bean.metrics();
assertMetrics(metrics, "datasource.primary.active", "datasource.primary.usage"); assertMetrics(metrics, "datasource.primary.active", "datasource.primary.usage");
} }
......
...@@ -104,7 +104,7 @@ public class DataSourceAutoConfiguration { ...@@ -104,7 +104,7 @@ public class DataSourceAutoConfiguration {
@Configuration @Configuration
@Conditional(PooledDataSourceCondition.class) @Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class, @Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class }) DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class })
protected static class PooledDataSourceConfiguration { protected static class PooledDataSourceConfiguration {
......
...@@ -84,9 +84,8 @@ public class DataSourceAutoConfigurationTests { ...@@ -84,9 +84,8 @@ public class DataSourceAutoConfigurationTests {
this.context.register(DataSourceAutoConfiguration.class, this.context.register(DataSourceAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
org.apache.tomcat.jdbc.pool.DataSource dataSource = this.context HikariDataSource dataSource = this.context.getBean(HikariDataSource.class);
.getBean(org.apache.tomcat.jdbc.pool.DataSource.class); assertThat(dataSource.getJdbcUrl()).isNotNull();
assertThat(dataSource.getUrl()).isNotNull();
assertThat(dataSource.getDriverClassName()).isNotNull(); assertThat(dataSource.getDriverClassName()).isNotNull();
} }
...@@ -114,41 +113,41 @@ public class DataSourceAutoConfigurationTests { ...@@ -114,41 +113,41 @@ public class DataSourceAutoConfigurationTests {
} }
@Test @Test
public void tomcatValidatesConnectionByDefault() { public void hikariValidatesConnectionByDefault() throws Exception {
org.apache.tomcat.jdbc.pool.DataSource dataSource = autoConfigureDataSource( HikariDataSource dataSource = autoConfigureDataSource(HikariDataSource.class,
org.apache.tomcat.jdbc.pool.DataSource.class); "org.apache.tomcat");
assertThat(dataSource.isTestOnBorrow()).isTrue(); assertThat(dataSource.getConnectionTestQuery()).isNull();
assertThat(dataSource.getValidationQuery()) // Use Connection#isValid()
.isEqualTo(DatabaseDriver.HSQLDB.getValidationQuery());
} }
@Test @Test
public void hikariIsFallback() throws Exception { public void tomcatIsFallback() throws Exception {
HikariDataSource dataSource = autoConfigureDataSource(HikariDataSource.class, org.apache.tomcat.jdbc.pool.DataSource dataSource = autoConfigureDataSource(
"org.apache.tomcat"); org.apache.tomcat.jdbc.pool.DataSource.class, "com.zaxxer.hikari");
assertThat(dataSource.getJdbcUrl()).isEqualTo("jdbc:hsqldb:mem:testdb"); assertThat(dataSource.getUrl()).isEqualTo("jdbc:hsqldb:mem:testdb");
} }
@Test @Test
public void hikariValidatesConnectionByDefault() throws Exception { public void tomcatValidatesConnectionByDefault() {
HikariDataSource dataSource = autoConfigureDataSource(HikariDataSource.class, org.apache.tomcat.jdbc.pool.DataSource dataSource = autoConfigureDataSource(
"org.apache.tomcat"); org.apache.tomcat.jdbc.pool.DataSource.class, "com.zaxxer.hikari");
assertThat(dataSource.getConnectionTestQuery()).isNull(); assertThat(dataSource.isTestOnBorrow()).isTrue();
// Use Connection#isValid() assertThat(dataSource.getValidationQuery())
.isEqualTo(DatabaseDriver.HSQLDB.getValidationQuery());
} }
@Test @Test
public void commonsDbcp2IsFallback() throws Exception { public void commonsDbcp2IsFallback() throws Exception {
BasicDataSource dataSource = autoConfigureDataSource(BasicDataSource.class, BasicDataSource dataSource = autoConfigureDataSource(BasicDataSource.class,
"org.apache.tomcat", "com.zaxxer.hikari"); "com.zaxxer.hikari", "org.apache.tomcat");
assertThat(dataSource.getUrl()).isEqualTo("jdbc:hsqldb:mem:testdb"); assertThat(dataSource.getUrl()).isEqualTo("jdbc:hsqldb:mem:testdb");
} }
@Test @Test
public void commonsDbcp2ValidatesConnectionByDefault() throws Exception { public void commonsDbcp2ValidatesConnectionByDefault() throws Exception {
org.apache.commons.dbcp2.BasicDataSource dataSource = autoConfigureDataSource( org.apache.commons.dbcp2.BasicDataSource dataSource = autoConfigureDataSource(
org.apache.commons.dbcp2.BasicDataSource.class, "org.apache.tomcat", org.apache.commons.dbcp2.BasicDataSource.class, "com.zaxxer.hikari",
"com.zaxxer.hikari"); "org.apache.tomcat");
assertThat(dataSource.getTestOnBorrow()).isEqualTo(true); assertThat(dataSource.getTestOnBorrow()).isEqualTo(true);
assertThat(dataSource.getValidationQuery()).isNull(); // Use Connection#isValid() assertThat(dataSource.getValidationQuery()).isNull(); // Use Connection#isValid()
} }
...@@ -163,7 +162,7 @@ public class DataSourceAutoConfigurationTests { ...@@ -163,7 +162,7 @@ public class DataSourceAutoConfigurationTests {
this.context.refresh(); this.context.refresh();
DataSource bean = this.context.getBean(DataSource.class); DataSource bean = this.context.getBean(DataSource.class);
assertThat(bean).isNotNull(); assertThat(bean).isNotNull();
org.apache.tomcat.jdbc.pool.DataSource pool = (org.apache.tomcat.jdbc.pool.DataSource) bean; HikariDataSource pool = (HikariDataSource) bean;
assertThat(pool.getDriverClassName()).isEqualTo("org.hsqldb.jdbcDriver"); assertThat(pool.getDriverClassName()).isEqualTo("org.hsqldb.jdbcDriver");
assertThat(pool.getUsername()).isEqualTo("sa"); assertThat(pool.getUsername()).isEqualTo("sa");
} }
...@@ -215,7 +214,7 @@ public class DataSourceAutoConfigurationTests { ...@@ -215,7 +214,7 @@ public class DataSourceAutoConfigurationTests {
this.context.refresh(); this.context.refresh();
DataSource bean = this.context.getBean(DataSource.class); DataSource bean = this.context.getBean(DataSource.class);
assertThat(bean).isNotNull(); assertThat(bean).isNotNull();
org.apache.tomcat.jdbc.pool.DataSource pool = (org.apache.tomcat.jdbc.pool.DataSource) bean; HikariDataSource pool = (HikariDataSource) bean;
assertThat(pool.getDriverClassName()).isEqualTo( assertThat(pool.getDriverClassName()).isEqualTo(
"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfigurationTests$DatabaseTestDriver"); "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfigurationTests$DatabaseTestDriver");
assertThat(pool.getUsername()).isNull(); assertThat(pool.getUsername()).isNull();
......
...@@ -24,6 +24,7 @@ import java.util.Random; ...@@ -24,6 +24,7 @@ import java.util.Random;
import javax.sql.DataSource; import javax.sql.DataSource;
import com.zaxxer.hikari.HikariDataSource;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
...@@ -112,7 +113,7 @@ public class DataSourceInitializerTests { ...@@ -112,7 +113,7 @@ public class DataSourceInitializerTests {
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
DataSource dataSource = this.context.getBean(DataSource.class); DataSource dataSource = this.context.getBean(DataSource.class);
assertThat(dataSource instanceof org.apache.tomcat.jdbc.pool.DataSource).isTrue(); assertThat(dataSource).isInstanceOf(HikariDataSource.class);
assertThat(dataSource).isNotNull(); assertThat(dataSource).isNotNull();
JdbcOperations template = new JdbcTemplate(dataSource); JdbcOperations template = new JdbcTemplate(dataSource);
assertThat(template.queryForObject("SELECT COUNT(*) from BAR", Integer.class)) assertThat(template.queryForObject("SELECT COUNT(*) from BAR", Integer.class))
...@@ -131,7 +132,7 @@ public class DataSourceInitializerTests { ...@@ -131,7 +132,7 @@ public class DataSourceInitializerTests {
.addResourcePathToPackagePath(getClass(), "data.sql")); .addResourcePathToPackagePath(getClass(), "data.sql"));
this.context.refresh(); this.context.refresh();
DataSource dataSource = this.context.getBean(DataSource.class); DataSource dataSource = this.context.getBean(DataSource.class);
assertThat(dataSource instanceof org.apache.tomcat.jdbc.pool.DataSource).isTrue(); assertThat(dataSource).isInstanceOf(HikariDataSource.class);
assertThat(dataSource).isNotNull(); assertThat(dataSource).isNotNull();
JdbcOperations template = new JdbcTemplate(dataSource); JdbcOperations template = new JdbcTemplate(dataSource);
assertThat(template.queryForObject("SELECT COUNT(*) from FOO", Integer.class)) assertThat(template.queryForObject("SELECT COUNT(*) from FOO", Integer.class))
...@@ -154,7 +155,7 @@ public class DataSourceInitializerTests { ...@@ -154,7 +155,7 @@ public class DataSourceInitializerTests {
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
DataSource dataSource = this.context.getBean(DataSource.class); DataSource dataSource = this.context.getBean(DataSource.class);
assertThat(dataSource instanceof org.apache.tomcat.jdbc.pool.DataSource).isTrue(); assertThat(dataSource).isInstanceOf(HikariDataSource.class);
assertThat(dataSource).isNotNull(); assertThat(dataSource).isNotNull();
JdbcOperations template = new JdbcTemplate(dataSource); JdbcOperations template = new JdbcTemplate(dataSource);
assertThat(template.queryForObject("SELECT COUNT(*) from FOO", Integer.class)) assertThat(template.queryForObject("SELECT COUNT(*) from FOO", Integer.class))
...@@ -177,7 +178,7 @@ public class DataSourceInitializerTests { ...@@ -177,7 +178,7 @@ public class DataSourceInitializerTests {
.addResourcePathToPackagePath(getClass(), "encoding-data.sql")); .addResourcePathToPackagePath(getClass(), "encoding-data.sql"));
this.context.refresh(); this.context.refresh();
DataSource dataSource = this.context.getBean(DataSource.class); DataSource dataSource = this.context.getBean(DataSource.class);
assertThat(dataSource instanceof org.apache.tomcat.jdbc.pool.DataSource).isTrue(); assertThat(dataSource).isInstanceOf(HikariDataSource.class);
assertThat(dataSource).isNotNull(); assertThat(dataSource).isNotNull();
JdbcOperations template = new JdbcTemplate(dataSource); JdbcOperations template = new JdbcTemplate(dataSource);
assertThat(template.queryForObject("SELECT COUNT(*) from BAR", Integer.class)) assertThat(template.queryForObject("SELECT COUNT(*) from BAR", Integer.class))
...@@ -197,7 +198,7 @@ public class DataSourceInitializerTests { ...@@ -197,7 +198,7 @@ public class DataSourceInitializerTests {
this.context.refresh(); this.context.refresh();
DataSource dataSource = this.context.getBean(DataSource.class); DataSource dataSource = this.context.getBean(DataSource.class);
this.context.publishEvent(new DataSourceInitializedEvent(dataSource)); this.context.publishEvent(new DataSourceInitializedEvent(dataSource));
assertThat(dataSource instanceof org.apache.tomcat.jdbc.pool.DataSource).isTrue(); assertThat(dataSource).isInstanceOf(HikariDataSource.class);
assertThat(dataSource).isNotNull(); assertThat(dataSource).isNotNull();
JdbcOperations template = new JdbcTemplate(dataSource); JdbcOperations template = new JdbcTemplate(dataSource);
try { try {
...@@ -270,7 +271,7 @@ public class DataSourceInitializerTests { ...@@ -270,7 +271,7 @@ public class DataSourceInitializerTests {
this.context.setResourceLoader(resourceLoader); this.context.setResourceLoader(resourceLoader);
this.context.refresh(); this.context.refresh();
DataSource dataSource = this.context.getBean(DataSource.class); DataSource dataSource = this.context.getBean(DataSource.class);
assertThat(dataSource instanceof org.apache.tomcat.jdbc.pool.DataSource).isTrue(); assertThat(dataSource).isInstanceOf(HikariDataSource.class);
assertThat(dataSource).isNotNull(); assertThat(dataSource).isNotNull();
JdbcOperations template = new JdbcTemplate(dataSource); JdbcOperations template = new JdbcTemplate(dataSource);
assertThat(template.queryForObject("SELECT COUNT(*) from FOO", Integer.class)) assertThat(template.queryForObject("SELECT COUNT(*) from FOO", Integer.class))
......
...@@ -64,6 +64,7 @@ public class CustomHibernateJpaAutoConfigurationTests { ...@@ -64,6 +64,7 @@ public class CustomHibernateJpaAutoConfigurationTests {
// Set up environment so we get a MySQL database but don't require server to be // Set up environment so we get a MySQL database but don't require server to be
// running... // running...
EnvironmentTestUtils.addEnvironment(this.context, EnvironmentTestUtils.addEnvironment(this.context,
"spring.datasource.type:" + org.apache.tomcat.jdbc.pool.DataSource.class.getName(),
"spring.datasource.database:mysql", "spring.datasource.database:mysql",
"spring.datasource.url:jdbc:mysql://localhost/nonexistent", "spring.datasource.url:jdbc:mysql://localhost/nonexistent",
"spring.datasource.initialize:false", "spring.jpa.database:MYSQL"); "spring.datasource.initialize:false", "spring.jpa.database:MYSQL");
......
...@@ -2821,10 +2821,10 @@ ensuring that it happens once access to the database is no longer needed. ...@@ -2821,10 +2821,10 @@ ensuring that it happens once access to the database is no longer needed.
Production database connections can also be auto-configured using a pooling `DataSource`. Production database connections can also be auto-configured using a pooling `DataSource`.
Here's the algorithm for choosing a specific implementation: Here's the algorithm for choosing a specific implementation:
* We prefer the Tomcat pooling `DataSource` for its performance and concurrency, so if * We prefer HikariCP for its performance and concurrency, so if that is available we
that is available we always choose it. always choose it.
* Otherwise, if HikariCP is available we will use it. * Otherwise, if the Tomcat pooling `DataSource` is available we will use it.
* If neither the Tomcat pooling datasource nor HikariCP are available and if Commons * If neither HikariCP nor the Tomcat pooling datasource are available and if Commons
DBCP2 is available we will use it. DBCP2 is available we will use it.
If you use the `spring-boot-starter-jdbc` or `spring-boot-starter-data-jpa` If you use the `spring-boot-starter-jdbc` or `spring-boot-starter-data-jpa`
...@@ -2863,8 +2863,8 @@ loadable. ...@@ -2863,8 +2863,8 @@ loadable.
See {sc-spring-boot-autoconfigure}/jdbc/DataSourceProperties.{sc-ext}[`DataSourceProperties`] See {sc-spring-boot-autoconfigure}/jdbc/DataSourceProperties.{sc-ext}[`DataSourceProperties`]
for more of the supported options. These are the standard options that work regardless of for more of the supported options. These are the standard options that work regardless of
the actual implementation. It is also possible to fine-tune implementation-specific the actual implementation. It is also possible to fine-tune implementation-specific
settings using their respective prefix (`+spring.datasource.tomcat.*+`, settings using their respective prefix (`+spring.datasource.hikari.*+`,
`+spring.datasource.hikari.*+`, and `+spring.datasource.dbcp2.*+`). Refer to the `+spring.datasource.tomcat.*+`, and `+spring.datasource.dbcp2.*+`). Refer to the
documentation of the connection pool implementation you are using for more details. documentation of the connection pool implementation you are using for more details.
For instance, if you are using the For instance, if you are using the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment