Java连接池详解 - 极悦
首页 课程 师资 教程 报名

Java连接池详解

  • 2022-11-17 11:15:54
  • 2001次 极悦

连接池是指连接对象池。连接池基于对象池设计模式。当创建新对象的成本(时间和资源,如 CPU、网络和 IO)较高时,使用对象池设计模式。根据对象池设计模式,应用程序预先创建一个对象并将它们放置在池或容器中。每当我们的应用程序需要此类对象时,它都会从池中获取它们,而不是创建一个新对象。

使用连接池策略的应用程序已经具有可以重用的数据库连接对象。所以,当需要与数据库进行交互时,应用程序从Pool中获取连接实例。连接池提高了与数据库交互的应用程序性能。

Java 应用程序中的连接池

让我们看看下面的库:

Apache Commons DBCP 2

光CP

C3P0

让我们一个一个地看下面的例子。出于演示目的,我们将使用 MySQL 数据库和 Eclipse IDE。我们还将使用 JDK 1.8 创建基于 Maven 的简单 Java 项目。

数据库脚本

create database empdb;
use empdb;
create table tblemployee(
                    empId integer AUTO_INCREMENT primary key,
                    empName varchar(64),
                    dob date,
                    designation varchar(64)
);
insert into  tblemployee(empId,empName,dob,designation) values (default,'Adam','1998-08-15','Manager');
insert into  tblemployee(empId,empName,dob,designation) values (default,'Smith','2001-01-11','Clerk');
insert into  tblemployee(empId,empName,dob,designation) values (default,'James','1996-03-13','Officer');

示例项目

按照以下步骤创建新项目。

打开 Eclipse 集成开发环境。

单击文件菜单并选择新建 -> Maven 项目

将显示以下屏幕。选择创建一个简单的项目选项并单击下一步按钮。

输入任何组 ID、工件 ID、名称和描述。

单击完成按钮。

在 MySQL 的 pom.xml 中添加以下依赖项。

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.49</version>
</dependency>

右键单击项目,选择 Maven -> 更新项目 -> 确定。它将下载所有依赖项。

Apache DBCP 2

DBCP 来自 Apache Common Project。DBCP 2.7 需要 Java 8。要使用 DBCP 2,您需要在项目中添加以下依赖项。

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-dbcp2</artifactId>
	<version>2.7.0</version>
</dependency>

Apache DBCP 2.0 提供了两种类型的数据源(BasicDataSource 和 PoolingDataSource)。

BasicDataSource:顾名思义,它很简单,适用于大多数常见的用例。它在内部为我们创建了 PoolingDataSource。

让我们看看以下初始化连接池的步骤。

创建 BasicDataSource 的实例

指定 JDBC Url、数据库用户名和密码

指定最小空闲连接数(Minimum number of connections that need to remain in the pool anytime)

指定最大空闲连接数(Maximum number of Idle connection in the pool)

指定最大连接总数。

package com.journaldev.example;
/**
 * Java JDBC Connection pool using Apache commons DBCP2 example program
 * 
 * @author pankaj
 */
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.commons.dbcp2.BasicDataSource;
public class DBCP2Demo {
	private static BasicDataSource dataSource = null;
	static {
		dataSource = new BasicDataSource();
		dataSource.setUrl("jdbc:mysql://localhost:3306/empdb?useSSL=false");
		dataSource.setUsername("root");
		dataSource.setPassword("root");
		dataSource.setMinIdle(5);
		dataSource.setMaxIdle(10);
		dataSource.setMaxTotal(25);
	}
public static void main(String[] args) throws SQLException {
		Connection connection = null;
		Statement statement = null;
		ResultSet resultSet = null;
		try {
			connection = dataSource.getConnection();
			statement = connection.createStatement();
			resultSet = statement.executeQuery("select * from tblemployee");
			while (resultSet.next()) {
				System.out.println("empId:" + resultSet.getInt("empId"));
				System.out.println("empName:" + resultSet.getString("empName"));
				System.out.println("dob:" + resultSet.getDate("dob"));
				System.out.println("designation:" + resultSet.getString("designation"));
			}
		} finally {
			resultSet.close();
			statement.close();
			connection.close();
		}
	}
}

输出:

empId:1
empName:Adam
dob:1998-08-15
designation:Manager
empId:2
empName:Smith
dob:2001-01-11
designation:Clerk
empId:3
empName:James
dob:1996-03-13
designation:Officer

PoolingDataSource:它提供了更多的灵活性。您只需要更改创建数据源的代码。其余代码将保持不变。

让我们看一下初始化连接池的以下步骤:

使用 JDBC URL 创建 ConnectionFactory 的实例。

使用在步骤 1 中创建的 ConnectionFactory 实例创建 PoolableConnectionFactory 实例

创建 GenericObjectPoolConfig 的实例并设置最大空闲、最小空闲和最大连接属性

现在使用在步骤 2 和步骤 3 中创建的实例初始化 ObjectPool

现在将池设置为 PoolableConnectionFactory 的实例

最后,初始化DataSource的一个实例

private static DataSource dataSource = null;
	static {
		Properties properties = new Properties();
		properties.setProperty("user", "root");
		properties.setProperty("password", "root");
		ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://localhost:3306/empdb",
				properties);
		PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null);
		GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
		config.setMaxTotal(25);
		config.setMaxIdle(10);
		config.setMinIdle(5);
		ObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnectionFactory, config);
		poolableConnectionFactory.setPool(connectionPool);
		dataSource = new PoolingDataSource<>(connectionPool);
	}

HikariCP

HikariCP 快速、可靠且简单。它是连接池的首选解决方案之一。像 Spring Boot 2.x 这样的框架使用它作为默认的连接管理器。

要使用 HikariCP,请在我们项目的 pom.xml 中添加以下依赖项。

<dependency>
	<groupId>com.zaxxer</groupId>
	<artifactId>HikariCP</artifactId>
	<version>3.4.5</version>
</dependency>

HikariCP 配置:

我们可以使用基于 Java 的配置,如下面的示例程序所示,或者我们可以使用属性文件来配置 HikariCP。让我们看看下面的属性。

idleTimeout:连接对象可以在池中保持空闲状态的时间(以毫秒为单位)。它适用于minimumIdle和maximumPoolSize属性。在指定的时间后连接对象将被释放。

connectionTimeout:客户端等待来自池的连接对象的时间(以毫秒为单位)。如果达到时间限制,则将抛出 SQL 异常。

autoCommit : 我们可以指定 true 或 false ,如果设置为 true 那么它会自动提交你执行的每条 SQL 语句,如果设置为 false 那么我们需要手动提交 SQL 语句

cachePrepStmts:为 Prepare Statement 启用缓存

minimumIdle:任何时候连接池中需要保留的最少连接对象数。

maximumPoolSize:可以保留在池中的最大连接数。

package com.journaldev.example;
/**
 * Java JDBC Connection pool using HikariCP example program
 * 
 * @author pankaj
 */
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
public class HikariCPDemo {
	private static HikariDataSource dataSource = null;
	static {
		HikariConfig config = new HikariConfig();
		config.setJdbcUrl("jdbc:mysql://localhost:3306/empdb");
		config.setUsername("root");
		config.setPassword("root");
		config.addDataSourceProperty("minimumIdle", "5");
		config.addDataSourceProperty("maximumPoolSize", "25");
		dataSource = new HikariDataSource(config);
	}
	public static void main(String[] args) throws SQLException {
		Connection connection = null;
		Statement statement = null;
		ResultSet resultSet = null;
		try {
			connection = dataSource.getConnection();
			statement = connection.createStatement();
			resultSet = statement.executeQuery("select * from tblemployee");
			while (resultSet.next()) {
				System.out.println("empId:" + resultSet.getInt("empId"));
				System.out.println("empName:" + resultSet.getString("empName"));
				System.out.println("dob:" + resultSet.getDate("dob"));
				System.out.println("designation:" + resultSet.getString("designation"));
			}
		} finally {
			resultSet.close();
			statement.close();
			connection.close();
		}
	}
}

输出:

empId:1
empName:Adam
dob:1998-08-15
designation:Manager
empId:2
empName:Smith
dob:2001-01-11
designation:Clerk
empId:3
empName:James
dob:1996-03-13
designation:Officer

C3P0

通常,它与 Hibernate 一起使用。要使用 C3P0,我们需要在项目中添加以下依赖。

<dependency>
	<groupId>com.mchange</groupId>
	<artifactId>c3p0</artifactId>
	<version>0.9.5.5</version>
</dependency>

我们可以使用 C3P0 配置以下属性。

driverClass:首选 Jdbc 驱动程序

jdbcUrl:数据库的 JDBC Url。

initialPoolSize:启动时在池中创建的连接数。

acquireIncrement:当前大小不够时需要创建的新连接数。

maxIdleTime:连接可以保留在池中而不被使用的秒数。

maxPoolSize:可以保留在 Pool 中的最大连接数。

minPoolSize:任何时候Pool中需要保留的最小连接对象数。

package com.journaldev.example;
/**
 * Java JDBC Connection pool using C3PO example program
 * 
 * @author pankaj
 */
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Demo {
	static ComboPooledDataSource comboPooledDataSource = null;
	static {
		comboPooledDataSource = new ComboPooledDataSource();
		comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/empdb?useSSL=false");
		comboPooledDataSource.setUser("root");
		comboPooledDataSource.setPassword("root");
		comboPooledDataSource.setMinPoolSize(3);
		comboPooledDataSource.setAcquireIncrement(3);
		comboPooledDataSource.setMaxPoolSize(30);
	}
public static void main(String[] args) throws SQLException {
		Connection connection = null;
		Statement statement = null;
		ResultSet resultSet = null;
		try {
			connection = comboPooledDataSource.getConnection();
			statement = connection.createStatement();
			resultSet = statement.executeQuery("select * from tblemployee");
			while (resultSet.next()) {
				System.out.println("empId:" + resultSet.getInt("empId"));
				System.out.println("empName:" + resultSet.getString("empName"));
				System.out.println("dob:" + resultSet.getDate("dob"));
				System.out.println("designation:" + resultSet.getString("designation"));
			}
		} finally {
			resultSet.close();
			statement.close();
			connection.close();
		}
	}
}

输出:

Aug 29, 2020 8:59:05 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1hge9kqacgbp7hjpftse6|77a567e1, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> null, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1hge9kqacgbp7hjpftse6|77a567e1, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/empdb?useSSL=false, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 30, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
empId:1
empName:Adam
dob:1998-08-15
designation:Manager
empId:2
empName:Smith
dob:2001-01-11
designation:Clerk
empId:3
empName:James
dob:1996-03-13
designation:Officer

 

选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交