Mastering Spring Boot Database Connection Pools: HikariCP vs Druid
This guide explains the need for JDBC connection pools, compares popular pools like HikariCP and Druid, and provides step‑by‑step configurations for both custom property files and Spring Boot auto‑configuration, helping you efficiently manage database connections in Java applications.
1. Background
When using JDBC, developers typically load the driver, create a connection, execute SQL, and then manually close the connection. Under low load this works, but with high concurrency the number of connections can become insufficient, leading to errors.
Database connection pools solve this problem by reusing a pool of pre‑created connections: a client obtains an idle connection from the pool, uses it, and returns it for future reuse, improving efficiency and response time.
Common open‑source JDBC connection pool frameworks include:
C3P0 – an old pool, performance poor, no longer maintained.
DBCP – Apache pool used by Tomcat, single‑threaded, low concurrency.
Tomcat JDBC Pool – an upgraded DBCP with asynchronous acquisition.
BoneCP – fast but unmaintained since 2013.
Druid – Alibaba’s pool with rich monitoring, very popular in China.
HikariCP – a high‑performance pool built on BoneCP, now the default in Spring Boot 2.
Performance tests rank the pools as
HikariCP > Druid > tomcat-jdbc > dbcp > c3p0. HikariCP achieves the best performance by minimizing lock contention, while Druid offers the most features such as SQL interception and slow‑query monitoring.
2. HikariCP
Two ways to configure HikariCP: using a custom configuration file or leveraging Spring Boot’s auto‑configuration.
2.1 Custom configuration file
2.1.1 Add HikariCP dependency
<code><dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
</dependency></code>2.1.2 Application properties
<code># Custom Hikari datasource properties
hikari.driver-class-name=com.mysql.jdbc.Driver
hikari.url=jdbc:mysql://localhost:3306/test
hikari.username=root
hikari.password=root
hikari.pool-name=HikariCP
hikari.minimum-idle=5
hikari.maximum-pool-size=20
hikari.idle-timeout=600000
hikari.auto-commit=true
hikari.max-lifetime=1800000
hikari.connection-timeout=30000
hikari.connection-test-query=SELECT 1</code>2.1.3 HikariDataSourceConfig class
<code>@Configuration
public class HikariDataSourceConfig {
@Value("${hikari.driver-class-name}") private String driverClassName;
@Value("${hikari.url}") private String url;
@Value("${hikari.username}") private String userName;
@Value("${hikari.password}") private String password;
@Value("${hikari.pool-name}") private String poolName;
@Value("${hikari.minimum-idle}") private Integer minimumIdle;
@Value("${hikari.maximum-pool-size}") private Integer maximumPoolSize;
@Value("${hikari.idle-timeout}") private Integer idleTimeout;
@Value("${hikari.auto-commit}") private Boolean autoCommit;
@Value("${hikari.max-lifetime}") private Integer maxLifetime;
@Value("${hikari.connection-timeout}") private Integer connectionTimeout;
@Value("${hikari.connection-test-query}") private String connectionTestQuery;
@Bean
public DataSource primaryDataSource() {
HikariConfig config = new HikariConfig();
config.setDriverClassName(driverClassName);
config.setJdbcUrl(url);
config.setUsername(userName);
config.setPassword(password);
config.setPoolName(poolName);
config.setMinimumIdle(minimumIdle);
config.setMaximumPoolSize(maximumPoolSize);
config.setIdleTimeout(idleTimeout);
config.setAutoCommit(autoCommit);
config.setMaxLifetime(maxLifetime);
config.setConnectionTimeout(connectionTimeout);
config.setConnectionTestQuery(connectionTestQuery);
return new HikariDataSource(config);
}
}</code>Start the application to load the datasource.
2.2 Spring Boot integration (recommended)
Spring Boot 2+ uses HikariCP as the default datasource. Adding
spring-boot-starter-jdbcbrings the dependency automatically.
<code><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency></code>Configure via Spring Boot properties:
<code>spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.hikari.pool-name=HikariCP
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1</code>Start the application; the datasource is initialized automatically.
3. Druid
Druid is a widely used open‑source connection pool with built‑in monitoring capabilities.
Two configuration approaches are provided: custom property files and Spring Boot auto‑configuration.
3.1 Custom configuration file
3.1.1 Add Druid dependency
<code><dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.17</version>
</dependency></code>3.1.2 Application properties
<code># Druid datasource configuration
druid.driver-class-name=com.mysql.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/test
druid.username=root
druid.password=root
druid.initialSize=5
druid.minIdle=5
druid.maxActive=20
druid.maxWait=60000
druid.minEvictableIdleTimeMillis=300000
druid.timeBetweenEvictionRunsMillis=60000
druid.validationQuery=SELECT 1 FROM DUAL
druid.testWhileIdle=true
druid.testOnBorrow=false
druid.testOnReturn=false
druid.poolPreparedStatements=false
druid.filters=stat,wall
druid.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
druid.useGlobalDataSourceStat=true</code>3.1.3 DruidConfig class
<code>@Configuration
public class DruidConfig {
@Value("${druid.driver-class-name}") private String driverClassName;
@Value("${druid.url}") private String url;
@Value("${druid.username}") private String username;
@Value("${druid.password}") private String password;
@Value("${druid.initialSize}") private Integer initialSize;
@Value("${druid.minIdle}") private Integer minIdle;
@Value("${druid.maxActive}") private Integer maxActive;
@Value("${druid.maxWait}") private Integer maxWait;
@Value("${druid.minEvictableIdleTimeMillis}") private Integer minEvictableIdleTimeMillis;
@Value("${druid.timeBetweenEvictionRunsMillis}") private Integer timeBetweenEvictionRunsMillis;
@Value("${druid.validationQuery}") private String validationQuery;
@Value("${druid.testWhileIdle}") private boolean testWhileIdle;
@Value("${druid.testOnBorrow}") private boolean testOnBorrow;
@Value("${druid.testOnReturn}") private boolean testOnReturn;
@Value("${druid.poolPreparedStatements}") private boolean poolPreparedStatements;
@Value("${druid.filters}") private String filters;
@Value("${druid.connectionProperties}") private String connectionProperties;
@Value("${druid.useGlobalDataSourceStat}") private boolean useGlobalDataSourceStat;
@Bean
public DruidDataSource dataSourceDefault() {
DruidDataSource datasource = new DruidDataSource();
datasource.setDriverClassName(driverClassName);
datasource.setUrl(url);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
// log error
}
datasource.setConnectionProperties(connectionProperties);
datasource.setUseGlobalDataSourceStat(useGlobalDataSourceStat);
return datasource;
}
}</code>3.1.4 DruidMonitorConfig class
<code>@Configuration
public class DruidMonitorConfig {
@Bean
public ServletRegistrationBean<StatViewServlet> statViewServlet() {
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet());
bean.addUrlMappings("/druid/*");
Map<String, String> initParas = new HashMap<>();
initParas.put("loginUsername", "admin");
initParas.put("loginPassword", "123456");
initParas.put("allow", "");
initParas.put("resetEnable", "false");
bean.setInitParameters(initParas);
return bean;
}
@Bean
public FilterRegistrationBean<WebStatFilter> webStatFilter() {
FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new WebStatFilter());
bean.addUrlPatterns("/*");
Map<String, String> initParams = new HashMap<>();
initParams.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
return bean;
}
}</code>After starting the service, access
http://127.0.0.1:8080/druid/and log in with the configured credentials to view the monitoring dashboard.
3.2 Spring Boot integration (recommended)
3.2.1 Add druid‑spring‑boot‑starter dependency
<code><dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency></code>3.2.2 Spring Boot properties for Druid
<code>spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
spring.datasource.druid.min-evictable-idle-time-millis=300000
spring.datasource.druid.time-between-eviction-runs-millis=60000
spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-on-return=false
spring.datasource.druid.pool-prepared-statements=false
spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.merge-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=5000
spring.datasource.druid.filter.wall.enabled=true
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=12345678
spring.datasource.druid.stat-view-servlet.reset-enable=false
spring.datasource.druid.web-stat-filter.enabled=true
spring.datasource.druid.web-stat-filter.url-pattern=/*
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.css,/druid/*</code>Start the application; the effect is equivalent to the manual configuration method.
4. Conclusion
This article consolidates knowledge on integrating database connection pools—HikariCP and Druid—with Spring Boot, enabling controlled management of database connections and improving application performance.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.