c3p0 数据库连接池技术的使用

在实际项目开发中,我们在操作数据库时,大部分情况下都会使用到连接池技术。有关连接池技术的工作原理,相信大家都非常清楚,这里就不啰嗦了。使用连接池技术操作数据库,主要目的还是在于高并发访问数据库时,能够有效的提升数据库的整体性能。目前比较流行的数据库连接池技术主要有两个:c3p0 和 druid。这里我们先以操作 mysql 数据库为例,快速简单总结一下 c3p0 数据库连接池技术的使用。

c3p0 的官网地址:https://www.mchange.com/projects/c3p0


一、配置 c3p0 连接池

我们首先创建一个 JavaSE 的 Maven 项目,在 pom.xml 文件中导入 c3p0 和 mysql 的 jar 包。

有关各种 jar 包依赖的 xml 配置内容,可以从 https://mvnrepository.com 上进行查找,复制粘贴到 pom.xml 即可。
c3p0 的 jar 包网址是:https://mvnrepository.com/artifact/com.mchange/c3p0
mysql 连接 java 的驱动 jar 包网址是:https://mvnrepository.com/artifact/mysql/mysql-connector-java

我在 pom.xml 配置的都是当前最新版本的 jar 包,如下所示:

<!-- 导入 c3p0 的 jar 包 -->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.5</version>
</dependency>

<!-- 导入 mysql 的 jar 包 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

配置好引用的 jar 包后,打开右侧的 Maven 窗口,刷新一下,这样 Maven 会自动下载所需的 jar 包文件。

然后在项目的 resources 资源目录下创建 c3p0 的配置文件(注意:c3p0 的配置文件的名称必须是 c3p0-config.xml 或 c3p0-config.properties),这里我们使用 c3p0-config.xml 作为配置文件,内容如下所示:

<c3p0-config>
    <!-- 配置默认使用的连接池相关参数 -->
    <default-config>
        <!--  mysql 连接参数 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/testdb</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <!--初始化的连接数量-->
        <property name="initialPoolSize">5</property>
        <!--最大连接数量-->
        <property name="maxPoolSize">20</property>
        <!--获取连接的等待超时时间(毫秒)-->
        <property name="checkoutTimeout">3000</property>
    </default-config>

    <!-- 根据实际业务需要,可以有多份具有名称的参数配置 -->
    <!-- 这里增加了一份名称为 other 的配置,连接的是本机另外一个数据库 -->
    <named-config name="fastdb">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/fastdb</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <property name="initialPoolSize">10</property>
        <property name="maxPoolSize">50</property>
        <property name="checkoutTimeout">5000</property>
    </named-config>
</c3p0-config>

c3p0 的配置文件中,有一个默认参数配置,即 default-config 包裹的配置内容。另外也可以有多个命名的参数配置,即 named-config 包裹的内容,这里增加了一个名称为 fastdb 的命名配置。当创建 c3p0 数据源对象 ComboPooledDataSource 时,如果没有指定参数,使用的就是默认配置。如果指定了参数,则必须使用 named-config 中配置的名称。


二、使用 c3p0 连接池

使用 c3p0 连接池,主要是创建出 ComboPooledDataSource 数据源对象,然后调用其 getConnection 方法获取数据库连接对象,拿到连接对象之后,其它的操作跟 JDBC 访问数据库的操作一模一样,唯一的区别就是当调用连接的 close 方法时,底层不再是关闭销毁连接对象,而是将连接对象放入到连接池中,以便后续新的请求到来时,直接拿去使用。具体代码如下:

import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class c3p0test {
    public static void main(String[] args) throws SQLException {

        //使用【默认的配置】创建 c3p0 的数据库连接池对象
        DataSource dataSource = new ComboPooledDataSource();

        //使用【指定名称的配置】创建 c3p0 的数据源对象
        //DataSource dataSource = new ComboPooledDataSource("fastdb");

        //通过数据源对象获取数据库连接
        //如果连接池中的连接已经被用完,则会等待一定的时间(所配置的时间)
        //如果等待超时,就会抛出异常
        Connection con = dataSource.getConnection();

        //执行 sql 语句,获取并打印结果集
        String sql = "select e_id, e_name, e_age from employee";
        PreparedStatement pst = con.prepareStatement(sql);
        ResultSet rs = pst.executeQuery();
        while (rs.next()) {
            System.out.println(
                    rs.getInt("e_id") + "\t" +
                    rs.getString("e_name") + "\t" +
                    rs.getInt("e_age"));
        }

        //释放资源
        rs.close();
        pst.close();

        //这里的关闭连接,并没有关闭和销毁连接
        //而是把连接对象,放入到连接池中,供后续访问时直接拿去使用
        con.close();
    }
}

如果你之前基于 JDBC 编写过通用的数据库访问类,那么将它改造为基于 c3p0 的数据库访问类,也是很容易的。
比如下面是一个简单的基于 c3p0 的数据库访问类,只提供了获取数据库连接,以及关闭(归还)数据库连接的方法:

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class c3p0helper {

    private static DataSource dataSource;

    //静态初始化,使用默认配置创建 c3p0 数据源对象
    static {
        dataSource = new ComboPooledDataSource();
    }

    //获取数据库连接
    public static Connection getConnection() {
        Connection con = null;
        try {
            con = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }

    //释放查询操作相关的资源(结果集对象,SQL语句对象,归还数据库连接)
    public static void close(Connection con, Statement stat, ResultSet rs) {
        if (con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (stat != null) {
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //释放增删改相关操作的资源(SQL语句对象,归还数据库连接)
    public static void close(Connection con, Statement stat) {
        close(con, stat, null);
    }
}

然后使用这个简单的 c3p0 数据库访问类,改造上面的代码示例:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class c3p0test {
    public static void main(String[] args) throws SQLException {

        Connection con = c3p0helper.getConnection();

        String sql = "select e_id,e_name,e_age from employee";
        PreparedStatement pst = con.prepareStatement(sql);

        ResultSet rs = pst.executeQuery();
        while (rs.next()) {
            System.out.println(
                    rs.getInt("e_id") + "\t" +
                    rs.getString("e_name") + "\t" +
                    rs.getInt("e_age"));
        }

        c3p0helper.close(con, pst, rs);
    }
}

OK,以上只是简单的介绍了一下 c3p0 连接池技术的使用,总体来说使用起来很简单,希望对大家有用。



posted @ 2022-02-12 20:54  乔京飞  阅读(9667)  评论(0编辑  收藏  举报