更新時間:2022-11-17 11:15:54 來源:動力節(jié)點 瀏覽2384次
連接池是指連接對象池。連接池基于對象池設計模式。當創(chuàng)建新對象的成本(時間和資源,如 CPU、網(wǎng)絡和 IO)較高時,使用對象池設計模式。根據(jù)對象池設計模式,應用程序預先創(chuàng)建一個對象并將它們放置在池或容器中。每當我們的應用程序需要此類對象時,它都會從池中獲取它們,而不是創(chuàng)建一個新對象。
使用連接池策略的應用程序已經(jīng)具有可以重用的數(shù)據(jù)庫連接對象。所以,當需要與數(shù)據(jù)庫進行交互時,應用程序從Pool中獲取連接實例。連接池提高了與數(shù)據(jù)庫交互的應用程序性能。
讓我們看看下面的庫:
Apache Commons DBCP 2
光CP
C3P0
讓我們一個一個地看下面的例子。出于演示目的,我們將使用 MySQL 數(shù)據(jù)庫和 Eclipse IDE。我們還將使用 JDK 1.8 創(chuàng)建基于 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');
按照以下步驟創(chuàng)建新項目。
打開 Eclipse 集成開發(fā)環(huán)境。
單擊文件菜單并選擇新建 -> Maven 項目
將顯示以下屏幕。選擇創(chuàng)建一個簡單的項目選項并單擊下一步按鈕。
輸入任何組 ID、工件 ID、名稱和描述。
單擊完成按鈕。
在 MySQL 的 pom.xml 中添加以下依賴項。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
右鍵單擊項目,選擇 Maven -> 更新項目 -> 確定。它將下載所有依賴項。
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 提供了兩種類型的數(shù)據(jù)源(BasicDataSource 和 PoolingDataSource)。
BasicDataSource:顧名思義,它很簡單,適用于大多數(shù)常見的用例。它在內(nèi)部為我們創(chuàng)建了 PoolingDataSource。
讓我們看看以下初始化連接池的步驟。
創(chuàng)建 BasicDataSource 的實例
指定 JDBC Url、數(shù)據(jù)庫用戶名和密碼
指定最小空閑連接數(shù)(Minimum number of connections that need to remain in the pool anytime)
指定最大空閑連接數(shù)(Maximum number of Idle connection in the pool)
指定最大連接總數(shù)。
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:它提供了更多的靈活性。您只需要更改創(chuàng)建數(shù)據(jù)源的代碼。其余代碼將保持不變。
讓我們看一下初始化連接池的以下步驟:
使用 JDBC URL 創(chuàng)建 ConnectionFactory 的實例。
使用在步驟 1 中創(chuàng)建的 ConnectionFactory 實例創(chuàng)建 PoolableConnectionFactory 實例
創(chuàng)建 GenericObjectPoolConfig 的實例并設置最大空閑、最小空閑和最大連接屬性
現(xiàn)在使用在步驟 2 和步驟 3 中創(chuàng)建的實例初始化 ObjectPool
現(xiàn)在將池設置為 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 快速、可靠且簡單。它是連接池的首選解決方案之一。像 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:連接對象可以在池中保持空閑狀態(tài)的時間(以毫秒為單位)。它適用于minimumIdle和maximumPoolSize屬性。在指定的時間后連接對象將被釋放。
connectionTimeout:客戶端等待來自池的連接對象的時間(以毫秒為單位)。如果達到時間限制,則將拋出 SQL 異常。
autoCommit : 我們可以指定 true 或 false ,如果設置為 true 那么它會自動提交你執(zhí)行的每條 SQL 語句,如果設置為 false 那么我們需要手動提交 SQL 語句
cachePrepStmts:為 Prepare Statement 啟用緩存
minimumIdle:任何時候連接池中需要保留的最少連接對象數(shù)。
maximumPoolSize:可以保留在池中的最大連接數(shù)。
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
通常,它與 Hibernate 一起使用。要使用 C3P0,我們需要在項目中添加以下依賴。
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
我們可以使用 C3P0 配置以下屬性。
driverClass:首選 Jdbc 驅(qū)動程序
jdbcUrl:數(shù)據(jù)庫的 JDBC Url。
initialPoolSize:啟動時在池中創(chuàng)建的連接數(shù)。
acquireIncrement:當前大小不夠時需要創(chuàng)建的新連接數(shù)。
maxIdleTime:連接可以保留在池中而不被使用的秒數(shù)。
maxPoolSize:可以保留在 Pool 中的最大連接數(shù)。
minPoolSize:任何時候Pool中需要保留的最小連接對象數(shù)。
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