【JavaSE高级】JDBC连接池

连接池

连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。

为什么要使用连接池

普通的JDBC请求MySQL连接,当完成所有SQL请求任务之后,MySQL连接就会关闭。这样一来MySQL的连接就变成了单次使用,每次使用前都需要重新创建,使用之后都需要将连接关闭。如果此时有多个用户使用JDBC的话,就会出现连接频繁的创建和关闭的过程。而连接池的出现就是为了让连接能够重复使用。

在这里插入图片描述

连接池的工作原理

数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。当用户第一次获取连接时,会先请求一定数量(初始连接数量)的连接存放在连接池中,并且会记录每个连接的初始(未使用)时间,然后再将连接池中的连接给有需要的用户。当缓冲池中初始连接用完了,链接池会判断所创建的连接数量是否大于最大连接数,如果不大于则可以继续创建连接给请求的用户使用(创建的新连接的个数可自己控制,链接池中有相应的增长参数);如果已经到到最大连接数则当前用户需要等待,直到有用户使用完之后关闭连接,这个用户才可以重复使用。当我们开始使用连接池的时候连接池内部就会进行计时(超时时间),每隔空闲连接的存活时间就会对连接池内部的连接进行一次清理。把所有(当前时间 - 链接最后使用的时间 )> 空闲连接的存活时间的连接释放掉。

在这里插入图片描述

连接池的使用流程

在此处我使用的是maven所快速搭建的项目。且采用的是c3p0连接池

1、导入依赖

当 A jar 包用到了 B jar 包中的某些类时,A 就对 B 产生了依赖。在项目中以依赖的方式引入一个我们需要的 jar 包,只需要使用 dependency 标签指定被依赖 jar 包的坐标就可以了。如果我们将maven的镜像配置文件更改为了阿里云,那么我们就可以直接去阿里仓库寻找我们所需要的依赖。

在这里插入图片描述

2、参数配置
//参数配置
private final String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
private final String useName;
private final String passWord;
private final String jdbcDriver = "com.mysql.jdbc.Driver"; //jdbc驱动
private final int initSize = 5;  //初始连接数量
private final int maxSize = 10; //最大连接数量
private final int minSize = 2;  //最小连接数量
private final int acq = 2;      //增长因子
private final int idle = 60;   //单位秒  空闲时间
//参数配置及驱动加载
public PoolService(){
    dataSource.setJdbcUrl(url);
    dataSource.setUser(useName);
    dataSource.setPassword(passWord);
    try {
        dataSource.setDriverClass(jdbcDriver); //jdbc驱动
    } catch (PropertyVetoException e) {
        e.printStackTrace();
    }
    dataSource.setInitialPoolSize(initSize); //初始连接数量
    dataSource.setMaxPoolSize(maxSize); //最大连接数量
    dataSource.setMinPoolSize(minSize); //最小连接数量
    dataSource.setAcquireIncrement(acq); //增长因子
    dataSource.setMaxIdleTime(idle); //单位秒  空闲时间
}

常用配置参数介绍

最基础的参数配置:

  • driverClass : 数据库驱动。(比如mysql,或者oracle数据库的驱动)
  • jdbcUrl: 数据库连接地址。(例如jdbc:mysql://127.0.0.1:3306/test)
  • useName:数据库用户名。
  • passWord:和数据库用户名对应的数据库密码。

基础的参数配置:

参数默认值解释
initialPoolSize3连接池初始化时创建的连接数(介于maxPoolSize和minPoolSize之间)
maxPoolSize15连接池中拥有的最大连接数,如果获得新连接时会使连接总数超过这个值则不会再获取新连接,而是等待其他连接释放,所以这个值有可能会设计地很大
minPoolSize3连接池保持地最小连接数,后面地maxIdleTimeExcessConnections跟这个配合使用来减轻连接池地负载
acquireIncrement3连接池在无空闲连接可用时一次性创建的新数据库连接数

管理连接池大小和连接时间的配置:

参数默认值解释
maxIdleTime0连接的最大空闲时间,如果超过这个时间,某个数据库连接还没有被使用,则会断开这个连接,如果值为0,则永远不会断开连接
maxConnectorAge0连接的最大绝对年龄,单位是秒,0表示绝对年龄无限大
maxIdleTimeExcessConnection0单位秒,为了减轻连接池的负载,当连接池经过数据访问高峰创建了很多连接,但是后面连接池不需要维护这么多的连接,必须小于maxIdleTime。配置不为0,则将连接池的数量保持到minPoolSize

用于连接测试的配置:

参数默认值解释
automaticTestTablenull如果不为null,c3p0将生成指定名称的空表,并使用该表来测试连接
connectionTesterClassNamecom.mchange.v2.c3p0.impl.DefaultConnectionTester通过实现ConnectionTester或QueryConnectionTester的类来测试连接,类名需要指定全路径
idleConnectionTestPeriod0每隔几秒检查所有连接池中的空闲连接
preferredTestQuerynull定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个可以显著提高测试速度。注意:测试的表必须在初始数据源的时候就存在
testConnectionOnCheckinfalse如果为true,那么将在取得连接的同时校验连接的有效性
testConnectionOnCheckoutfalse如果为true,那么将在连接释放的同时校验连接的有效性
  • 在这几个参数中,idleConnectionTestPeriod、testConnectionOnCheckout和testConnectuonOnCheckin控制什么时候连接将被校验检测。
  • automaticTestTable、connectionTesterClassName和perferedTestQuery控制连接将怎么样被检测。

关于SQL语句操作对象的配置:

参数默认值解释
maxStatements0JDBC的标准参数,用以控制数据源中加载的PreparedStatement的数量
maxStatementsPerConnection0maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存的PreparedStatement数
statementCacheNumDeferredCloseThreads0如果大于0,则语句池会延迟物理close()缓存语句直到其父连接未被任何客户端使用,或者在其内部(例如在测试中)由池本身使用

关于数据库中断恢复的配置:

参数默认值解释
acquireRetryAttempts30连接池在获得新连接失败时重试的次数,如果小于等于0则无限重试直至连接获得成功
acquireRetryDelay1000连接池在获得新连接时的间隔时间,单位毫秒
breakAfterAcquireFailurefalse获取连接失败将会引起所有等待连接池获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设置为true,那么在尝试获取连接失败后该数据源将声明已断开并永久关闭

关于未解决的事务处理的配置:

参数默认值解释
autoCommitOnClosefalse连接池在回收数据库连接时是否自动提交事务。如果为false,则会回滚未提交的事务,如果为true,则会自动提交事务
forceIgnoreUnresolvedTransactionsfalse这个配置强烈不建议为true。一般来说事务当然由自己关闭了,为什么要让连接池来处理这种不细心问题呢?

其他数据源配置:

参数默认值解释
checkoutTimeout0当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如果设置为0,则将无限期等待,单位为毫秒
factoryClassLocation0指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可
numHelperThreads3异步操作,提升性能通过多线程实现多个操作同时被执行
3、获取连接
//创建c3p0连接池的数据对象
private final ComboPooledDataSource dataSource = new ComboPooledDataSource();
//给用户提供获取连接的接口
public Connection getConnection(){
    Connection connection = null;
    try {
        connection = dataSource.getConnection(); //核心代码
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return connection;
}
4、创建发送SQL请求的对象,进行相关操作
public static void main(String[] args) {
    PoolService service = new PoolService();
    //从连接池获取连接
    Connection connection = service.getConnection();
    String sql = "select * from jdbc_test";
    PreparedStatement pre = null;
    try {
        pre = connection.prepareStatement(sql);
        ResultSet resultSet = pre.executeQuery();
        while (resultSet.next()){
            System.out.println("id: "+resultSet.getString(1)
                    + "   name: "+resultSet.getString(2));
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }finally {
        try {
            pre.close();
            connection.close(); //并不是真实的关闭连接,只是将连接返回到连接池当中
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

详细操作请见JDBC编程

5、关闭连接
connection.close(); //并不是真实的关闭连接,只是将连接返回到连接池当中

这里的关闭连接只是关闭了单一用户使用JDBC的连接,此时连接将会返回到连接池中等待下一个用户的使用。如果等待时间超过所设置的空闲时间,则此连接才会被真正的关闭。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值