Java 數據庫連接池c3p0 介紹

前言:

c3p0 是一個開源的數據庫連接池,實現瞭 JDBC 3 規范;本文主要介紹 c3p0 的基本使用,文中使用到的軟件版本:Java 1.8.0_191、c3p0 0.9.5.5、Spring Boot 2.3.12.RELEASE。

1、配置參數

1.1、基礎配置

配置

參數 默認值 描述
driverClass null 驅動類名稱
jdbcUrl null jdbc 連接 url
user null 用戶名
password null 密碼

1.2、連接池大小

參數 默認值 描述
acquireIncrement 3 連接池中的連接耗盡時,一次創建的連接個數
initialPoolSize 3 初始連接池大小,介於 minPoolSize 和 maxPoolSize 之間
maxPoolSize 15 最大連接數
minPoolSize 3 最小連接數

1.3、連接池大小和連接存活時間

參數 默認值 描述
maxConnectionAge 0 連接存活的最長時間(秒),0 表示沒有限制。正在使用的連接不會不受此限制。
 maxIdleTime 0  空閑連接數最大存活時間,0 表示永不過期
 maxIdleTimeExcessConnections 0  當連接數大於 minPoolSize 時,空閑連接數最大存活時間,0 表示永不過期

1.4、連接測試

參數 默認值 描述
automaticTestTable null 測試的表名;如果設置瞭,c3p0 將使用該表名創建一個空表,並使用其來測試連接,preferredTestQuery 參數將被忽略。
connectionTesterClassName com.mchange.v2.c3p0.impl.DefaultConnectionTester 連接測試的類名,需實現  com.mchange.v2.c3p0.ConnectionTester 或 com.mchange.v2.c3p0.QueryConnectionTester 接口。
idleConnectionTestPeriod 0 空閑連接測試的間隔(秒)。
preferredTestQuery null 連接測試的語句;如果不設置,將使用 DatabaseMetaData 的 getTables 方法來測試,這可能時比較慢的。
testConnectionOnCheckin false 連接返回連接池時,是否測試
testConnectionOnCheckout false 從連接池獲取連接時,是否測試

1.5、預編譯池

參數 默認值 描述
maxStatements 0 緩存總體預編譯語句的最大數量
maxStatementsPerConnection 0 緩存每個連接中預編譯語句的最大數量
statementCacheNumDeferredCloseThreads 0 清理 statement 緩存的線程數,如果需要設置,應設置為 1。一些數據庫,特別是 oracle 會在連接使用時關閉 statement,數據庫無法很好的處理這種情況,進而導致死鎖。清理的線程會在連接

maxStatements 和 maxStatementsPerConnection 如果都為 0,將不緩存預編譯語句。如果 maxStatements=0 and maxStatementsPerConnection>0maxStatementsPerConnection 起作用,不限制總的緩存數量;如果 maxStatements>0 and maxStatementsPerConnection=0maxStatements 起作用,不限單個連接的緩存數量。

1.6、數據庫中斷的恢復

參數 默認值 描述
acquireRetryAttempts 30 獲取連接失敗時的重試次數
acquireRetryDelay 1000 連接獲取重試的時間間隔(毫秒)
 breakAfterAcquireFailure  false 嘗試獲取連接失敗時,是否聲明連接池斷開並永久關閉

1.7、自定義連接生命周期管理

參數 默認值 描述
connectionCustomizerClassName null 連接生命周期管理的自定義類,需實現 com.mchange.v2.c3p0.ConnectionCustomizer 接口

1.8、處理未提交的事務

參數 默認值 描述
autoCommitOnClose false 連接在返回連接池時是否自動提交事務。true,提交事務;false,回滾事務
forceIgnoreUnresolvedTransactions false 連接在返回連接池時,是否強制不處理事務;強烈不推薦設置為 true。

1.9、調試

參數 默認值 描述
debugUnreturnedConnectionStackTraces false 是否記錄活動連接的堆棧信息;如果設為 true,且 unreturnedConnectionTimeout>0,當連接借出時間 > unreturnedConnectionTimeout 時,就會打印連接的堆棧信息,並刪除該連接。
unreturnedConnectionTimeout 0 連接未返回連接池的超時時間(秒)

這兩個參數可用於幫助發現連接泄露。

1.10、避免熱部署內存泄露

參數 默認值 描述
contextClassLoaderSource caller 用於生成 c3p0 線程的類加載器來源,為 caller, library 或 none。caller 表示來源於連接池的調用者;library 表示來源於 c3p0 本身;none 表示使用系統類加載器
privilegeSpawnedThreads false  生成 c3p0 線程時是否使用 c3p0 庫中的 AccessControlContext;默認(false)使用連接池調用者的 AccessControlContext。

在應用熱部署、取消部署時,連接池可能會阻止垃圾回收進而導致內存泄露; 這兩個參數主要用於處理這種情況。

1.11、其它配置

參數 默認值 描述
checkoutTimeout 0 從連接獲取連接的超時時間,0 表示永不超時
factoryClassLocation null c3p0 libraries的路徑,如果在本地(通常都是這樣),那麼無需設置
forceSynchronousCheckins false 連接返回連接池是否同步方式
 maxAdministrativeTaskTime  0  管理任務運行的最大時間(秒),超過改時間會終端任務;0 表示管理任務永遠不被打斷。
 numHelperThreads  3  管理線程個數
usesTraditionalReflectiveProxies false 已過期。是否使用發射動態代理的方式來實現 Connection 及 其他 JDBC 接口。

詳細說明可參考官網文檔:https://www.mchange.com/projects/c3p0/#configuration

2、原始連接操作

c3p0 提供 api 來訪問原始連接中的非標準接口:

  • 把連接轉成 C3P0ProxyConnection
  • 然後調用 rawConnectionOperation 方法

下面是獲取 PostgreSQL  JDBC 驅動中 CopyManager 對象的方法:

Connection connection = (C3P0ProxyConnection) c3p0DataSource.getConnection();

C3P0ProxyConnection castConnection = (C3P0ProxyConnection) connection;

Method method = BaseConnection.class.getMethod(“getCopyAPI”, new Class[]{});

CopyManager copyManager = (CopyManager) castConnection.rawConnectionOperation(method, C3P0ProxyConnection.RAW_CONNECTION, new Object[]{});

3、使用

3.1、直接使用

3.1.1、引入依賴

<dependency>

    <groupId>com.mchange</groupId>

    <artifactId>c3p0</artifactId>

    <version>0.9.5.5</version>

</dependency>

3.1.2、使用例子

package com.abc.demo.general.dbpool;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.beans.PropertyVetoException;

import java.sql.Connection;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

public class C3p0Case {

    public static void main(String[] args) throws PropertyVetoException {

        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();

        comboPooledDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");

        comboPooledDataSource.setJdbcUrl("jdbc:mysql://10.40.9.11:3306/mydb?useUnicode=true&characterEncoding=UTF-8");

        comboPooledDataSource.setUser("root");

        comboPooledDataSource.setPassword("123456");

        comboPooledDataSource.setInitialPoolSize(2);

        comboPooledDataSource.setMinPoolSize(2);

        comboPooledDataSource.setMaxPoolSize(10);

        comboPooledDataSource.setPreferredTestQuery("select 1");

        comboPooledDataSource.setIdleConnectionTestPeriod(60);

        comboPooledDataSource.setTestConnectionOnCheckout(true);

        comboPooledDataSource.setCheckoutTimeout(1000 * 30);

        Connection connection = null;

        Statement st = null;

        ResultSet rs  = null;

        try {

            connection = comboPooledDataSource.getConnection();

            st = connection.createStatement();

            rs = st.executeQuery("select version()");

            if (rs.next()) {

                System.out.println(rs.getString(1));

            }

        } catch (SQLException e) {

            e.printStackTrace();

        } finally {

            close(connection);

        }

        //實際使用中一般是在應用啟動時初始化數據源,應用從數據源中獲取連接;並不會關閉數據源。

        comboPooledDataSource.close();

    }

    private static void close(Connection connection) {

        if (connection != null) {

            try {

                connection.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

        }

    }

}

3.2、在 SpringBoot 中使用

3.1.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>

    <dependency>

        <groupId>org.springframework</groupId>

        <artifactId>spring-jdbc</artifactId>

    </dependency>

    <dependency>

        <groupId>com.mchange</groupId>

        <artifactId>c3p0</artifactId>

        <version>0.9.5.5</version>

    </dependency>

    <dependency>

        <groupId>mysql</groupId>

        <artifactId>mysql-connector-java</artifactId>

    </dependency>

</dependencies>

3.1.2、單數據源

application.yml 配置:

spring:

  datasource:

    c3p0:

      driver-class: com.mysql.cj.jdbc.Driver

      jdbc-url: jdbc:mysql://10.40.9.11:3306/myDb?useUnicode=true&characterEncoding=UTF-8

      user: root

      password: 123456

      initial-pool-size: 2

      min-pool-size: 2

      max-pool-size: 10

      preferred-test-query: select 1

      idle-connection-test-period: 60

      test-connection-on-checkout: true

      checkout-timeout: 30000

數據源配置類:

package com.abc.demo.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;

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 javax.sql.DataSource;

@Configuration

public class DataSourceConfig {

    @Bean("dataSource")

    @ConfigurationProperties(prefix = "spring.datasource.c3p0")

    public DataSource dataSource1() {

        return DataSourceBuilder.create().type(ComboPooledDataSource.class).build();

    }

}

使用:

@Autowired

private DataSource dataSource;

3.1.3、多數據源

application.yml 配置:

spring:

  datasource:

    c3p0:

      db1:

        driver-class: com.mysql.cj.jdbc.Driver

        jdbc-url: jdbc:mysql://10.40.9.11:3306/myDb?useUnicode=true&characterEncoding=UTF-8

        user: root

        password: InsYR0ot187!

        initial-pool-size: 2

        min-pool-size: 2

        max-pool-size: 10

        preferred-test-query: select 1

        idle-connection-test-period: 60

        test-connection-on-checkout: true

        checkout-timeout: 30000

      db2:

        driver-class: com.mysql.cj.jdbc.Driver

        jdbc-url: jdbc:mysql://10.40.9.12:3306/myDb?useUnicode=true&characterEncoding=UTF-8

        user: root

        password: InsYR0ot187!

        initial-pool-size: 2

        min-pool-size: 2

        max-pool-size: 10

        preferred-test-query: select 1

        idle-connection-test-period: 60

        test-connection-on-checkout: true

        checkout-timeout: 30000

數據源配置類:

package com.abc.demo.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;

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 javax.sql.DataSource;

@Configuration

public class DataSourceConfig {

    @Bean("dataSource1")

    @ConfigurationProperties(prefix = "spring.datasource.c3p0.db1")

    public DataSource dataSource1() {

        return DataSourceBuilder.create().type(ComboPooledDataSource.class).build();

    }

    @Bean("dataSource2")

    @ConfigurationProperties(prefix = "spring.datasource.c3p0.db2")

    public DataSource dataSource2() {

        return DataSourceBuilder.create().type(ComboPooledDataSource.class).build();

    }

}

使用:

@Autowired

@Qualifier("dataSource1")

private DataSource dataSource1;



@Autowired

@Qualifier("dataSource2")

private DataSource dataSource2;

到此這篇關於 Java 數據庫連接池c3p0 介紹的文章就介紹到這瞭,更多相關 Java 連接池c3p0 內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: