【深入浅出谈数据库连接池】

502 阅读4分钟

「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。

前言

大家好,我是程序猿小白 GW_gw,很高兴能和大家一起学习进步。

以下内容部分来自于网络,如有侵权,请联系我删除,本文仅用于学习交流,不用作任何商业用途。

摘要

本文主要介绍数据库连接池技术以及两种数据库连接池的使用(c3p0数据库连接池和druid数据库连接池)。

1. 基本概念

对于简单的数据库应用来说,由于对数据库的访问不是那么频繁,所以我们使用完数据库之后可以直接关闭,也不会造成较多的开销,但是对于复杂的数据库应用,频繁的建立和关闭连接就会造成较大的额外的性能开销。

数据库连接池应运而生。

数据库连接池其实就是存放数据库连接对象的容器。

数据库连接池在创建初期会存放一定数量(数据库的最小连接数量)的数据库连接,如果需要的数据库连接超过初始数量就会就会建立新的数据库连接,但是数量不会超过最大连接数量。这些新建的数据库连接在使用完毕后不会立即释放,会保留在数据库连接池中等待重用或者等待空闲超时后自动释放。

优点:

  1. 节约资源。
  2. 提高访问效率。

2. 具体实现

关于数据库连接池的实现,我们就需要了解javax.sql包下的一个接口:DataSource。

DataSource对象是获取连接的首选方法。DataSource的接口主要由驱动程序的供应商实现。

DataSource只有两个重载方法:

Connection getConnection() 
    尝试建立与此 DataSource对象所代表的数据源的连接。  
Connection getConnection(String username, String password) 
    尝试建立与该 DataSource对象所代表的数据源的连接。  

一般我们不会实现DataSource接口,而是由各厂商实现,例如下面两种数据库连接池实现技术。

2.1 C3P0连接池的配置

配置步骤:

  1. 下载驱动jar包并导入。

    https://sourceforge.net/projects/c3p0/
    

    image-20220122170433123

    image-20220122172116358

  2. 定义配置文件。

    在src路径下创建c3p0.properties文件或c3p0-config.xml文件(多使用)。

    c3p0.properties文件

    c3p0.url=jdbc:mysql://localhost:3306/db_test?serverTimezone=Asia/Shanghai&useSSL=false
    c3p0.username=root
    c3p0.password=123456
    c3p0.driver=com.mysql.cj.jdbc.Driver
    c3p0.maxPoolSize = 20
    c3p0.minPoolSize = 3
    c3p0.maxStatements = 30
    c3p0.maxIdleTime = 150
    c3p0.initialPoolSize=10
    

    c3p0-config.xml

    <c3p0-config>
        <!--使用默认的配置读取数据库连接池对象 -->
        <default-config>
            <!--  连接参数 -->
            <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
            <!-- 数据库连接url并对&符号进行转义 -->
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/db_test?serverTimezone=Asia/Shanghai&amp;useSSL=false</property>
            <!-- 连接数据库用户名 -->
            <property name="user">root</property>
            <!-- 连接数据库密码 -->
            <property name="password">123456</property>
    ​
            <!-- 连接池参数 -->
            <!--初始化申请的连接数量-->
            <property name="initialPoolSize">5</property>
            <!--最大的连接数量-->
            <property name="maxPoolSize">10</property>
            <!--超时时间,毫秒为单位-->
            <property name="checkoutTimeout">3000</property>
        </default-config>
        <named-config name="otherc3p0">
            <!--  连接参数 -->
            <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
            <!-- 数据库连接url并对&符号进行转义 -->
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/db_test1?serverTimezone=Asia/Shanghai&amp;useSSL=false</property>
            <!-- 连接数据库用户名 -->
            <property name="user">root</property>
            <!-- 连接数据库密码 -->
            <property name="password">123456</property>
    ​
            <!-- 连接池参数 -->
            <!--初始化申请的连接数量-->
            <property name="initialPoolSize">5</property>
            <!--最大的连接数量-->
            <property name="maxPoolSize">20</property>
            <!--超时时间,毫秒为单位-->
            <property name="checkoutTimeout">2000</property>
        </named-config></c3p0-config>
    
  3. 创建数据库连接池对象。

  4. c3p0的xml的同一个配置文件可以有多个配置,如果在创建时不指定名字,则使用默认的配置。如果指定名字,则使用指定名字的配置。

    一般只使用默认配置。

    //使用默认配置
    DataSource dataSource = new ComboPooledDataSource();
    //使用指定名字的配置。
    DataSource dataSource = new ComboPooledDataSource("otherc3p0");
    
  5. 获取数据库连接对象。

    Connection connection = comboPooledDataSource.getConnection();
    
  6. 配置测试

    public class C3p0Demo01 {
        public static void main(String[] args) throws SQLException {
            DataSource dataSource = new ComboPooledDataSource();
            Connection connection = dataSource.getConnection();
            System.out.println(connection);
            connection.close();
        }
    }
    

    image-20220123151041492

2.2 Druid连接池的配置

Druid数据库连接池是由阿里研发,是目前最流行且性能较高的数据库连接池技术。

配置步骤如下:

  1. 下载jar包并导入。

    https://repo1.maven.org/maven2/com/alibaba/druid
    

    下载最新的即可。

  2. 创建properties配置文件

    url=jdbc:mysql://localhost:3306/db_test?serverTimezone=Asia/Shanghai&useSSL=false
    username=root
    password=123456
    driverClassName=com.mysql.cj.jdbc.Driver
    # 初始化连接数量
    initialSize=10
    # 最大连接数量
    maxActive=20
    # 最大等待时间
    maxWait=3000
    
  3. 加载配置文件

    Properties properties = new Properties();
    properties.load(DruidDemo01.class.getClassLoader().getResourceAsStream("druid.properties"));
    
  4. 创建数据库连接池对象

    DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
    
  5. 创建数据库连接对象

    Connection connection = dataSource.getConnection();
    

2.2.1 druid工具类

package com.poison.utils;
​
​
​
import com.alibaba.druid.pool.DruidDataSourceFactory;
​
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
​
/**
 * @description:
 * @author: Poison
 * @date: 
 */
public class JdbcUtils {
    private static DataSource dataSource;
​
    static{
        try {
            //加载配置文件
            Properties properties = new Properties();
            properties.load(JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //创建数据库连接池对象
            dataSource = DruidDataSourceFactory.createDataSource(properties);
​
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
​
    /**
     * 从数据库连接池中获取数据库连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
​
    /**
     * 关闭连接,释放资源。
     * @param statement 执行sql语句对象
     * @param connection 数据库连接对象
     */
    public static void close(Statement statement,Connection connection){
        close(null,statement,connection);
    }
​
    /**
     * 关闭连接,释放资源。
     * @param resultSet sql结果集对象
     * @param statement 执行sql语句对象
     * @param connection 数据库连接对象
     */
    public static void close(ResultSet resultSet,Statement statement, Connection connection){
        if(resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement!=null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
​
    }
​
    /**
     * 获取数据库连接池对象
     * @return 返回数据库连接池对象
     */
    public static DataSource getDataSource(){
        return dataSource;
    }
}

小结

以上就是关于数据库连接池的一些基本概念和两种数据库连接池的基本使用,相对来说druid要更为受欢迎,毕竟性能更高嘛。希望以上内容能对读者有所帮助,如有不正之处,欢迎掘由们留言指正。