前言
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。连接池技术尽可能多地重用了消耗内存的资源,大大节省了内存。通过使用连接池,将大大提高程序运行效率。常用的数据库连接池有C3P0、DBCP、Druid及HikariCP等几种,以下分别对这几种连接池进行简单说明。
一、数据库连接池
1.1 什么是连接池
数据库连接池(Connection Pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地分配池中的连接进行申请、使用、释放。由于数据库连接的创建和断开是一个耗时性的操作,同时对数据库会造成安全隐患。因此,在程序初始化时集中创建多个连接,并将其集中管理供程序使用,可以保证较快的数据读写速度且提高系统的安全可靠性。
连接池是创建和管理一个连接的缓冲池,其核心思想是连接复用。连接池允许应用程序在需要时从池中获取连接,而不是每次都创建新连接。使用完毕后,连接可以被释放回池中以供其他请求使用。这种重用机制可以降低数据库服务器的负担,提高应用程序的性能。
1.2 为何要使用连接池
假设网站一天有很大的访问量,数据库服务器就需要为每次连接创建一次数据库连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。数据库连接是一种关键的有限的昂贵的资源,对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标,而数据库连接池正式针对这个问题提出来的。数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
1.3 JDBC 连接池
JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器提供实现,也有一些开源组织提供实现:
- DBCP 是Apache提供的数据库连接池。tomcat 服务器自带dbcp数据库连接池。速度相对c3p0较快,但因自身存在BUG,Hibernate3已不再提供支持。
- C3P0 是一个开源组织提供的一个数据库连接池,**速度相对较慢,稳定性还可以。**hibernate官方推荐使用
- Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
- BoneCP 是一个开源组织提供的数据库连接池,速度快
- Druid 是阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,但是速度不确定是否有BoneCP快。
DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池。DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度。
二、数据库连接池:C3P0
2.1 C3P0 简介
作为开源的数据库连接池,C3P0是一个优秀的连接池,性能也十分可靠。C3P0 可以与各种关系型数据库一起使用,包括 MySQL、Oracle、SQL Server 等,它实现了数据源与JNDI绑定,支持JDBC3规范和实现了JDBC2的标准扩展说明的Connection和Statement池的DataSources对象。
2.2 连接池的使用
若是想要使用 C3P0 数据库连接池,首先需要在项目中引入 C3P0 的相关依赖。如果使用 Maven,可以在 pom.xml
文件中添加以下依赖:
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.10.1</version>
</dependency>
接着,我们需要创建一个 C3P0 连接池的配置对象。C3P0 提供了 ComboPooledDataSource
类来实现这一功能。ComboPooledDataSource是C3P0提供的数据源,需要设置数据库的相关信息,包括数据库驱动类、JDBC URL、用户名和密码。以下是一个简单的配置示例:
public static void main(String[] args) throws Exception {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUser("root");
dataSource.setPassword("123456");
Connection conn = dataSource.getConnection();
}
其中,ComboPooledDataSource是C3P0提供的数据源,需要设置数据库的相关信息,包括数据库驱动类、JDBC URL、用户名和密码。getConnection()方法用于获取一个数据库连接。
2.3 连接池配置总结
关于c3p0一般有这么两种配置,一种是通过set方法进行配置,另一种是通过在同src目录下的c3p0-conflg.xml文件或者c3p0.properties文件进行相关的配置。
对于连接池的基本配置,如连接池的名称、用户名、密码、连接URL等,可以通过在配置文件中指定相关属性来完成。C3P0 提供了许多配置参数,可以根据应用程序的需求进行调整。以下是一些常用的配置参数和其作用的简要说明:
配置参数 | 说明 |
---|---|
user | 数据库用户名。 |
password | 数据库密码。 |
jdbcUrl | 数据库连接 URL。 |
initialPoolSize | 数据库连接池中初始化时的连接数 |
minPoolSize | 连接池中保持的最小连接数。 |
maxPoolSize | 连接池中允许的最大连接数。 |
maxIdleTime | 连接的最大空闲时间(以秒为单位)。 |
作为一个数据库连接池自然有很多参数要设置,这些参数可以在 ComboPooledDataSource
对象中进行设置,以满足不同场景下的需求。
2.3.1 通过set方法进行配置
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
/**
* 配置DataSource
*/
public static void configDataSource(){
try {
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/zhanghanlun");
dataSource.setUser("zhanghanlun");
dataSource.setPassword("123456");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(10);
dataSource.setMinPoolSize(3);
dataSource.setAcquireIncrement(3);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
}
/**
* 获取Connection连接
*/
public static Connection getConnection(){
Connection conn = null;
configDataSource();
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
2.4.2 通过c3p0-config.xml文件进行配置
关于通过配置文件进行配置的话,需要把xml文件方法同src文件夹下,c3p0会扫描文件进行相关的配置。废话不多说,下面是c3p0-config.xml文件的代码:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 默认配置,如果没有指定则使用这个配置 -->
<default-config>
<property name="user">root</property>
<property name="password">123456</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">3</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">2</property>
<property name="maxStatements">200</property>
</default-config>
<!-- 命名的配置,可以通过方法调用实现 -->
<named-config name="test">
<property name="user">root</property>
<property name="password">123456</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!-- 如果池中数据连接不够时一次增长多少个 -->
<property name="acquireIncrement">5</property>
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize">20</property>
<!-- 数据库连接池中的最大的数据库连接数 -->
<property name="maxPoolSize">25</property>
<!-- 数据库连接池中的最小的数据库连接数 -->
<property name="minPoolSize">5</property>
</named-config>
</c3p0-config>
2.4 连接池配置项
除了上面介绍的连接池配置方法以外,还有其他的配置方法,如连接池的自动回收机制、连接池的失败重试机制等。这些配置方法对于优化连接池的性能、稳定性具有重要作用。
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">3</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">30</property>
<!--两次连接中间隔时间,单位毫秒。Default: 1000 -->
<property name="acquireRetryDelay">1000</property>
<!--连接关闭时默认将所有未提交的操作回滚。Default: false -->
<property name="autoCommitOnClose">false</property>
<!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么 属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试 使用。Default: null-->
<property name="automaticTestTable">Test</property>
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试 获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->
<property name="breakAfterAcquireFailure">false</property>
<!--当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出 SQLException,如设为0则无限期等待。单位毫秒。Default: 0 -->
<property name="checkoutTimeout">100</property>
<!--通过实现ConnectionTester或QueryConnectionTester的类来测试连接。类名需制定全路径。 Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester-->
<property name="connectionTesterClassName"></property>
<!--指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可 Default: null-->
<property name="factoryClassLocation">null</property>
<!--Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs. (文档原文)作者强烈建议不使用的一个属性-->
<property name="forceIgnoreUnresolvedTransactions">false</property>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">60</property>
<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">3</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">60</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">15</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。 如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
<property name="maxStatements">100</property>
<!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
<property name="maxStatementsPerConnection"></property>
<!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能 通过多线程实现多个操作同时被执行。Default: 3-->
<property name="numHelperThreads">3</property>
<!--当用户调用getConnection()时使root用户成为去获取连接的用户。主要用于连接池连接非c3p0 的数据源时。Default: null-->
<property name="overrideDefaultUser">root</property>
<!--与overrideDefaultUser参数对应使用的一个参数。Default: null-->
<property name="overrideDefaultPassword">password</property>
<!--密码。Default: null-->
<property name="password"></property>
<!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意: 测试的表必须在初始数据源的时候就存在。Default: null-->
<property name="preferredTestQuery">select id from test where id=1</property>
<!--用户修改系统配置参数执行前最多等待300秒。Default: 300 -->
<property name="propertyCycle">300</property>
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable 等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout">false</property>
<!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->
<property name="testConnectionOnCheckin">true</property>
<!--用户名。Default: null-->
<property name="user">root</property>
<!--早期的c3p0版本对JDBC接口采用动态反射代理。在早期版本用途广泛的情况下这个参数 允许用户恢复到动态反射代理以解决不稳定的故障。最新的非反射代理更快并且已经开始 广泛的被使用,所以这个参数未必有用。现在原先的动态反射与新的非反射代理同时受到 支持,但今后可能的版本可能不支持动态反射代理。Default: false-->
<property name="usesTraditionalReflectiveProxies">false</property>
<property name="automaticTestTable">con_test</property>
<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">25</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">0</property>
</default-config>
</c3p0-config>
2.5 C3P0 示例
使用连接池的步骤如下:
public class ConnectionManager {
private static ConnectionManager instance;
private static ComboPooledDataSource dataSource;
/**
* 创建数据库连接池对象
*/
private ConnectionManager() throws PropertyVetoException {
dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("123456");
dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/test");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setInitialPoolSize(5);
dataSource.setMinPoolSize(1);
dataSource.setMaxPoolSize(10);
dataSource.setMaxStatements(50);
dataSource.setMaxIdleTime(60);
}
/**
* 使用单利模式创建数据库连接池
*/
public static final ConnectionManager getInstance() {
if (instance == null) {
try {
instance = new ConnectionManager();
} catch (Exception e) {
e.printStackTrace();
}
}
return instance;
}
/**
* 获取连接对象
*/
public synchronized final Connection getConnection() {
Connection conn = null;
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
下面是测试代码:
public class ConnectionDemo {
public static void main(String[] args) throws SQLException {
System.out.println("使用连接池................................");
for (int i = 0; i < 20; i++) {
long beginTime = System.currentTimeMillis();
Connection conn = ConnectionManager.getInstance().getConnection();
try {
PreparedStatement pstmt = conn.prepareStatement("select * from event");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
// do nothing...
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis();
System.out.println("第" + (i + 1) + "次执行花费时间为:" + (endTime - beginTime));
}
}
}
三、数据库连接池:DBCP
3.1 DBCP 是什么
DBCP 是 Apache 上的一个 Java连接池项目,也是 tomcat使用的连接池组件。Apache DBCP 提供了基本的连接池功能,虽然性能不如HikariCP,但胜在稳定性和易于配置。由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。
注意:dbcp没有自动的去回收空闲连接的功能。
3.2 连接池的使用
若是想要使用 DBCP 数据库连接池,首先需要在项目中引入 DBCP 的相关依赖。如果使用 Maven,可以在 pom.xml
文件中添加以下依赖:
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>x.y.z</version>
</dependency>
然后在代码中使用以下方式获取连接:
public static void main(String[] args) throws Exception {
// 1 获得连接池
BasicDataSource dataSource = new BasicDataSource();
// 1.1 基本项
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("123456");
// 1.2 其他项
dataSource.setInitialSize(5);
dataSource.setMaxActive(10);
// 2 获得连接
Connection conn = dataSource.getConnection();
}
其中,BasicDataSource是DBCP提供的数据源,需要设置数据库的相关信息,包括数据库驱动类、JDBC URL、用户名和密码。getConnection()方法用于获取一个数据库连接。
3.3 常见配置项
分类 | 属性 | 描述 |
---|---|---|
必须项 | driverClassName | |
url | ||
username | ||
password | ||
基本项 | maxActive | 最大连接数量 |
minIdle | 最小空闲连接 | |
maxIdle | 最大空闲连接 | |
initialSize | 初始化连接 | |
优化配置(扩展) | logAbandoned | 连接被泄露时是否打印 |
removeAbandoned | 是否自动回收超时连接 | |
removeAbandonedTimeout | 超时时间(以秒数为单位) | |
maxWait | 超时等待时间以毫秒为单位 1000等于60秒 | |
timeBetweenEvictionRunsMillis | 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位 | |
numTestsPerEvictionRun | 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 | |
minEvictableIdleTimeMillis | 连接在池中保持空闲而不被空闲连接回收器线程 |
参考文档:http://commons.apache.org/proper/commons-dbcp/configuration.html
四、数据库连接池:Druid
4.1 Druid是什么
Druid 是阿里巴巴开源的一个功能强大、性能优越的数据库连接池,它是一个高效的并发连接管理工具,可大幅提升应用程序的数据库访问效率。它支持对于许多不同类型的数据库,例如 MySQL、Oracle、PostgreSQL 和 SQL Server 等。Druid 结合了C3P0、DBCP、Proxool等DB池的优点,同时加入了 日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池,可以说无论是在单机应用还是分布式系统中,Druid连接池都是一个可靠、高效的选择。主要特点和优势如下:
- 高性能:Druid连接池采用了一系列性能优化策略,包括预先创建连接、连接池复用、有效的连接验证等,以提供高效的数据库连接获取和释放操作。它还支持连接池的异步初始化和预热,以减少请求响应时间。
- 监控统计:Druid提供了丰富的监控和统计功能,可以实时监控连接池的状态、活动连接数、请求频率、SQL执行情况等。通过集成Druid的监控模块,可以方便地查看连接池的性能指标和诊断数据库访问问题。
- 防止泄露和超时:Druid连接池具有连接泄露检测和自动回收的功能,可以检测未正确关闭的连接,并自动将其回收到连接池中。此外,它还支持连接超时配置,在连接空闲时间过长时自动关闭连接,以释放资源。
- 数据库连接池扩展:Druid连接池支持多种数据库驱动程序,包括常见的MySQL、Oracle、PostgreSQL等。它还提供了一些扩展功能,如连接池分区、读写分离、SQL防火墙等,以满足不同应用场景的需求。
- 配置灵活性:Druid连接池的配置项非常丰富,可以灵活地调整连接池的大小、最大连接数、最小空闲连接数、连接超时时间等参数,以适应不同的负载和性能要求。
4.2 连接池的使用
若是想要使用 HikariCP 数据库连接池,首先需要在项目中引入 HikariCP 的相关依赖。如果使用 Maven,可以在 pom.xml
文件中添加以下依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>x.y.z</version>
</dependency>
然后在代码中使用以下方式获取连接:
public static void main(String[] args) throws Exception {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("123456");
Connection conn = dataSource.getConnection();
}
其中,DruidDataSource是Druid提供的数据源,需要设置数据库的相关信息,包括数据库驱动类、JDBC URL、用户名和密码。getConnection()方法用于获取一个数据库连接。
其次,我们需要创建一个配置文件,命名为druid.properties。有配置如下:
# 需要配置driverClassName才能支持国产数据库
driverClassname=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis=1800000
# 连接有效性检测
validationQuery=SELECT 'x'
# 配置监控统计拦截的filters,filters常用种类:
# 监控统计用的filter:stat
# 日志用的filter:log4j
# 防御sql注入的filter:wall目前不支持国产数据库
filters=stat,log4j
public static void main(String[] args) throws Exception {
Properties pro = new Properties();
InputStream is = druidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
try {
pro.load(is);
} catch (IOException e) {
e.printStackTrace();
}
// 获取数据库连接池对象:通过工厂来获取 DruidDataSourceFactory
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
Connection conn = ds.getConnection();
System.out.println("conn:"+conn);
}
4.3 参数介绍
参数介绍
配置 | 缺省值 | 说明 |
---|---|---|
name | 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 | |
url | 连接数据库的url,不同数据库不一样。 | |
username | 连接数据库的用户名 | |
password | 连接数据库的密码。 | |
driverClassName | 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName | |
initialSize | 0 | 初始化时建立物理连接的个数。 |
maxActive | 8 | 最大连接池数量 |
minIdle | 最小连接池数量 | |
maxWait | 获取连接时最大等待时间,单位毫秒。 | |
poolPreparedStatements | false | 是否缓存preparedStatement,也就是PSCache。 |
maxPoolPreparedStatementPerConnectionSize | -1 | 要启用PSCache,必须配置大于0。 当大于0时,poolPreparedStatements自动触发修改为true。 |
validationQuery | 用来检测连接是否有效的sql | |
validationQueryTimeout | 单位:秒,检测连接是否有效的超时时间。 | |
testOnBorrow | true | 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 |
testOnReturn | false | 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 |
testWhileIdle | false | 申请连接的时候检测。建议配置为true,不影响性能,并且保证安全性。 |
keepAlive | false | 连接池中的minIdle数量以内的连接 |
timeBetweenEvictionRunsMillis | 1分钟 | 检测连接的间隔时间 |
minEvictableIdleTimeMillis | 连接保持空闲而不被驱逐的最小时间 | |
connectionInitSqls | 物理连接初始化的时候执行的sql | |
exceptionSorter | 当数据库抛出一些不可恢复的异常时,抛弃连接 | |
filters |
具体参考官网:DruidDataSource配置属性列表
五、数据库连接池:HikariCP
5.1 HikariCP 是什么
HikariCP 是一个快速、高效和可靠的Java连接池库,适用于需要处理大量数据库操作的应用程序。它被广泛应用于各种Java项目,包括Web应用程序、大数据处理、微服务等。主要特点和优势如下:
- 高性能:HikariCP通过有效地管理连接池、使用轻量级的数据结构和最小化的锁定机制,实现了卓越的性能。它具有低延迟和高吞吐量,适用于处理大量并发数据库操作的场景。
- 资源效率:HikariCP在连接池管理方面非常高效。它采用了快速的连接获取和释放机制,以及优化的连接验证和闲置连接检测策略,减少了资源的消耗和浪费。
- 配置简单:HikariCP提供了简洁而直观的配置选项,使得连接池的设置和调整变得容易。你可以通过一些基本的配置参数来优化连接池的大小、超时设置、连接验证等。
- 自动管理:HikariCP内置了自动管理和维护连接池的功能。它能够自动检测并处理故障连接、超时连接和过期连接,确保连接池的稳定和可靠性。
- 兼容性:HikariCP与各种数据库和框架兼容性良好,包括MySQL、PostgreSQL、Oracle、SQLite等。它可以与大多数常见的Java应用程序和持久化框架集成。
虽然 HikariCP 是一个轻量级的高性能连接池,具有较好的性能和可扩性。但是HikariCP在可扩展性方面比较弱,无法支持多数据源。
5.2 连接池的使用
若是想要使用 HikariCP 数据库连接池,首先需要在项目中引入 HikariCP 的相关依赖。如果使用 Maven,可以在 pom.xml
文件中添加以下依赖:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>x.y.z</version>
</dependency>
然后在代码中使用以下方式获取连接:
public static void main(String[] args) throws Exception {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/test");
config.setUsername("root");
config.setPassword("123456");
config.setDriverClassName("com.mysql.jdbc.Driver");
HikariDataSource dataSource = new HikariDataSource(config);
Connection conn = dataSource.getConnection();
}
其中,HikariConfig 用于设置数据库的相关信息,包括JDBC URL、用户名、密码和驱动类。HikariDataSource是HikariCP提供的数据源,通过config参数初始化。getConnection()方法用于获取一个数据库连接。
5.3 参数配置
5.3.1 必填参数项
参数项 | 说明 | 默认值 |
---|---|---|
dataSourceClassName | 这是JDBC 驱动程序提供的类dataSourceClassName的名称。 | 无 |
jdbcUrl | 无 | |
username | 获取 Connections 时使用的默认身份验证用户名。 | 无 |
password | 获取 Connections 时使用的默认身份验证密码。 | 无 |
5.3.2 经常使用参数
参数项 | 说明 | 默认值 |
---|---|---|
autoCommit | 此属性控制从池返回的连接的默认自动提交行为。它是一个布尔值。 | true |
connectionTimeout | 等待来自池的连接的最大毫秒数。如果超过此时间而没有可用连接,则会抛出 SQLException。 可接受的最低连接超时为 250 毫秒。 | 30000(30 秒) |
idleTimeout | 此属性控制允许连接在池中空闲的最长时间。 0 表示永远不会从池中删除空闲连接。允许的最小值为 10000 毫秒(10 秒) | 600000(10 分钟) |
keepaliveTime | 此属性控制 HikariCP 尝试保持连接活动的频率,以防止数据库或网络基础设施超时。 该值必须小于该 maxLifetime 值。允许的最小值为 30000 毫秒(30 秒)。 | 0(禁用) |
maxLifetime | 池中连接的最长生命周期。正在使用的连接永远不会退休,只有当它关闭时才会被删除。 | 1800000(30 分钟) |
connectionTestQuery | 这是在从池中提供连接之前执行的查询,以验证与数据库的连接是否仍然有效。 | 无 |
minimumIdle | 最小空闲连接数。 | 与 MaximumPoolSize 相同 |
maximumPoolSize | 允许达到的最大大小,包括空闲连接和正在使用的连接。 | 10 |
poolName | 连接池的用户定义名称,主要出现在日志记录和 JMX 管理控制台中,用于标识池和池配置。 | 自动生成 |
六、知识拓展
6.1 功能对比
功能 | dbcp | druid | c3p0 | HikariCP |
---|---|---|---|---|
是否支持PSCache | 是 | 是 | 是 | 否 |
监控 | jmx | jmx/log/http | jmx,log | jmx |
扩展性 | 弱 | 好 | 弱 | 弱 |
sql拦截及解析 | 无 | 支持 | 无 | 无 |
代码 | 简单 | 中等 | 复杂 | 简单 |
更新时间 | 2015.8.6 | 2015.10.10 | 2015.12.09 | 2015.12.3 |
特点 | 依赖于common-pool | 阿里开源, 功能全面 | 历史久远,代码逻辑复杂,且不易维护 | 优化力度大,功能简单 |
连接池管理 | LinkedBlockingDeque | 数组 | threadlocal+CopyOnWriteArrayList |
6.2 竞品数据对比
功能类别 | 功能 | Druid | HikariCP | DBCP | C3P0 |
---|---|---|---|---|---|
性能 | PSCache | 是 | 否 | 是 | 是 |
LRU | 是 | 否 | 是 | 是 | |
SLB负载均衡支持 | 是 | 否 | 否 | 否 | |
稳定性 | ExceptionSorter | 是 | 否 | 否 | 否 |
扩展 | 扩展 | Filter | |||
监控 | 监控方式 | jmx/log/http | jmx/metrics | jmx | jmx |
支持SQL级监控 | 是 | 否 | 否 | 否 | |
Spring/Web关联监控 | 是 | 否 | 否 | 否 | |
诊断支持 | LogFilter | 否 | 否 | 否 | |
连接泄露诊断 | logAbandoned | 否 | 否 | 否 | |
安全 | SQL防注入 | 是 | 无 | 无 | 无 |
支持配置加密 | 是 | 否 | 否 | 否 |
结语
选择合适的JDBC连接池对于提升Java应用的性能至关重要。HikariCP以其高性能成为首选;Apache DBCP适合追求稳定性的项目;C3P0则为需要高度定制化的场景提供解决方案。无论选择哪一种,都需注意合理配置、避免连接泄露、定期维护,才能充分发挥连接池的优势。通过上述分析与代码示例,希望能帮助开发者更好地理解和使用这些强大的工具。