Java中的连接池管理

连接池意味着一组连接对象。连接池基于对象池设计模式。当创建新对象的成本(时间和资源,如CPU、网络和IO)较高时,使用对象池设计模式。根据对象池设计模式,应用程序预先创建对象并将它们放入池或容器中。当应用程序需要这些对象时,它从池中获取而不是创建一个新对象。

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

Connection Pooling

我们可以自己实现连接池。任何连接池框架都需要完成三项任务。

  • Creating Connection Objects
  • Manage usage of created Objects and validate them
  • Release/Destroy Objects

使用Java,我们有一系列非常好用的库可供使用。我们只需要配置一些属性就可以使用它们了。

在 Java 应用程序中的连接池

让我们来看看下面的图书馆吧。 de ba.)

  • Apache Commons DBCP 2
  • HikariCP
  • C3P0

让我们逐个看一下以下的例子。为了演示的目的,我们将使用MySQL数据库和Eclipse集成开发环境。我们还将基于Maven创建一个简单的Java项目,使用JDK 1.8。

数据库脚本

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');

示例项目

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

    1. 打开Eclipse IDE。

点击文件菜单,选择新建 -> Maven项目。

下方屏幕将会显示。选择创建一个简单项目选项,然后点击下一步按钮。

New Maven Project
    请输入任何群组ID、依赖ID、名称以及描述。
Maven Project Configs

点击“完成”按钮。

    在您的pom.xml中添加以下依赖项以支持MySQL。
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.49</version>
</dependency>
    在项目上点击右键,选择Maven -> 更新项目 -> 确定。它将下载所有依赖项。

1) Apache commons DBCP 2 约男巴胆亥枇

DBCP来自于Apache Common项目。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)。

Apache DBCP 2.0提供了两种数据源类型,分别是BasicDataSource和PoolingDataSource。

BasicDataSource: 正如其名称所示,它简单且适用于大多数常见的用例。它在内部为我们创建了PoolingDataSource。

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

    1. 创建一个BasicDataSource的实例。

 

    1. 指定JDBC URL、数据库用户名和密码。

 

    1. 指定最小空闲连接数(池中必须保持的最小连接数)。

 

    1. 指定最大空闲连接数(池中允许的最大空闲连接数)。

 

    指定最大连接总数。
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:它提供更多的灵活性。您只需更改创建数据源的代码即可,其余的代码将保持不变。

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

    1. 使用JDBC URL创建一个ConnectionFactory实例。

 

    1. 使用在第1步中创建的ConnectionFactory实例创建一个PoolableConnectionFactory实例。

 

    1. 创建一个GenericObjectPoolConfig实例并设置最大闲置、最小闲置和最大连接属性。

 

    1. 现在使用第2步和第3步中创建的实例初始化ObjectPool。

 

    1. 现在将pool设置为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);

	}

2)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: Time in milliseconds for which connection object can stay in the pool as idle. It works with minimumIdle and maximumPoolSize properties. After a specified time connection object will be released.
  • connectionTimeout: Time in milliseconds for which the client will wait for connection object from Pool. If the time limit is reached then SQL Exception will be thrown.
  • autoCommit: We can specify true or false and if it is set to true then it will automatically commit every SQL statements you execute and if it is set to false then we need to commit SQL statements manually
  • cachePrepStmts: Enable caching for Prepare Statement
  • minimumIdle: Minimum number of connection objects needs to remain in the pool at any time.
  • maximumPoolSize: Maximum number of connections that can stay in the pool.
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

3) 人造人C3P0

C3P0是最古老的库之一。一般来说,它与Hibernate一起使用。使用C3P0,我们需要将以下依赖项添加到项目中。

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

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

  • driverClass: Preferred Jdbc Driver
  • jdbcUrl: JDBC Url for the database.
  • initialPoolSize: Number of connections created in the pool at startup.
  • acquireIncrement: Number of new connections needs to be created when the current size is not enough.
  • maxIdleTime: Number of seconds Connection can remain in Pool without being used.
  • maxPoolSize: Maximum number of connections that can stay in Pool.
  • minPoolSize: Minimum number of connection objects needs to remain in Pool at any time.
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

JDBC连接池示例教程就介绍到这里,希望没有漏掉重要的内容。

参考资料:HikariCP、Apache Commons DBCP、C3P0

bannerAds