Java 数据库连接池介绍(7)--HikariCP 介绍
HikariCP 是一个快速、简单、可靠的 JDBC 连接池,在性能上做了很多优化,是目前最快的数据库连接池;本文主要介绍 HikariCP 的基本使用,文中使用到的软件版本:Java 1.8.0_191、HikariCP 4.0.3、Spring Boot 2.3.12.RELEASE。
1、配置参数
HikariCP 所有时间相关的参数单位都为 ms。
1.1、基本配置
参数 | 默认值 | 描述 |
dataSourceClassName | none | 驱动里面数据源的类名称;不支持 XA 数据源,各数据源对应的数据源类名可参见 ”2、数据源类名“ |
jdbcUrl | none | 连接 url;该参数与 dataSourceClassName 设置一个即可 |
username | none | 用户名 |
password | none | 密码 |
1.2、常用配置
参数 | 默认值 | 描述 |
autoCommit | true | 连接返回连接池时,是否自动提交事务 |
connectionTimeout | 30000 | 从连接池获取连接的最大超时时间 |
idleTimeout | 60000 | 空闲连接存活的最大时间,当空闲连接数 >minimumIdle 且 连接的空闲状态时间 >idleTimeout 时,将把该连接从连接池中删除;只有当 minimumIdle < maximumPoolSize 时,该设置才生效;0 表示永不超时 |
keepaliveTime | 0 | 保持空闲连接可用的检测频率,单位:ms;0 表示不检测 |
maxLifetime | 1800000 | 连接存活的最大时间;0 表示没有限制 |
connectionTestQuery | none | 连接检测的查询语句;如果驱动支持 JDBC 4,强烈建议不要设置此参数 |
minimumIdle | same as maximumPoolSize | 最小空闲连接数;为了提高性能,建议不要设置此参数,使连接池为固定大小 |
maximumPoolSize | 10 | 最大连接数 |
metricRegistry | none | 该参数仅通过编程配置或 IoC 容器可用;该参数用于指定池使用的 Codahale/Dropwizard MetricRegistry 实例来记录各种指标。 |
healthCheckRegistry | none | 该参数仅通过编程配置或 IoC 容器可用;该参数用于指定池使用的 Codahale/Dropwizard HealthCheckRegistry 实例来记录健康信息。 |
poolName | auto-generated | 连接池名称 |
1.3、不常用配置
参数 | 默认值 | 描述 |
initializationFailTimeout | 1 | 启动连接池时不能成功初始化连接,是否快速失败。>0 时,会尝试获取连接。如果获取时间超过指定时长 (connectionTimeout + initializationFailTimeout),不会开启连接池,并抛出异常。=0 时,会尝试获取并验证连接。如果获取成功但验证失败则不开启池,但是如果获取失败还是会开启池。<0 时,直接启动连接池,不进行初始化连接尝试。 |
isolateInternalQueries | false | 是否在事务中隔离 HikariCP 自己的查询;autoCommit 为 false 时,该设置生效 |
allowPoolSuspension | false | 是否允许通过 JMX 挂起和恢复连接池;挂起时获取连接不会超时,知道连接池恢复 |
readOnly | false | 连接是否只读 |
registerMbeans | false | 是否开启 JMX |
catalog | driver default | 默认的数据库 catalog |
connectionInitSql | none | 连接池初始化后执行的 SQL |
driverClassName | none | 驱动类名;HikariCP 会尝试通过 jdbcUrl 来确定 driverClassName,但对一些老的驱动必须指定 driverClassName;可以忽略该配置除非报 "the driver was not found" 的错误。 |
transactionIsolation | driver default | 默认的事务隔离级别 |
validationTimeout | 5000 | 连接检测的超时时间;必须大于 connectionTimeout,最小允许的值为 250 |
leakDetectionThreshold | 0 | 连接可以被借出多久;超过该时间将打印连接可能泄露的日志,最小允许的值为 2000,单位 ms |
dataSource | none | 指定数据源;此参数仅通过编程配置或 IoC 容器可用,当设置此参数,dataSourceClassName 和所有 DataSource- 相关的属性将被忽略。 |
schema | driver default | 默认的数据库 schema |
threadFactory | none | 指定连接池用于创建线程的 java.util.concurrent.ThreadFactory 实例;此参数仅通过编程配置或 IoC 容器可用 |
scheduledExecutor | none | 指定连接池用于执行定时任务的 java.util.concurrent.ScheduledExecutorService 实例;此参数仅通过编程配置或 IoC 容器可用 |
详细的配置说明可参考官网文档:https://github.com/brettwooldridge/HikariCP
2、数据源类名
HikariCP 建议使用 dataSourceClassName 代替 jdbcUrl,但是两个都是支持的。
注:Spring Boot 基于自动配置,使用 jdbcUrl。
MySQL 的 DataSource 不支持网络超时,使用 jdbcUrl 代替。
常用数据库的 JDBC 数据源类名如下:
Database | Driver | DataSource class |
---|---|---|
Apache Derby | Derby | org.apache.derby.jdbc.ClientDataSource |
Firebird | Jaybird | org.firebirdsql.ds.FBSimpleDataSource |
H2 | H2 | org.h2.jdbcx.JdbcDataSource |
HSQLDB | HSQLDB | org.hsqldb.jdbc.JDBCDataSource |
IBM DB2 | IBM JCC | com.ibm.db2.jcc.DB2SimpleDataSource |
IBM Informix | IBM Informix | com.informix.jdbcx.IfxDataSource |
MS SQL Server | Microsoft | com.microsoft.sqlserver.jdbc.SQLServerDataSource |
Connector/J | ||
MariaDB | MariaDB | org.mariadb.jdbc.MariaDbDataSource |
Oracle | Oracle | oracle.jdbc.pool.OracleDataSource |
OrientDB | OrientDB | com.orientechnologies.orient.jdbc.OrientDataSource |
PostgreSQL | pgjdbc-ng | com.impossibl.postgres.jdbc.PGDataSource |
PostgreSQL | PostgreSQL | org.postgresql.ds.PGSimpleDataSource |
SAP MaxDB | SAP | com.sap.dbtech.jdbc.DriverSapDB |
SQLite | xerial | org.sqlite.SQLiteDataSource |
SyBase | jConnect | com.sybase.jdbc4.jdbc.SybDataSource |
3、使用
3.1、直接使用
3.1.1、引入依赖
<dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>4.0.3</version> </dependency>
3.1.2、使用例子
package com.abc.demo.general.dbpool;import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class HikariCPCase {
private static Logger logger = LoggerFactory.getLogger(HikariCPCase.class);</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 使用 dataSourceClassName </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> test1() { HikariConfig hikariConfig </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HikariConfig(); hikariConfig.setPoolName(</span>"HikariCP 连接池"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.setDataSourceClassName(</span>"oracle.jdbc.pool.OracleDataSource"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.addDataSourceProperty(</span>"user", "test"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.addDataSourceProperty(</span>"password", "123456"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.addDataSourceProperty(</span>"url", "jdbc:oracle:thin:@10.49.196.10:1521:test"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.setMaximumPoolSize(</span>15<span style="color: rgba(0, 0, 0, 1)">); HikariDataSource hikariDataSource </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HikariDataSource(hikariConfig); Connection connection </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { connection </span>=<span style="color: rgba(0, 0, 0, 1)"> hikariDataSource.getConnection(); Statement st </span>=<span style="color: rgba(0, 0, 0, 1)"> connection.createStatement(); ResultSet rs </span>= st.executeQuery("select * from v$version"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (rs.next()) { logger.info(rs.getString(</span>1<span style="color: rgba(0, 0, 0, 1)">)); } } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) { e.printStackTrace(); } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> { close(connection); } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实际使用中一般是在应用启动时初始化数据源,应用从数据源中获取连接;并不会关闭数据源。</span>
hikariDataSource.close();
}</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 使用jdbc-url </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> test2() { HikariConfig hikariConfig </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HikariConfig(); hikariConfig.setPoolName(</span>"HikariCP 连接池"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.setDriverClassName(</span>"com.mysql.cj.jdbc.Driver"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.setJdbcUrl(</span>"jdbc:mysql://10.49.196.11:3306/mydb?useUnicode=true&characterEncoding=UTF-8"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.setUsername(</span>"root"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.setPassword(</span>"123456"<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.setMinimumIdle(</span>2<span style="color: rgba(0, 0, 0, 1)">); hikariConfig.setMaximumPoolSize(</span>10<span style="color: rgba(0, 0, 0, 1)">); HikariDataSource hikariDataSource </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HikariDataSource(hikariConfig); Connection connection </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { connection </span>=<span style="color: rgba(0, 0, 0, 1)"> hikariDataSource.getConnection(); Statement st </span>=<span style="color: rgba(0, 0, 0, 1)"> connection.createStatement(); ResultSet rs </span>= st.executeQuery("select version()"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (rs.next()) { logger.info(rs.getString(</span>1<span style="color: rgba(0, 0, 0, 1)">)); } } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) { e.printStackTrace(); } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> { close(connection); } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实际使用中一般是在应用启动时初始化数据源,应用从数据源中获取连接;并不会关闭数据源。</span>
hikariDataSource.close();
}</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> close(Connection connection) { </span><span style="color: rgba(0, 0, 255, 1)">if</span> (connection != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { connection.close(); } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) { e.printStackTrace(); } } }
}
3.2、在 SpringBoot 中使用
3.2.1、引入依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.12.RELEASE</version> <relativePath /> </parent><dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>org.springframework<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>spring-jdbc<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>com.zaxxer<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>HikariCP<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">></span>4.0.3<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>mysql<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>mysql-connector-java<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span>
</dependencies>
3.2.2、单数据源
application.yml 配置:
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://10.140.9.11:3306/mydb?useUnicode=true&characterEncoding=UTF-8 username: root password: 123456 #type: com.zaxxer.hikari.HikariDataSource hikari: maximum-pool-size: 15
使用:
@Autowired private DataSource dataSource;
3.2.3、多数据源
application.yml 配置:
spring: datasource: hikari: db1: pool-name: 连接池 1 driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://10.49.196.11:3306/mydb?useUnicode=true&characterEncoding=UTF-8 username: root password: 123456 maximum-pool-size: 15 db2: pool-name: 连接池 2 driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://10.49.196.12:3306/mydb?useUnicode=true&characterEncoding=UTF-8 username: root password: 123456 maximum-pool-size: 15
数据源配置类:
package com.abc.demo.config;import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Primary
@Bean(name = "dataSource1")
@ConfigurationProperties("spring.datasource.hikari.db1")
public DataSource dataSourceOne(){
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}@Bean(name </span>= "dataSource2"<span style="color: rgba(0, 0, 0, 1)">) @ConfigurationProperties(</span>"spring.datasource.hikari.db2"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> DataSource dataSourceTwo(){ </span><span style="color: rgba(0, 0, 255, 1)">return</span> DataSourceBuilder.create().type(HikariDataSource.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">).build(); }
}
使用:
@Autowired @Qualifier("dataSource1") private DataSource dataSource1;@Autowired
@Qualifier("dataSource2")
private DataSource dataSource2;