转自:http://www.cnblogs.com/ysw-go/

JDBC数据库连接池的必要性

一、在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤:

1)在主程序(如servlet/beans)中建立数据库连接

2)进行sql操作

3)断开数据库连接

二、这种模式开发,存在的问题:

1)普通的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将Connection加载进内存中,再验证用户名和密码(得花费0.05s~1s的时间).需要数据库连接的时候,就向数据库要求一个,执行完成后就断开连接。这样的方式将消耗大连的时间和资源。数据库的连接资源并没有得到很好的重复利用。若同时有几百人甚至几千人同时在线,频繁的进行数据库连接将占用很多的系统资源,严重的甚至会造成服务器的崩溃。

2)对于每一次数据库连接,使用完成后都要断开。否则,如果程序出现异常而未能关闭,将导致数据库系统的内存泄露,并最终导致重启数据库。

3)这种开发不能控制被创建的连接对象数,系统资源被毫无顾忌的分配出去,如连接过多,也可能导致内存泄露,服务器崩溃

数据库连接池(connection pool)

1)为了解决传统开发中的数据库连接问题,可以采用数据库连接池技术。

2)数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”,预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需要从“缓冲池”中取出一个,使用完毕之后再放回去。

3)数据库连接池负责分配、管理和释放数据库连接,他允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。

4)数据库连接池在初始化的时候将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。

连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序想连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待序列中.

数据库连接池(connection pool)的工作原理

数据库连接池(connection pool)的优点

1) 资源重用 
由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量);
2) 更快的系统响应速度 
数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间;
3) 新的资源分配手段 
对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接池技术,几年前也许还是个新鲜话题,对于目前的业务系统而言,如果设计中还没有考虑到连接池的应用,那么…….快在设计文档中加上这部分的内容吧。某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源;
4) 统一的连接管理,避免数据库连接泄漏 
在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用连接。从而避免了常规数据库连接操作中可能出现的资源泄漏。一个最小化的数据库连接池实现;

两种开源的数据库连接池
1)JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由服务器(Weblogic,WebSphere,Tomcat)提供实现
--DBCP数据库连接池(Tomcat内置的数据库连接池)
--C3P0数据库连接池(Hibernate推荐使用的数据库连接池,性能不错)
2)DataSource通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把DataSource称为连接池。
DBCP数据库连接池
方式一:
使用DBCP数据库连接池的步骤

* 1.加入JAR包(2个)
* commons-dbcp2-2.1.1.jar
* Commons-pool.jar
* 2.创建数据库连接池
* 3.为数据源实例指定必须的属性
* 4.从数据源中获取数据库连接

具体代码实现:

 1 @Test
 2     public void testDBCP() throws Exception{
 3         DataSource dataSource=null;
 4         //1.创建DBCP数据源实例
 5         dataSource=new BasicDataSource();
 6         //2.为数据源实例指定必须的属性
 7         ((BasicDataSource) dataSource).setUsername("root");
 8         ((BasicDataSource) dataSource).setPassword("123456");
 9         ((BasicDataSource) dataSource).setUrl("jdbc:mysql://localhost:3306/atguigu");
10         ((BasicDataSource) dataSource).setDriverClassName("com.mysql.jdbc.Driver");
11         //3.指定数据源一些可选的属性(可以看下载的Jar包中的index.html)API文档
12         /*
13          * maxIdle,最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。
14            MaxActive,连接池的最大数据库连接数。设为0表示无限制。
15            maxWait ,最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制
16                                 【温馨提示】:pool2中修改如下:
17                     maxActive  ==>  maxTotal
18                     maxWait ==> maxWaitMillis
19          */
20         //1).指定数据库连接池中初始化连接的个数
21         ((BasicDataSource) dataSource).setInitialSize(10);
22         //2).指定数据库连接池中最大连接的个数:同一时刻可以同时向数据库申请的数据库连接
23         ((BasicDataSource) dataSource).setMaxTotal(5);
24         //3).指定数据库连接池中最小连接的个数:在连接池中保存的最小空闲连接的数量
25         ((BasicDataSource) dataSource).setMinIdle(5);
26         //4).指定数据库连接池分配连接的最长时间,单位为毫秒,超出改时间将抛出异常
27         ((BasicDataSource) dataSource).setMaxWaitMillis(1000*5);
28         //4.从数据源中获取数据库连接
29
30         Connection connection=dataSource.getConnection();
31         System.out.println(connection.getClass());
32
33     }

方式二:

使用DBCP数据库连接池的步骤

* 1.加载dbcp的properties配置文件
* 配置文件中的键值对需要来自BasicDataSource这个类的属性
* 2.调用BasicDataSourceFactory的createDataSource方法
* 创建DataSource实例
* 3.从DataSource中获取数据库连接

dbcp.properties文件内容如下:

driver=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/atguigu
user=root
password=123456
initialSize=10
maxTotal=50
minIdle=5
maxWaitMillis=5000

具体代码实现:

 1 @Test
 2     public void testDBCPWithDataSourceFactory() throws Exception{
 3         Properties properties=new Properties();
 4         InputStream inputStream=JDBCTest.class.getClassLoader()
 5                 .getResourceAsStream("dbcp.properties");
 6         properties.load(inputStream);
 7         DataSource dataSource=
 8                 BasicDataSourceFactory.createDataSource(properties);
 9         System.out.println(dataSource.getConnection());
10
11         BasicDataSource basicDataSource=
12                 (BasicDataSource) dataSource;
13         System.out.println(basicDataSource.getMaxTotal());
14
15     }

C3P0数据库连接池

方式一:

这里我们需要加入两个JAR包:c3p0-0.9.5.2.jar和mchange-commons-java-0.2.11.jar

我们下载的c3p0JAR包中的doc文件夹中的index.html文件,点击该文件->Contents->Quickstart,我们可以看到c3p0数据库连接池的创建步骤,如下图所示(我们使用一些JAR包的时候要善于利用好帮助文档):

import com.mchange.v2.c3p0.*;

...

ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver
cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" );
cpds.setUser("dbuser");
cpds.setPassword("dbpassword");

于是我们的代码就可以这样写了:

1     @Test
2     public void testC3P0() throws Exception{
3         ComboPooledDataSource cpds = new ComboPooledDataSource();
4         cpds.setDriverClass( "com.mysql.jdbc.Driver" ); //loads the jdbc driver
5         cpds.setJdbcUrl( "jdbc:mysql://localhost:3306/atguigu" );
6         cpds.setUser("root");
7         cpds.setPassword("123456");
8         System.out.println(cpds.getConnection());
9     }

运行结果:证明创建成功

五月 09, 2016 4:35:56 下午 com.mchange.v2.log.MLog
信息: MLog clients using java 1.4+ standard logging.
五月 09, 2016 4:35:57 下午 com.mchange.v2.c3p0.C3P0Registry
信息: Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
五月 09, 2016 4:35:57 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource
信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1hge1d39g158wpld8tx485|1588809, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1hge1d39g158wpld8tx485|1588809, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/atguigu, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
com.mchange.v2.c3p0.impl.NewProxyConnection@6776ad [wrapping: com.mysql.jdbc.JDBC4Connection@108b2d7]

方式二:使用配置文件的形式

具体的步骤:

     * 1.创建c3p0-config.xml文件,参考帮助文档中
     *   Appendix B: Configuation Files, etc.的内容
     * 2.创建ComboPooledDataSource实例:
     *   DataSource dataSource =
                new ComboPooledDataSource("helloc3p0");
     *3.从DataSource实例中获取数据库连接

其中c3p0-config.xml中的内容我们进行更改成下面的形式:每一行代表什么我都给出了详细的解释

<c3p0-config>

  <named-config name="helloc3p0">
  <!-- 指定数据源的基本属性 -->
    <property name="user">root</property>
    <property name="password">123456</property>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/atguigu</property>
    <!-- 若数据库中连接数不足时,一次向数据库服务器申请多少个连接    -->
    <property name="acquireIncrement">5</property>
    <!-- 初始化数据库连接时连接的数量 -->
    <property name="initialPoolSize">10</property>
    <!-- 数据库连接池中最小的数据库连接数 -->
    <property name="minPoolSize">5</property>
     <!-- 数据库连接池中最大的数据库连接数 -->
    <property name="maxPoolSize">10</property>

    <!-- 数据库连接池可以维护的Statement的个数 -->
    <property name="maxStatements">10</property>
    <!-- 每个连接同时可以使用的Statement对象的个数 -->
    <property name="maxStatementsPerConnection">5</property>

  </named-config>
</c3p0-config>

我们可以看到named-config name="helloc3p0",我们要创建的数据库连接池的名称是helloc3p0;

第二种方式的具体代码实现:

1     @Test
2     public void testC3P0withConfigFile() throws Exception{
3         DataSource dataSource =
4                 new ComboPooledDataSource("helloc3p0");
5         System.out.println(dataSource.getConnection());
6         ComboPooledDataSource comboPooledDataSource=
7                 (ComboPooledDataSource) dataSource;
8         System.out.println(comboPooledDataSource.getMaxStatements());
9     }

测试一些,运行结果:

1 五月 09, 2016 4:42:15 下午 com.mchange.v2.log.MLog
2 信息: MLog clients using java 1.4+ standard logging.
3 五月 09, 2016 4:42:15 下午 com.mchange.v2.c3p0.C3P0Registry
4 信息: Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
5 五月 09, 2016 4:42:15 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource
6 信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> helloc3p0, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1hge1d39g1594tqaufcxlm|1588809, idleConnectionTestPeriod -> 0, initialPoolSize -> 10, jdbcUrl -> jdbc:mysql://localhost:3306/atguigu, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 10, maxStatements -> 10, maxStatementsPerConnection -> 5, minPoolSize -> 5, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
7 com.mchange.v2.c3p0.impl.NewProxyConnection@1bcffb5 [wrapping: com.mysql.jdbc.JDBC4Connection@c1f859]
8 10

此时我们JDBCtools中的获取连接的函数getConnection就可以改写代码了,不是每一次都创建新的数据库连接,而是从数据库连接池中获取连接,release函数也不是真正的关闭连接了,而是把数据库连接继续放到连接池中。

 1     private static DataSource dataSource=null;
 2     //数据库连接池只被初始化一次
 3     static {
 4         dataSource=new ComboPooledDataSource("helloc3p0");
 5     }
 6     // 获取数据库连接
 7     public static Connection getConnection() throws  Exception{
 8
 9         /*    ClassNotFoundException, SQLException {
10         Properties properties = new Properties();
11         InputStream inputStream = JDBCTest.class.getClassLoader()
12                 .getResourceAsStream("jdbc.properties");
13         properties.load(inputStream);
14         String user = properties.getProperty("user");
15         String password = properties.getProperty("password");
16         String jdbcUrl = properties.getProperty("jdbcUrl");
17         String driverClass = properties.getProperty("driver");
18         Class.forName(driverClass);
19         Connection connection = DriverManager.getConnection(jdbcUrl, user,
20                 password);*/
21
22         return dataSource.getConnection();
23     }

数据库连接池一般只有一个,所以我们用static修饰,并使用静态代码块的形式初始化数据库连接池,getConnection中的被注释代码使我们原来的获取连接的方式,可以看到代码简洁了不少!

最后附上两部分用到的JAR包:链接:http://pan.baidu.com/s/1eSjUDn8 密码:49zw

【转】JDBC学习笔记(8)——数据库连接池(dbcp&C3P0)的更多相关文章

  1. JDBC学习笔记(8)——数据库连接池(dbcp&C3P0)

    JDBC数据库连接池的必要性 一.在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤: 1)在主程序(如servlet/beans)中建立数据库连接 2)进行sql操作 3)断开数据库连接 ...

  2. JDBC编程学习笔记之数据库连接池的实现

    在JDBC编程的时候,获取到一个数据库连接资源是很宝贵的,倘若数据库访问量超大,而数据库连接资源又没能得到及时的释放,就会导致系统的崩溃甚至宕机.造成的损失将会是巨大的.再看有了数据库连接池的JDBC ...

  3. java之数据库连接池-dbcp&c3p0&dbutils

    介绍 因为数据库连接对象的创建比较消耗性能,所以可以在应用程序启动时就在内存中开辟一片空间(集合)存放多个数据库连接对象,后面需要连接时直接从该空间中取而不用新创建:使用完毕后归还连接(将连接重新放回 ...

  4. java学习笔记—第三方数据库连接池包1(29)

    第一步:导入dbcp包 第二步:通过核心类连接数据 BasicDataSource它是javax.sql.DataSrouce的子类. 一个工具类:BasicDataSourceFactory. 手工 ...

  5. java攻城狮之路--复习JDBC(数据库连接池 : C3P0、DBCP)

    复习数据库连接池 : C3P0.DBCP 1.数据库连接池技术的优点: •资源重用:      由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销.在减少系统消耗的基础上,另一方面也增 ...

  6. JDBC学习笔记二

    JDBC学习笔记二 4.execute()方法执行SQL语句 execute几乎可以执行任何SQL语句,当execute执行过SQL语句之后会返回一个布尔类型的值,代表是否返回了ResultSet对象 ...

  7. [数据库连接池] Java数据库连接池--DBCP浅析.

    前言对于数据库连接池, 想必大家都已经不再陌生, 这里仅仅设计Java中的两个常用数据库连接池: DBCP和C3P0(后续会更新). 一. 为何要使用数据库连接池假设网站一天有很大的访问量,数据库服务 ...

  8. 常用数据库连接池 (DBCP、c3p0、Druid) 配置说明

    1. 引言 1.1 定义 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库 ...

  9. java常用数据库连接池 (DBCP、c3p0、Druid) 配置说明

    1. 引言 1.1 定义 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库 ...

随机推荐

  1. mysql数据库的中文乱码问题的解决

    今天终于解决了数据库中文乱码的问题,分享出来让更多的人作为参考,我们进入主题: 如果在搭建mysql数据库的时候没有设置它的编码格式,在以后的开发中,中文乱码会是一个令人头疼的问题,所以我在这里分享一 ...

  2. 2017-3-10 SQL server 数据库 T--SQL语句

    创建数据库:create datebase  数据库名     注:数据库名不能为中文,不能数字开头,不能符号开头. 删除数据库:drop datebase 数据库名 创建表:create   tab ...

  3. 网络安全实验室 注入关通关writeup

    URL:http://hackinglab.cn 注入关  [1] 最简单的SQL注入username = admin' or ''='password随便什么都可以直接可以登录 [2] 熟悉注入环境 ...

  4. (1)写给Web初学者的教案-----学习Web的知识架构

    1:学习Web的知识架构 前文中我们简单的介绍了一些关于Web的基本知识,这里任老师再次强调一下凡是用浏览器打开的网站我们就称之为Web应用程序(B/S结构).除此之外其它需要下载安装的软件或是手机  ...

  5. CRUD操作(20161017)

    上午: (7)范围查询 select * from car where price>40 and price<60 select * from car where price betwee ...

  6. Visual Studio 2015/2017 与ASP.NET CORE 联合创建具有SPA模式的Angular2模板

    虽然注册博客园很久,但是一直没有什么可写的,真心感觉好尴尬了,这次终于找到了一点可以写,有点小兴奋和小害羞呢. 进入主题,前端SPA模式越来越受到欢迎,Core 也开始被很多企业提上日程,但是因为这个 ...

  7. 关于js中两种定时器的设置及清除(转载)

    1.JS中的定时器有两种: window.setTimeout([function],[interval]) 设置一个定时器,并且设定了一个等待的时间[interval],当到达时间后,执行对应的方法 ...

  8. 读书笔记 effective c++ Item 35 考虑虚函数的替代者

    1. 突破思维——不要将思维限定在面向对象方法上 你正在制作一个视频游戏,你正在为游戏中的人物设计一个类继承体系.你的游戏处在农耕时代,人类很容易受伤或者说健康度降低.因此你决定为其提供一个成员函数, ...

  9. Win10下 VS2017 安装失败 未能安装包“Microsoft.VisualStudio.AspNet45.Feature,version=15.0.26208.0”

    事情的起因是这样的,前段时间,VS2017发布当天,想在自己的Win10上安装VS2017,然而,由于自己的系统很久没有更新(PS:自己关闭了Windows更新). 安装提示:未能安装包“Micros ...

  10. 对Golang有兴趣的朋友,推荐一款go语言Web框架-dotweb

    Go语言,2009年推出,对我个人,2015年下半年,才下定决心正式开始引入使用Go,自此,让我获得了一种全新的开发体验. 在不断的项目过程中,一个开发人员总喜欢堆积一些代码段,由于Go的开源特性,逐 ...