C3P0连接池案例

wen java案例 4

本文目录导读:

C3P0连接池案例

  1. Maven依赖配置
  2. C3P0配置文件(c3p0-config.xml)
  3. JDBC工具类(JDBCUtils.java)
  4. 数据访问测试类(UserDao.java)
  5. 测试主类(Main.java)
  6. properties配置方式(可选)
  7. 注意事项

我来为您提供一个完整的C3P0连接池使用案例,包括配置文件和Java代码示例。

Maven依赖配置

<dependencies>
    <!-- C3P0连接池 -->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.5</version>
    </dependency>
    <!-- MySQL驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.28</version>
    </dependency>
    <!-- 或使用MSSQL -->
    <!-- 
    <dependency>
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>
        <version>9.4.1.jre8</version>
    </dependency>
    -->
</dependencies>

C3P0配置文件(c3p0-config.xml)

在项目的src/main/resources目录下创建c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 默认配置 -->
    <default-config>
        <!-- 数据库连接基础信息 -->
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/test_db?useSSL=false&amp;serverTimezone=UTC</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <!-- 初始化连接数 -->
        <property name="initialPoolSize">5</property>
        <!-- 最大连接数 -->
        <property name="maxPoolSize">20</property>
        <!-- 最小连接数 -->
        <property name="minPoolSize">5</property>
        <!-- 获取连接失败时,从数据库获取新连接的次数 -->
        <property name="acquireRetryAttempts">30</property>
        <!-- 两次连接中间隔时间,单位毫秒 -->
        <property name="acquireRetryDelay">1000</property>
        <!-- 连接测试间隔时间,单位秒 -->
        <property name="testConnectionOnCheckout">true</property>
        <!-- 连接空闲时间,单位秒,超过时间则被回收 -->
        <property name="maxIdleTime">60</property>
        <!-- 连接最大空闲时间 -->
        <property name="maxIdleTimeExcessConnections">30</property>
        <!-- 定期清理连接的间隔时间 -->
        <property name="idleConnectionTestPeriod">30</property>
        <!-- 每次获取连接时测试是否有效 -->
        <property name="preferredTestQuery">SELECT 1</property>
        <!-- 连接耗尽时的增长数 -->
        <property name="acquireIncrement">5</property>
        <!-- 每个连接的最大缓存Statement数量 -->
        <property name="maxStatements">50</property>
        <!-- 每个连接中缓存Statement的最大数量 -->
        <property name="maxStatementsPerConnection">10</property>
        <!-- 连接池中不重要的连接数 -->
        <property name="unreturnedConnectionTimeout">300</property>
        <!-- 调试模式 -->
        <property name="debugUnreturnedConnectionStackTraces">false</property>
    </default-config>
    <!-- 命名配置 -->
    <named-config name="mysql-config">
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/mysql_db?useSSL=false&amp;serverTimezone=UTC</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <!-- 连接池参数 -->
        <property name="initialPoolSize">3</property>
        <property name="minPoolSize">3</property>
        <property name="maxPoolSize">15</property>
        <property name="acquireIncrement">5</property>
        <property name="maxStatements">50</property>
        <property name="testConnectionOnCheckout">true</property>
        <property name="preferredTestQuery">SELECT 1</property>
    </named-config>
</c3p0-config>

JDBC工具类(JDBCUtils.java)

package com.example.util;
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 JDBCUtils {
    private static DataSource dataSource = null;
    // 静态代码块初始化数据源
    static {
        try {
            // 使用默认配置
            dataSource = new ComboPooledDataSource();
            // 或者使用命名配置
            // dataSource = new ComboPooledDataSource("mysql-config");
        } catch (Exception e) {
            e.printStackTrace();
            throw new ExceptionInInitializerError("C3P0连接池初始化失败");
        }
    }
    /**
     * 获取数据库连接
     */
    public static Connection getConnection() throws SQLException {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
            throw e;
        }
    }
    /**
     * 释放资源
     */
    public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (pstmt != null) {
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 通用增删改方法
     */
    public static int update(String sql, Object... params) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            // 设置参数
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }
            }
            return pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            return -1;
        } finally {
            close(conn, pstmt, null);
        }
    }
    /**
     * 获取数据源
     */
    public static DataSource getDataSource() {
        return dataSource;
    }
}

数据访问测试类(UserDao.java)

package com.example.dao;
import com.example.util.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class UserDao {
        // 创建用户表
        public static void createUserTable() {
            String sql = "CREATE TABLE IF NOT EXISTS user (" +
                    "id INT PRIMARY KEY AUTO_INCREMENT," +
                    "username VARCHAR(50) NOT NULL," +
                    "password VARCHAR(50) NOT NULL," +
                    "age INT," +
                    "email VARCHAR(100)," +
                    "created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP" +
                    ")";
            int result = JDBCUtils.update(sql);
            System.out.println("创建表结果: " + (result == -1 ? "失败" : "成功"));
        }
        // 插入用户
        public static int insertUser(String username, String password, Integer age, String email) {
            String sql = "INSERT INTO user (username, password, age, email) VALUES (?, ?, ?, ?)";
            return JDBCUtils.update(sql, username, password, age, email);
        }
        // 查询所有用户
        public static List<String> selectAllUsers() {
            List<String> userList = new ArrayList<>();
            Connection conn = null;
            PreparedStatement pstmt = null;
            ResultSet rs = null;
            try {
                conn = JDBCUtils.getConnection();
                String sql = "SELECT * FROM user";
                pstmt = conn.prepareStatement(sql);
                rs = pstmt.executeQuery();
                while (rs.next()) {
                    int id = rs.getInt("id");
                    String username = rs.getString("username");
                    String password = rs.getString("password");
                    int age = rs.getInt("age");
                    String email = rs.getString("email");
                    userList.add(String.format("ID: %d, 用户名: %s, 密码: %s, 年龄: %d, 邮箱: %s",
                            id, username, password, age, email));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.close(conn, pstmt, rs);
            }
            return userList;
        }
        // 根据用户名查询用户
        public static void selectUserByUsername(String username) {
            Connection conn = null;
            PreparedStatement pstmt = null;
            ResultSet rs = null;
            try {
                conn = JDBCUtils.getConnection();
                String sql = "SELECT * FROM user WHERE username = ?";
                pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, username);
                rs = pstmt.executeQuery();
                while (rs.next()) {
                    System.out.println("找到用户: " + 
                            "ID=" + rs.getInt("id") + 
                            ", 用户名=" + rs.getString("username") +
                            ", 年龄=" + rs.getInt("age") +
                            ", 邮箱=" + rs.getString("email"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.close(conn, pstmt, rs);
            }
        }
        // 更新用户信息
        public static int updateUser(int id, String username, Integer age) {
            String sql = "UPDATE user SET username = ?, age = ? WHERE id = ?";
            return JDBCUtils.update(sql, username, age, id);
        }
        // 删除用户
        public static int deleteUser(int id) {
            String sql = "DELETE FROM user WHERE id = ?";
            return JDBCUtils.update(sql, id);
        }
    }

测试主类(Main.java)

package com.example;
import com.example.dao.UserDao;
import java.util.List;
public class Main {
    public static void main(String[] args) {
        // 1. 创建用户表
        UserDao.createUserTable();
        // 2. 插入多个用户
        int result1 = UserDao.insertUser("张三", "123456", 25, "zhangsan@example.com");
        int result2 = UserDao.insertUser("李四", "abcdef", 30, "lisi@example.com");
        int result3 = UserDao.insertUser("王五", "654321", 28, "wangwu@example.com");
        System.out.println("插入结果: 张三=" + result1 + ", 李四=" + result2 + ", 王五=" + result3);
        // 3. 查询所有用户
        System.out.println("\n=== 查询所有用户 ===");
        List<String> users = UserDao.selectAllUsers();
        for (String user : users) {
            System.out.println(user);
        }
        // 4. 根据用户名查询
        System.out.println("\n=== 查询用户名包含'张'的用户 ===");
        UserDao.selectUserByUsername("张");
        // 5. 更新用户信息
        System.out.println("\n=== 更新用户ID=1的信息 ===");
        int updateResult = UserDao.updateUser(1, "张三丰", 35);
        System.out.println("更新结果: " + (updateResult > 0 ? "成功" : "失败"));
        // 6. 删除用户
        System.out.println("\n=== 删除用户ID=2 ===");
        int deleteResult = UserDao.deleteUser(2);
        System.out.println("删除结果: " + (deleteResult > 0 ? "成功" : "失败"));
        // 7. 最终查询验证
        System.out.println("\n=== 最终用户列表 ===");
        users = UserDao.selectAllUsers();
        for (String user : users) {
            System.out.println(user);
        }
    }
}

properties配置方式(可选)

除了XML配置,也可以使用properties文件配置(c3p0.properties):

# c3p0.properties
c3p0.driverClass=com.mysql.cj.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC
c3p0.user=root
c3p0.password=123456
# 连接池配置
c3p0.initialPoolSize=5
c3p0.minPoolSize=5
c3p0.maxPoolSize=20
c3p0.acquireIncrement=5
c3p0.maxStatements=50
c3p0.maxStatementsPerConnection=10
c3p0.testConnectionOnCheckout=true
c3p0.preferredTestQuery=SELECT 1
c3p0.maxIdleTime=60
c3p0.idleConnectionTestPeriod=30

注意事项

  1. 配置文件路径:c3p0-config.xml必须放在classpath下(src/main/resources)。

  2. 数据库驱动:根据你使用的数据库选择合适的驱动类。

    • MySQL 8.x: com.mysql.cj.jdbc.Driver
    • MySQL 5.x: com.mysql.jdbc.Driver
    • PostgreSQL: org.postgresql.Driver
  3. 连接测试testConnectionOnCheckout=true表示每次获取连接时都测试,这会影响性能,在生产环境建议设置为false。

  4. 资源关闭:使用完毕后一定要关闭连接,释放回连接池。

  5. 连接池监控:可以通过C3P0提供的API查看连接池状态。

// 查看连接池状态
ComboPooledDataSource cpds = (ComboPooledDataSource) JDBCUtils.getDataSource();
System.out.println("活动连接数: " + cpds.getNumBusyConnections());
System.out.println("空闲连接数: " + cpds.getNumIdleConnections());
System.out.println("总连接数: " + cpds.getNumConnections());

这个案例展示了C3P0连接池的基本使用,包括配置、工具类封装和实际业务操作,您可以根据实际需求修改数据库连接信息和连接池参数。

抱歉,评论功能暂时关闭!