详解C3P0(数据库连接池)

article/2025/10/29 16:53:46

一、基本定义

  C3P0是一个开源的JDBC连接池,它实现了数据源与JNDI绑定,支持JDBC3规范和实现了JDBC2的标准扩展说明的Connection和Statement池的DataSources对象。

  即将用于连接数据库的连接整合在一起形成一个随取随用的数据库连接池(Connection pool)。

 

二、使用C3P0(数据库连接池)的必要性

  当我们在进行基于数据库的web程序开发时,我们可以先在主程序(如Servlet、Bean)中通过JDBC中的DriverManager建立数据库连接,然后将要对数据库进行操作的sql语句封装到Statement中,最后在返回结果集后断开数据库连接。以上是较为传统的开发模式,然而用这种模式开发会埋下严重的安全隐患。

1.JDBC传统模式开发存在的主要问题

    1.1>时间和内存资源消耗巨大

      普通的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将Connection加载到内存中,再根据JDBC代码(或配置文件)中的用户名和密码进行验证其正确性。这一过程一般会花费0.05~1s,一旦需要数据库连接的时候就必须向数据库请求一个,执行完后再断开连接。显然,如果同一个数据库在同一时间有数十人甚至上百人请求连接势必会占用大量的系统资源,严重的会导致服务器崩溃。

    1.2>有内存泄漏的风险

      因为每一次数据库连接使用完后都需要断开连接,但如果程序出现异常致使连接未能及时关闭,这样就可能导致内存泄漏,最终只能以重启数据库的方法来解决;

      另外使用传统JDBC模式开发不能控制需要创建的连接数,系统一般会将资源大量分出给连接以防止资源不够用,如果连接数超出一定数量也会有极大的可能导致内存泄漏。

 

三、数据库连接池的详细说明

  为了解决由使用传统开发模式创建连接导致的一系列问题,我们可以采用数据库连接池技术。

  数据库连接池的基本原理就是为数据库建立一个缓冲池。在缓冲池中先创建指定数量的数据库连接,当有连接请求时就从缓冲池中取出处于“空闲”状态的连接,并将此连接标记为“忙碌”,直到该请求进程结束后,它所使用的连接才会重新回到“空闲”状态,并等待下一次请求调用。

  从上面不难看出数据库连接池的主要作用就是负责分配、管理和释放数据库连接,它允许程序重复使用同一个现有的数据库连接,大大缩短了运行时间,提高了执行效率。

  这里需要强调一点的是,数据库连接池中的连接数是在其初始化时根据c3p0-config.xml中的最小连接数来确定的,关于c3p0-config.xml我会在后文提供模板以供大家参考。当然,无论连接池的连接数是否有被使用,它都至少会保持最小连接数,如果请求连接数超过最小连接数也会根据c3p0-config.xml中指定的自增长数增加连接数直到达到最大连接数,这时如果请求连接数量还是大于连接池中的连接数的话,剩下的请求将会被放入等待队列直到有空闲连接出现。

  这样一来,数据库连接池相较于传统JDBC模式等到请求发出才创建连接的做法有着显而易见的优势。

 

四、使用连接池的明显优势

1.资源的高效利用

  由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销,减小了系统资源消耗的同时也提高了系统运行环境的平稳性。

2.更快的系统反应速度

  数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接可以避免数据库在连接初始化和释放过程所需的时间开销,从而减少了系统的响应时间,提高了系统的反应速度。

3.减少了资源独占的风险

  新的资源分配手段对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置实现对某一应用最大可用数据库连接数的限制,避免了应用独占所有数据库资源的风险。

4.统一的连接管理,避免数据库连接泄露

  在实现较为完善的数据库连接池时,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。

 

——————————————我是一条优雅的分割线——————————————

  虽然数据库连接池(Connection pool)种类很多,并不仅限于c3p0这一个,像DBCP、BoneCP、Proxool、SmartPool、MiniConnectionPoolManager等等都是较为常用的,c3p0只是其中较为优秀且使用人数较多的一款,因为标题的原因这里只说c3p0。

 

五、C3P0实操

1.导入jar包

主要是c3p0和mysql,其他根据需求添加

2.配置xml文件

 下面是我配置的c3p0-config.xml,可以作为模板以供大家参考:

3. 一般c3p0-config.xml模板

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config><default-config><!--mysql数据库连接的各项参数--><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/day06</property><property name="user">root</property><property name="password">root</property><!--配置数据库连接池的初始连接数、最小链接数、获取连接数、最大连接数、最大空闲时间--><property name="initialPoolSize">10</property><property name="minPoolSize">10</property><property name="acquireIncrement">5</property><property name="maxPoolSize">100</property><property name="maxIdleTime">30</property></default-config>
</c3p0-config>

 当然,除了以上这几种常用的参数设置以外,这里还有一份有关c3p0-config.xml参数的详细清单,如有需要可自行增加。

4.c3p0-config.xml参数清单

<c3p0-config>   <default-config>   <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->   <property name="acquireIncrement">3</property>   <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->   <property name="acquireRetryAttempts">30</property>   <!--两次连接中间隔时间,单位毫秒。Default: 1000 -->   <property name="acquireRetryDelay">1000</property>   <!--连接关闭时默认将所有未提交的操作回滚。Default: false -->   <property name="autoCommitOnClose">false</property>   <!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么   属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试   使用。Default: null-->   <property name="automaticTestTable">Test</property>   <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效   保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试   获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->   <property name="breakAfterAcquireFailure">false</property>   <!--当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出   SQLException,如设为0则无限期等待。单位毫秒。Default: 0 -->   <property name="checkoutTimeout">100</property>   <!--通过实现ConnectionTester或QueryConnectionTester的类来测试连接。类名需制定全路径。   Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester-->   <property name="connectionTesterClassName"></property>   <!--指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可   Default: null-->   <property name="factoryClassLocation">null</property>   <!--强烈不建议使用该方法,将这个设置为true可能会导致一些微妙而奇怪的bug-->   <property name="forceIgnoreUnresolvedTransactions">false</property>   <!--每60秒检查所有连接池中的空闲连接。Default: 0 -->   <property name="idleConnectionTestPeriod">60</property>   <!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->   <property name="initialPoolSize">3</property>   <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->   <property name="maxIdleTime">60</property>   <!--连接池中保留的最大连接数。Default: 15 -->   <property name="maxPoolSize">15</property>   <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements   属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。   如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->   <property name="maxStatements">100</property>   <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->   <property name="maxStatementsPerConnection"></property>   <!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能   通过多线程实现多个操作同时被执行。Default: 3-->   <property name="numHelperThreads">3</property>   <!--当用户调用getConnection()时使root用户成为去获取连接的用户。主要用于连接池连接非c3p0   的数据源时。Default: null-->   <property name="overrideDefaultUser">root</property>   <!--与overrideDefaultUser参数对应使用的一个参数。Default: null-->   <property name="overrideDefaultPassword">password</property>   <!--密码。Default: null-->   <property name="password"></property>   <!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:   测试的表必须在初始数据源的时候就存在。Default: null-->   <property name="preferredTestQuery">select id from test where id=1</property>   <!--用户修改系统配置参数执行前最多等待300秒。Default: 300 -->   <property name="propertyCycle">300</property>   <!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的   时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable   等方法来提升连接测试的性能。Default: false -->   <property name="testConnectionOnCheckout">false</property>   <!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->   <property name="testConnectionOnCheckin">true</property>   <!--用户名。Default: null-->   <property name="user">root</property>   <!--早期的c3p0版本对JDBC接口采用动态反射代理。在早期版本用途广泛的情况下这个参数   允许用户恢复到动态反射代理以解决不稳定的故障。最新的非反射代理更快并且已经开始   广泛的被使用,所以这个参数未必有用。现在原先的动态反射与新的非反射代理同时受到   支持,但今后可能的版本可能不支持动态反射代理。Default: false-->   <property name="usesTraditionalReflectiveProxies">false</property> </default-config>      
</c3p0-config>

5.创建C3P0Util类

package com.c3p0.utils;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource;public class C3P0Util {//使用ComboPooledDataSource来生成DataSource的实例private static DataSource dataSource = new ComboPooledDataSource();//从连接池中获取连接public static Connection getConnection() {try {return dataSource.getConnection();} catch (SQLException e) {// TODO Auto-generated catch blockthrow new RuntimeException();}}//释放连接回连接池public static void release(Connection conn, Statement stmt, ResultSet rs) {if (rs != null) {try {rs.close();} catch (Exception e) {e.printStackTrace();}rs = null;}if (stmt != null) {try {stmt.close();} catch (Exception e) {e.printStackTrace();}stmt = null;}if (conn != null) {try {conn.close();} catch (Exception e) {e.printStackTrace();}conn = null;}}
}

1.相较于JDBC,使用C3P0能够更加高效地建立与数据库的连接,尤其是在高并发随机访问数据库的时候;

2.C3P0通过dataSource.getConnection()从线程池中获取“空闲”连接,真正的数据库连接创建与释放则是由C3P0在后台自行完成的,我们只花费了获取和释放连接占用权的时间;

3.使用c3p0-config.xml代替原来JDBC硬编码的形式,提高了代码复用性。

 


http://chatgpt.dhexx.cn/article/2scRFDbL.shtml

相关文章

C3P0连接池的使用

C3P0连接池的使用 什么是连接池&#xff1f;C3P0连接池的使用什么是C3P0&#xff1f;环境准备手动配置主要步骤开始编写&#xff01; 采用配置文件的方式主要步骤开始编写&#xff01; 完整代码及运行结果 什么是连接池&#xff1f; 既然叫做池&#xff0c;那么连接池(Connect…

C3P0连接池配置文档

一、导入jar包 下载链接 二、配置文件 配置文件名称&#xff1a;c3p0-config.xml (固定) 配置文件路径&#xff1a;src (类路径) 配置文件内容&#xff1a;命名配置 <c3p0-config><!-- 命名的配置 --><named-config name"test"><!-- 连接数…

C3P0数据库连接池的配置

在pom.xml文件中导入jar包 <dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version> </dependency> 在src目录下创建c3p0-config.xml文件 <c3p0-config><named-config …

C3P0连接池的基本配置与使用

上一期我写了一篇Druid连接池的基本配置与使用&#xff0c;今天我要介绍一下C3P0连接池的基本使用。因为是介绍基本使用&#xff0c;所以我打算用一个非常简单的java应用来教大家如何对C3P0连接池进行基本配和使用。所以你只要有jdbc和Java基础就能看懂这篇文章&#xff0c;并学…

Windows API编程(一)最基础的知识介绍:Windows编程基础

主要内容简介&#xff1a; 1. Windows 编程基础&#xff1a;开发环境和开发过程。 2. Windows事件驱动模型和消息机制。 3. Windows的资源&#xff1a;图标、光标、菜单、位图等。 4. Windows绘图&#xff1a;图形和文字的显示。 5. 对话框和控件。 6. 静态库和动态库。 …

通过一个最简单的程序入门Windows编程

一、最简单的程序 我们首先先一个最简单的Windows程序&#xff0c;功能是显示一个消息框&#xff0c;随便提示一些文字就可以了。 看一下代码&#xff1a; #include <Windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, in…

windows编程 线程局部存储(TLS)详解

文章目录 一、基本概念二、基本使用三、例子分析&#xff1a; 总结 一、基本概念 线程局部存储&#xff08;TLS&#xff09;&#xff0c;是一种变量的存储方法&#xff0c;这个变量在它所在的线程内是全局可访问的&#xff0c;但是不能被其他线程访问到&#xff0c;这样就保持…

windows编程入门

记录一下windows编程编写一个消息框&#xff0c;算是学习windows编程的入门级程序吧 以下代码来自&#xff1a;《windows游戏编程大师技巧&#xff08;第二版&#xff09;》 #include<Windows.h> #include<windowsx.h> #include<string> #include<sstre…

Windows编程捕获特定窗口及键盘鼠标消息模拟

Windows编程捕获特定窗口及键盘鼠标消息模拟 一、简介二、使用到的API简介三、获取Windows记事本的编辑区窗口的句柄并模拟输入操作1、分析2、代码一3、代码二 四、后记 一、简介 窗口是Windows的核心组件&#xff0c;Windoows下的绝大部分应用都是利用Windows提供的原生窗口&…

【Windows编程】实时捕捉屏幕

实时捕捉屏幕 主要分为三个部分 获取屏幕 // 两个函数都可以进行位图复制&#xff0c;不过StretchBlt可以按照位图进行拉伸或者压缩 BitBlt(HDC hdc,int x,int y,int cx,int cy,HDC hdcSrc,int x1,int y1,DWORD rop); 或者 StretchBlt(HDC hdcDest,int xDest,int yDest,int …

Windows编程初步(一)

第一节:安装帮助文档 使用C语言进行Windows开发,必然使用到WindowsSDK。Windows SDK指Windows开发人员工具包,是为使用C语言开发Windows程序所提供的工具集。里面提供的工具异常全面丰富,很少有人能全部了解,在开发Windows应用程序时,应同时使用MSDN,即俗称Windows开发…

Windows编程

Windows编程基础 Windows系统级开发&#xff0c;简称Win32 应用程序分类 在Windows这个操作系统平台上&#xff0c;共有三类应用程序控制台程序Console Dos程序&#xff0c;本身没有窗口&#xff0c;通过Windows DOS窗口执行 窗口程序 拥有自己的窗口&#xff0c;可以与用户…

【Windows编程】windows窗口创建过程详解

文章目录 前言1 应用程序的分类2 应用程序分类的对比3 编译工具4 windows库文件和头文件5 WinMain函数和MessageBox函数初始6 窗口类7 窗口类的分类8 注册窗口类函数9 注册窗口类的结构体10 注册全局和局部窗口类11 创建窗口的函数12 创建一个windows的过程步骤13 创建一个子窗…

windows系统编程1——线程和进程

学习视频链接 03进程的创建_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Fd4y1G7Td?p3&vd_source0471cde1c644648fafd07b54e303c905 目录 一、创建线程 二、线程间同步 2.1 线程不同步的结果 2.2 原子操作上锁 2.3 临界区 2.4 内核对象 三、线程间通信…

day01 windows编程入门

文章目录 window编程基本概念Windows常见的数据类型字符串的处理 第一个windows程序的编写 window编程基本概念 Windows编程的本质就是使用好操作系统&#xff0c;想要用好操作系统必不可少的秘籍----MSDN。 Windows编程主要分为两种&#xff1a; 1、控制台编程(CUI) 2、图形界…

10行代码带你入门Windows编程

Windows编程——Hello World 开发工具效果展示源代码主函数主函数参数HINSTANCEhInstanccehPreInstanceLPSTRlpCmdLinenCmdShowMessageBox 小知识 开发工具 Visual Studio 2013 效果展示 源代码 #include <Windows.h> //头文件//主函数 int WINAPI WinMain(HINSTANC…

使用VS Code进行Qt开发

使用VS Code进行Qt开发 文章目录 使用VS Code进行Qt开发测试环境步骤1. 将Qt的bin目录添加到环境变量2. 安装VS Code扩展3. 使用Qt Creator创建CMake项目4. 在VS Code中打开项目5. 构建并运行项目7. 调试项目 一些小问题 Qt Creator界面不美观&#xff0c;而VS Code更漂亮一些。…

Qt开发CAN通信的环境配置

Qt开发CAN通信的环境配置 目录 1 开发环境 1 1.1 编程环境 1 1.2 工程设置 1 1.3 调试窗口设置 2 1.4 依赖库 2 1.5 源代码的适配 3 2 运行及硬件环境 3 2.1 CAN设备 3 2.4 运行支持文件 3 3 故障解决 4 3.1 转到槽函数失败 4 1 开发环境 1.1 编程环境 工程采用Windows系统下的…

Qt开发必备技术栈学习路线和资料

简介 本文为&#xff1a;C QT 学习路线大纲资料&#xff08;文章底部&#xff09; Qt 可以做什么&#xff1f; Qt 虽然经常被当做一个 GUI 库&#xff0c;用来开发图形界面应用程序&#xff0c;但这并不是 Qt 的全部&#xff1b;Qt 除了可以绘制漂亮的界面&#xff08;包括控…

WIndows下搭建Qt开发环境 -- Qt 、Qt Creater 安装、配置

[本文发布于https://blog.csdn.net/Stack_/article/details/122491885&#xff0c;未经许可不得转载&#xff0c;转载须注明出处] 一、需要下载安装哪些文件 1Qt SDK&#xff0c;即Qt官方提供的API2编辑器、UI设计器 – Qt Creater3编译器 其中Qt Creater是可以被Visual Studi…