• Java 数据库连接池介绍(2)--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>0,maxStatementsPerConnection 起作用,不限制总的缓存数量;如果 maxStatements>0 and maxStatementsPerConnection=0,maxStatements 起作用,不限单个连接的缓存数量。

    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 来访问原始连接中的非标准接口:
    1、把连接转成 C3P0ProxyConnection
    2、然后调用 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;
  • 相关阅读:
    病毒木马查杀实战第017篇:U盘病毒之专杀工具的编写
    病毒木马查杀实战第016篇:U盘病毒之逆向分析
    病毒木马查杀实战第015篇:U盘病毒之脱壳研究
    病毒木马查杀实战第014篇:U盘病毒之手动查杀
    病毒木马查杀实战第024篇:MBR病毒之编程解析引导区
    病毒木马查杀实战第023篇:MBR病毒之引导区的解析
    缓冲区溢出分析第11课:整数溢出的原理
    缓冲区溢出分析第10课:Winamp缓冲区溢出研究
    Backdoor.Zegost木马病毒分析(一)
    缓冲区溢出分析第09课:MS06-040漏洞研究——深入挖掘
  • 原文地址:https://www.cnblogs.com/wuyongyin/p/15459526.html
Copyright © 2020-2023  润新知