跳到主要内容

Commons Pool 连接 seekdb 示例程序

本文将介绍如何使用 Commons Pool、MySQL Connector/J 和 seekdb 构建一个应用程序,实现基本的数据库操作,包括创建表、插入数据、更新数据、删除数据、查询数据和删除表等。

点击下载 commonpool-mysql-client 示例工程

前提条件

  • 您已安装 seekdb。

  • 您已安装 JDK 1.8 和 Maven。

  • 您已安装 Eclipse。

    信息

    本文档运行代码使用的工具是 Eclipse IDE for Java Developers 2022-03 版本,您也可以根据个人喜好选择适合自己的工具运行的示例代码。

操作步骤

信息

本文中给出的操作步骤是在 Windows 环境下使用 Eclipse IDE for Java Developers 2022-03 编译和运行该项目的步骤。如果您使用的是其他操作系统环境或编译器,那么操作步骤可能会略有不同。

  1. commonpool-mysql-client 项目导入到 Eclipse 中。
  2. 获取 seekdb URL。
  3. 修改 commonpool-mysql-client 项目中的数据库连接信息。
  4. 运行 commonpool-mysql-client 项目。

步骤一:将 commonpool-mysql-client 项目导入到 Eclipse 中

  1. 打开 Eclipse,在菜单栏上选择 File -> Open Projects from File System

  2. 在弹出的对话框中,点击 Directory 按钮选择项目所在的目录,然后点击 Finish 完成导入。

    信息

    当使用 Eclipse 导入 Maven 项目时,Eclipse 会自动检测项目中的 pom.xml 文件,并根据文件中描述的依赖关系自动下载所需的依赖库,并将它们添加到项目中。

    1

  3. 查看项目情况。

    2

步骤二:获取 seekdb URL

  1. 联系 seekdb 部署人员或者管理员获取相应的数据库连接串。

    示例如下:

    mysql -hxxx.xxx.xxx.xxx -P2881 -uroot -p****** -Dtest

    更多连接串的信息,请参见 通过 MySQL 连接 seekdb

  2. 根据 seekdb 连接串信息填写下面 URL 的对应信息。

    jdbc:mysql://$host:$port/$database_name?user=$user_name&password=$password&useSSL=false

    参数说明:

    • $host:提供 seekdb 的连接 IP。使用实际的 IP 替换,也可以使用本地 IP 及 127.0.0.1。
    • $port:提供 seekdb 接端口。使用实际的端口替换,默认是 2881,在部署 seekdb 时可自定义。
    • $database_name:需要访问的数据库名称。
    • user_name:提供连接账户。格式:用户名
    • password:提供账户密码。

    更多有关 MySQL Connector/J 连接属性信息,请参见 Configuration Properties

    示例如下:

    jdbc:mysql://xxx.xxx.xxx.xxx:2881/test?user=root&password=******&useSSL=false

步骤三:修改 commonpool-mysql-client 项目中的数据库连接信息

根据 步骤二:获取 seekdb URL 中获取的信息修改文件 commonpool-mysql-client/src/main/resources/db.properties 中的数据库连接信息。

3

示例如下:

  • seekdb 的 IP 地址为 xxx.xxx.xxx.xxx
  • 访问端口使用的是 2881。
  • 需要访问的数据库名称为 test
  • 连接账户是 root
  • 密码是 ******

代码如下:

...
db.url=jdbc:mysql://xxx.xxx.xxx.xxx:2881/test?useSSL=false
db.username=root
db.password=******
...

步骤四:运行 commonpool-mysql-client 项目

  1. 在项目导航器视图中,找到并展开 src/main/java 目录。

  2. 右键点击 Main.java 文件,然后选择 Run As -> Java Application

    4

  3. 在 Eclipse 的控制台窗口中来查看输出结果。

    5

项目代码介绍

点击 commonpool-mysql-client 下载项目代码,是一个名称为 commonpool-mysql-client.zip 的压缩包。

解压后,得到一个名为 commonpool-mysql-client 的文件夹。目录结构如下所示:

commonpool-mysql-client
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── Main.java
│ └── resources
│ └── db.properties
└── pom.xml

文件说明:

  • src:源代码根目录。
  • main:主代码目录,包含应用程序的主要逻辑。
  • java:Java 源代码目录。
  • com:Java 包目录。
  • example:示例项目的包目录。
  • Main.java:主类程序示例文件,包含创建表、插入、删除、更新和查询数据等逻辑。
  • resources:资源文件目录,包含配置文件等。
  • db.properties:连接池的配置文件,包含了数据库连接的相关参数。
  • pom.xml:Maven 项目的配置文件,用于管理项目的依赖和构建设置。

pom.xml 代码介绍

pom.xml 文件是 Maven 项目的配置文件,定义了项目的依赖项、插件和构建规则等信息。Maven 是一个 Java 项目管理工具,可以自动下载依赖项、编译和打包项目等操作。

本文 pom.xml 文件的代码主要包括以下几个部分:

  1. 文件声明语句。

    声明本文件是一个 XML 文件,使用的 XML 版本是 1.0,字符编码方式是 UTF-8

    代码如下:

    <?xml version="1.0" encoding="UTF-8"?>
  2. 配置 POM 的命名空间和 POM 模型版本。

    1. 通过 xmlns 指定 POM 的命名空间为 http://maven.apache.org/POM/4.0.0
    2. 通过 xmlns:xsi 指定 XML 命名空间 http://www.w3.org/2001/XMLSchema-instance
    3. 通过 xsi:schemaLocation 指定 POM 的命名空间为 http://maven.apache.org/POM/4.0.0 和 POM 的 XSD 文件的位置为 http://maven.apache.org/xsd/maven-4.0.0.xsd
    4. 通过 <modelVersion> 元素指定了该 POM 文件使用的 POM 模型版本为 4.0.0

    代码如下:

    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 其他配置 -->

    </project>
  3. 配置基本信息。

    1. 通过 <groupId> 指定项目所属组织为 com.example
    2. 通过 <artifactId> 指定项目的名称为 commonpool-mysql-client
    3. 通过 <version> 项目的版本号为 1.0-SNAPSHOT

    代码如下:

        <groupId>com.example</groupId>
    <artifactId>commonpool-mysql-client</artifactId>
    <version>1.0-SNAPSHOT</version>
  4. 配置项目源文件的属性。

    指定 Maven 的编译器插件为 maven-compiler-plugin,并设置了源代码和目标 Java 版本都为 8。这意味着项目的源代码使用 Java 8 特性编写,且编译后的字节码也将兼容 Java 8 运行时环境。这样设置可以确保项目在编译和运行时能够正确地处理 Java 8 的语法和特性。

    信息

    Java 1.8 和 Java 8 是同一个版本的不同命名方式。

    代码如下:

        <build>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
    <source>8</source>
    <target>8</target>
    </configuration>
    </plugin>
    </plugins>
    </build>
  5. 配置项目所依赖组件。

    1. 添加 mysql-connector-java 依赖库,用于与数据库进行交互:

      1. 通过 <groupId> 指定依赖项所属的组织为 mysql
      2. 通过 <artifactId> 指定依赖项的名称为 mysql-connector-java
      3. 通过 <version> 指定依赖项的版本号为 5.1.40

      代码如下:

              <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.40</version>
      </dependency>
    2. 添加 commons-pool2 依赖库,以便在项目中能够使用该库的功能和类:

      1. 通过 <groupId> 指定依赖项所属的组织为 org.apache.commons
      2. 通过 <artifactId> 指定依赖项的名称为 commons-pool2
      3. 通过 <version> 指定依赖项的版本号为 2.7.0

      代码如下:

              <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <version>2.7.0</version>
      </dependency>

db.properties 代码介绍

db.properties 是本文示例的连接池配置文件,其中包含了连接池的配置属性。这些属性包括数据库 URL、用户名、密码、连接池其他可选项。

本文 db.properties 文件的代码主要包括以下几个部分:

  1. 配置数据库连接参数。

    1. 配置数据库连接的 URL,包括主机 IP、端口号、需要访问的数据库。
    2. 配置数据库用户名。
    3. 配置数据库密码。

    代码如下:

    db.url=jdbc:mysql://$host:$port/$database_name?useSSL=false
    db.username=$user_name
    db.password=$password

    参数解释:

    • $host:提供 seekdb 的连接 IP。使用实际的 IP 替换,也可以使用本地 IP 及 127.0.0.1。
    • $port:提供 seekdb 接端口。使用实际的端口替换,默认是 2881,在部署 seekdb 时可自定义。
    • $database_name:需要访问的数据库名称。
    • $user_name:提供连接账户。格式:用户名
    • $password:提供账户密码。
  2. 配置其他连接池的参数。

    1. 设置连接池的最大连接数为 10。这表示连接池中最多可以同时拥有 10 个连接。
    2. 设置连接池的最大空闲连接数为 5。当连接池中的连接数量超过最大空闲连接数时,多余的连接将被关闭。
    3. 设置连接池的最小空闲连接数为 2。即使连接池中没有正在使用的连接,也会保持至少 2 个空闲连接。
    4. 设置从连接池获取连接的最大等待时间为 5000 毫秒。如果连接池中没有可用连接,获取连接的操作将会等待,直到超过最大等待时间为止。

    代码如下:

    pool.maxTotal=10
    pool.maxIdle=5
    pool.minIdle=2
    pool.maxWaitMillis=5000
提示

具体的属性(参数)配置取决于项目需求和数据库的特点,建议您根据实际情况进行调整和配置。

Commons Pool 2 常用配置参数:

参数描述
url指定连接数据库的 URL 地址,包括数据库类型、主机名、端口号、数据库名称等信息。
username连接数据库所需的用户名。
password连接数据库所需的密码。
maxTotal指定对象池中允许创建的最大对象数量。
maxIdle指定对象池中允许保持的最大空闲对象数量。
minIdle指定对象池中保持的最小空闲对象数量。
blockWhenExhausted指定当对象池耗尽时,对 borrowObject 操作的行为。
  • trueborrowObject 方法将阻塞,直到有可用对象为止。
  • falseborrowObject 方法将立即抛出 NoSuchElementException 异常。
maxWaitMillis指定 borrowObject 方法在池耗尽时的最大等待时间(毫秒)。
testOnBorrow指定在 borrowObject 方法调用时是否对对象进行验证。
  • true:每次 borrowObject 方法调用时都会调用对象的 validateObject 方法进行验证。
  • false:不进行验证。
testOnReturn指定在 returnObject 方法调用时是否对对象进行验证。
  • true:每次 returnObject 方法调用时都会调用对象的 validateObject 方法进行验证。
  • false:不进行验证。
testWhileIdle指定当对象处于空闲状态时是否对它们进行验证,具体的含义如下:
  • 当设置为 true 时,表示在对象池中的空闲对象被借出之前,会定期对它们调用 validateObject 方法进行验证。此验证操作可确保空闲对象仍然有效可用。
  • 当设置为 false 时,表示不对空闲对象进行验证,即不会调用 validateObject 方法。
timeBetweenEvictionRunsMillis指定空闲对象的驱逐线程调度的时间间隔(毫秒)。
numTestsPerEvictionRun指定每次驱逐线程调度时要检查的空闲对象数量。

Main.java 代码介绍

Main.java 文件是示例程序的一部分,代码演示了如何使用 Commons Pool 2 执行数据库操作。本文 Main.java 文件的代码主要包括以下几个部分:

  1. 定义包和导入必要的类。

    1. 声明当前代码所属的包名为 com.example
    2. 导入 java.io.IOException 类,用于处理输入输出异常。
    3. 导入 java.sql.Connection 类,用于表示与数据库的连接。可以使用该对象执行 SQL 语句并获取结果。
    4. 导入 java.sql.DriverManager 类,用于管理驱动程序的加载和数据库连接的建立。可以使用该类获取数据库连接。
    5. 导入 java.sql.ResultSet 类,用于表示 SQL 查询的结果集。可以使用该对象遍历和操作查询结果。
    6. 导入 java.sql.SQLException 类,用于处理 SQL 语句相关的异常情况。
    7. 导入 java.sql.Statement 类,用于执行 SQL 语句的对象。可以通过 Connection 对象的 createStatement 方法创建。
    8. 导入 java.util.Properties 类,是一个键值对的集合,用于加载和保存配置信息。可以从配置文件中加载数据库的连接信息。
    9. 导入 org.apache.commons.pool2.ObjectPool 类,是一个对象池接口,定义了池化对象的基本操作,如获取、归还对象等。
    10. 导入 org.apache.commons.pool2.PoolUtils 类,提供了一些工具方法,用于方便地操作对象池。
    11. 导入 org.apache.commons.pool2.PooledObject 类,是一种实现了对象池管理的包装对象。可以通过实现该接口来管理池化对象的生命周期。
    12. 导入 org.apache.commons.pool2.impl.GenericObjectPool 类,是 ObjectPool 接口的默认实现类,实现了连接池的基本功能。
    13. 导入 org.apache.commons.pool2.impl.GenericObjectPoolConfig 类,是 GenericObjectPool 的配置类,用于设置连接池的属性。
    14. 导入 org.apache.commons.pool2.impl.DefaultPooledObject 类,是 PooledObject 接口的默认实现类,用于管理池化对象的包装。它可以包含实际的连接对象以及其他一些管理信息。

    代码如下:

    package com.example;

    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;

    import org.apache.commons.pool2.ObjectPool;
    import org.apache.commons.pool2.PoolUtils;
    import org.apache.commons.pool2.PooledObject;
    import org.apache.commons.pool2.impl.GenericObjectPool;
    import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
    import org.apache.commons.pool2.impl.DefaultPooledObject;
  2. 创建一个 Main 类,并定义 main 方法。

    定义一个 Main 类和 main 方法,main 方法用于演示如何使用连接池从数据库中执行一系列的操作。具体步骤如下:

    1. 定义一个名为 Main 的公共类,作为程序的入口点。类名需要与文件名保持一致。

    2. 定义一个公共静态方法 main,作为程序的起始执行点。

      1. 加载数据库配置文件:

        1. 创建一个 Properties 对象,用于存储数据库配置信息。
        2. 通过 Main 类的类加载器获取 db.properties 资源文件的输入流,并使用 Properties 对象的 load() 方法加载该输入流,将属性文件中的键值对加载到 props 对象中。
        3. 捕获可能抛出的 IOException 异常,并打印异常堆栈信息。
      2. 创建数据库连接池配置:

        1. 创建一个泛型对象池配置对象,用于配置连接池的行为。
        2. 设置连接池中允许的最大连接数。
        3. 设置连接池中允许的最大空闲连接数。
        4. 设置连接池中允许的最小空闲连接数。
        5. 设置获取连接的最大等待时间。
      3. 创建数据库连接池:创建一个线程安全的连接池对象 connectionPool,使用 ConnectionFactory 对象和 poolConfig 配置对象来创建泛型对象池,并将其包装在一个线程安全的对象池中。通过对连接池进行线程安全的包装,可以确保在多线程环境下的连接获取和释放操作的安全性。

      4. 获取数据库连接,使用连接池的 borrowObject() 方法获取一个数据库连接,并在 try 代码块中使用该连接进行数据库操作。

        1. 调用 createTable() 方法,创建表。
        2. 调用 insertData() 方法,插入数据。
        3. 调用 selectData() 方法,查询数据。
        4. 调用 updateData() 方法,更新数据。
        5. 再次调用 selectData() 方法,查询更新后的数据。
        6. 调用 deleteData() 方法,删除数据。
        7. 再次调用 selectData() 方法,查询删除后的数据。
        8. 调用 dropTable() 方法,删除表。
        9. 捕获并打印任何异常。
    3. 定义其他数据库操作方法。

    代码如下:

    public class Main {

    public static void main(String[] args) {
    // Load the database configuration file
    Properties props = new Properties();
    try {
    props.load(Main.class.getClassLoader().getResourceAsStream("db.properties"));
    } catch (IOException e) {
    e.printStackTrace();
    }

    // Create the database connection pool configuration
    GenericObjectPoolConfig<Connection> poolConfig = new GenericObjectPoolConfig<>();
    poolConfig.setMaxTotal(Integer.parseInt(props.getProperty("pool.maxTotal")));
    poolConfig.setMaxIdle(Integer.parseInt(props.getProperty("pool.maxIdle")));
    poolConfig.setMinIdle(Integer.parseInt(props.getProperty("pool.minIdle")));
    poolConfig.setMaxWaitMillis(Long.parseLong(props.getProperty("pool.maxWaitMillis")));

    // Create the database connection pool
    ObjectPool<Connection> connectionPool = PoolUtils.synchronizedPool(new GenericObjectPool<>(new ConnectionFactory(
    props.getProperty("db.url"), props.getProperty("db.username"), props.getProperty("db.password")), poolConfig));

    // Get a database connection
    try (Connection connection = connectionPool.borrowObject()) {

    // Create table
    createTable(connection);

    // Insert data
    insertData(connection);
    // Query data
    selectData(connection);

    // Update data
    updateData(connection);
    // Query the updated data
    selectData(connection);

    // Delete data
    deleteData(connection);
    // Query the data after deletion

    selectData(connection);

    // Drop table
    dropTable(connection);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    // 定义用于创建表的方法
    // 定义用于插入数据的方法
    // 定义用于更新数据的方法
    // 定义用于删除数据的方法
    // 定义用于查询数据的方法
    // 定义用于删除表的方法
    // 定义一个 ConnectionFactory 类
    }
  3. 定义用于创建表的方法。

    定义一个名为 createTable 的方法,接收一个 Connection 对象作为参数。具体步骤如下:

    1. 定义一个私有静态方法 createTable(),接收一个 Connection 对象作为参数,并声明可能抛出 SQLException 异常。
    2. 使用连接的 createStatement() 方法创建一个 Statement 对象,并在 try-with-resources 语句中使用该对象来执行数据库操作。
    3. 定义一个字符串变量 sql,存储创建表的 SQL 语句。
    4. 使用 Statement 对象的 executeUpdate() 方法执行 sql 语句,创建表。
    5. 在控制台输出表创建成功的提示信息。

    代码如下:

        private static void createTable(Connection connection) throws SQLException {
    try (Statement statement = connection.createStatement()) {
    String sql = "CREATE TABLE test_commonpool (id INT,name VARCHAR(20))";
    statement.executeUpdate(sql);
    System.out.println("Table created successfully.");
    }
    }
  4. 定义用于插入数据的方法。

    定义一个名为 insertData() 的方法,接收一个 Connection 对象作为参数。具体步骤如下:

    1. 定义一个私有静态方法 insertData(),接收一个 Connection 对象作为参数,并声明可能抛出 SQLException 异常。
    2. 使用连接的 createStatement() 方法创建一个 Statement 对象,并在 try-with-resources 语句中使用该对象来执行数据库操作。
    3. 定义一个字符串变量 sql,存储插入数据的 SQL 语句。
    4. 使用 Statement 对象的 executeUpdate() 方法执行 sql 语句,插入数据。
    5. 在控制台输出数据插入成功的提示信息。

    代码如下:

        private static void insertData(Connection connection) throws SQLException {
    try (Statement statement = connection.createStatement()) {
    String sql = "INSERT INTO test_commonpool (id, name) VALUES (1,'A1'), (2,'A2'), (3,'A3')";
    statement.executeUpdate(sql);
    System.out.println("Data inserted successfully.");
    }
    }
  5. 定义用于更新数据的方法。

    定义一个名为 updateData() 的方法,接收一个 Connection 对象作为参数。具体步骤如下:

    1. 定义一个私有静态方法 updateData(),接收一个 Connection 对象作为参数,并声明可能抛出 SQLException 异常。
    2. 使用连接的 createStatement() 方法创建一个 Statement 对象,并在 try-with-resources 语句中使用该对象来执行数据库操作。
    3. 定义一个字符串变量 sql,存储更新数据的 SQL 语句。
    4. 使用 Statement 对象的 executeUpdate() 方法执行 sql 语句,更新数据。
    5. 在控制台输出数据更新成功的提示信息。

    代码如下:

        private static void updateData(Connection connection) throws SQLException {
    try (Statement statement = connection.createStatement()) {
    String sql = "UPDATE test_commonpool SET name = 'A11' WHERE id = 1";
    statement.executeUpdate(sql);
    System.out.println("Data updated successfully.");
    }
    }
  6. 定义用于删除数据的方法。

    定义一个名为 deleteData() 的方法,接收一个 Connection 对象作为参数。具体步骤如下:

    1. 定义一个私有静态方法 deleteData(),接收一个 Connection 对象作为参数,并声明可能抛出 SQLException 异常。
    2. 使用连接的 createStatement() 方法创建一个 Statement 对象,并在 try-with-resources 语句中使用该对象来执行数据库操作。
    3. 定义一个字符串变量 sql,存储删除数据的 SQL 语句。
    4. 使用 Statement 对象的 executeUpdate() 方法执行 sql 语句,删除数据。
    5. 在控制台输出数据删除成功的提示信息。

    代码如下:

        private static void deleteData(Connection connection) throws SQLException {
    try (Statement statement = connection.createStatement()) {
    String sql = "DELETE FROM test_commonpool WHERE id = 2";
    statement.executeUpdate(sql);
    System.out.println("Data deleted successfully.");
    }
    }
  7. 定义用于查询数据的方法。

    定义一个名为 selectData() 的方法,接收一个 Connection 对象作为参数。具体步骤如下:

    1. 定义一个私有静态方法 selectData(),接收一个 Connection 对象作为参数,并声明可能抛出 SQLException 异常。
    2. 使用连接的 createStatement() 方法创建一个 Statement 对象,并在 try-with-resources 语句中使用该对象来执行数据库操作。
    3. 定义一个字符串变量 sql,存储查询数据的 SQL 语句。
    4. 使用 Statement 对象的 executeQuery() 方法执行 sql 语句,并将结果存储在 ResultSet 对象中。
    5. 使用 resultSet.next() 方法判断是否还有下一行数据,并进入循环。
    6. 使用 resultSet.getInt() 方法获取当前行的整型数据,该方法的参数为数据的列名。
    7. 使用 resultSet.getString() 方法获取当前行的字符串数据,该方法的参数为数据的列名。
    8. 在控制台输出当前行的数据。

    代码如下:

        private static void selectData(Connection connection) throws SQLException {
    try (Statement statement = connection.createStatement()) {
    String sql = "SELECT * FROM test_commonpool";
    ResultSet resultSet = statement.executeQuery(sql);
    while (resultSet.next()) {
    int id = resultSet.getInt("id");
    String name = resultSet.getString("name");
    System.out.println("id: " + id + ", name: " + name);
    }
    }
    }
  8. 定义用于删除表的方法。

    定义一个名为 dropTable() 的方法,接收一个 Connection 对象作为参数。具体步骤如下:

    1. 定义一个私有静态方法 dropTable(),接收一个 Connection 对象作为参数,并声明可能抛出 SQLException 异常。
    2. 使用连接的 createStatement() 方法创建一个 Statement 对象,并在 try-with-resources 语句中使用该对象来执行数据库操作。
    3. 定义一个字符串变量 sql,存储删除表的 SQL 语句。
    4. 使用 Statement 对象的 executeUpdate() 方法执行 sql 语句,删除表。
    5. 在控制台输出表删除成功的提示信息。

    代码如下:

        private static void dropTable(Connection connection) throws SQLException {
    try (Statement statement = connection.createStatement()) {
    String sql = "DROP TABLE test_commonpool";
    statement.executeUpdate(sql);
    System.out.println("Table dropped successfully.");
    }
    }
  9. 定义一个 ConnectionFactory 类。

    定义一个名为 ConnectionFactory 的静态内部类,继承了 BasePooledObjectFactory 类,并实现了创建和管理连接对象的方法。具体步骤如下:

    信息

    @Override 是一个注解,表示下面的方法是重写父类中的方法。

    1. 定义一个名为 ConnectionFactory 的静态内部类,继承了 org.apache.commons.pool2.BasePooledObjectFactory<Connection> 类,用于创建和管理连接对象的工厂类。
    2. 定义一个私有的不可变字符串变量,存储数据库的 URL。
    3. 定义一个私有的不可变字符串变量,存储连接数据库的用户名。
    4. 定义一个私有的不可变字符串变量,存储连接数据库的密码。
    5. 定义 ConnectionFactory 类的构造函数,用于初始化类的成员变量 urlusernamepassword。构造函数接收三个参数,分别是数据库的 URL、连接数据库的用户名和密码,并将这些参数的值分别赋给对应的成员变量。这样,在创建 ConnectionFactory 对象时,可以通过构造函数传入数据库相关的信息。
    6. 重写了 BasePooledObjectFactory 类中的 create() 方法,用于创建一个新的连接对象。
    7. 使用 DriverManager 类的 getConnection() 方法创建并返回一个连接对象。
    8. 重写了 BasePooledObjectFactory 类中的 destroyObject() 方法,用于销毁连接对象。
    9. 调用连接对象的 close() 方法关闭连接。
    10. 重写了 BasePooledObjectFactory 类中的 validateObject() 方法,用于验证连接对象的有效性。
    11. 调用连接对象的 isValid() 方法检查连接是否有效,设置超时时间为 5000 毫秒。
    12. 重写了 BasePooledObjectFactory 类中的 wrap() 方法,用于将连接对象包装成 PooledObject 对象。
    13. 使用 DefaultPooledObject 类的构造函数创建一个 PooledObject 对象,并将连接对象作为参数传入。

    代码如下:

    static class ConnectionFactory extends org.apache.commons.pool2.BasePooledObjectFactory<Connection> {
    private final String url;
    private final String username;
    private final String password;

    public ConnectionFactory(String url, String username, String password) {
    this.url = url;
    this.username = username;
    this.password = password;
    }

    @Override
    public Connection create() throws Exception {
    return DriverManager.getConnection(url, username, password);
    }

    @Override
    public void destroyObject(org.apache.commons.pool2.PooledObject<Connection> p) throws Exception {
    p.getObject().close();
    }

    @Override
    public boolean validateObject(org.apache.commons.pool2.PooledObject<Connection> p) {
    try {
    return p.getObject().isValid(5000);
    } catch (SQLException e) {
    return false;
    }
    }

    @Override
    public PooledObject<Connection> wrap(Connection connection) {
    return new DefaultPooledObject<>(connection);
    }
    }

完整的代码展示

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>commonpool-mysql-client</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
</project>

db.properties

# Database Configuration
db.url=jdbc:mysql://$host:$port/$database_name?useSSL=false
db.username=$user_name
db.password=$password

# Connection Pool Configuration
pool.maxTotal=10
pool.maxIdle=5
pool.minIdle=2
pool.maxWaitMillis=5000

Main.java

package com.example;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.PoolUtils;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.commons.pool2.impl.DefaultPooledObject;

public class Main {

public static void main(String[] args) {
// Load the database configuration file
Properties props = new Properties();
try {
props.load(Main.class.getClassLoader().getResourceAsStream("db.properties"));
} catch (IOException e) {
e.printStackTrace();
}

// Create the database connection pool configuration
GenericObjectPoolConfig<Connection> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(Integer.parseInt(props.getProperty("pool.maxTotal")));
poolConfig.setMaxIdle(Integer.parseInt(props.getProperty("pool.maxIdle")));
poolConfig.setMinIdle(Integer.parseInt(props.getProperty("pool.minIdle")));
poolConfig.setMaxWaitMillis(Long.parseLong(props.getProperty("pool.maxWaitMillis")));

// Create the database connection pool
ObjectPool<Connection> connectionPool = PoolUtils.synchronizedPool(new GenericObjectPool<>(new ConnectionFactory(
props.getProperty("db.url"), props.getProperty("db.username"), props.getProperty("db.password")), poolConfig));

// Get a database connection
try (Connection connection = connectionPool.borrowObject()) {

// Create table
createTable(connection);

// Insert data
insertData(connection);
// Query data
selectData(connection);

// Update data
updateData(connection);
// Query the updated data
selectData(connection);

// Delete data
deleteData(connection);
// Query the data after deletion
selectData(connection);

// Drop table
dropTable(connection);
} catch (Exception e) {
e.printStackTrace();
}
}

private static void createTable(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement()) {
String sql = "CREATE TABLE test_commonpool (id INT,name VARCHAR(20))";
statement.executeUpdate(sql);
System.out.println("Table created successfully.");
}
}

private static void insertData(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement()) {
String sql = "INSERT INTO test_commonpool (id, name) VALUES (1,'A1'), (2,'A2'), (3,'A3')";
statement.executeUpdate(sql);
System.out.println("Data inserted successfully.");
}
}

private static void updateData(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement()) {
String sql = "UPDATE test_commonpool SET name = 'A11' WHERE id = 1";
statement.executeUpdate(sql);
System.out.println("Data updated successfully.");
}
}

private static void deleteData(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement()) {
String sql = "DELETE FROM test_commonpool WHERE id = 2";
statement.executeUpdate(sql);
System.out.println("Data deleted successfully.");
}
}

private static void selectData(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement()) {
String sql = "SELECT * FROM test_commonpool";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println("id: " + id + ", name: " + name);
}
}
}

private static void dropTable(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement()) {
String sql = "DROP TABLE test_commonpool";
statement.executeUpdate(sql);
System.out.println("Table dropped successfully.");
}
}

static class ConnectionFactory extends org.apache.commons.pool2.BasePooledObjectFactory<Connection> {
private final String url;
private final String username;
private final String password;

public ConnectionFactory(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
}

@Override
public Connection create() throws Exception {
return DriverManager.getConnection(url, username, password);
}

@Override
public void destroyObject(org.apache.commons.pool2.PooledObject<Connection> p) throws Exception {
p.getObject().close();
}

@Override
public boolean validateObject(org.apache.commons.pool2.PooledObject<Connection> p) {
try {
return p.getObject().isValid(5000);
} catch (SQLException e) {
return false;
}
}

@Override
public PooledObject<Connection> wrap(Connection connection) {
return new DefaultPooledObject<>(connection);
}
}
}

相关文档

更多 MySQL Connector/J 的信息,请参见 Overview of MySQL Connector/J