转自:51某博客
本文主要对连接池的基本原理以及dbcp的实现方式做一个分析,对dbcp的配置参数结合原理做一个简单解释。
连接池扼要
JDBC是一套通用的Java语言与多种数据库(文件)通讯的标准API。大部分针对数据库服务器(例如Oracle, MySQL等等)的JDBC实现都是基于TCP/IP连接的客户端-服务器端通讯方式。
当我们需要执行一个数据库操作时,有下面三步:
1. 客户端与服务器之间建立一个数据库连接
2. 执行某种数据库操作
3. 断开连接
如果每次处理都要走上面的三步,则应用程序与数据库服务器都要将大量的时间和资源消耗在数据连接的断开与建立上。对于并发较大的系统,建立一次连接然后缓存起来连续使用,直到程序结束等情况下再释放连接,就能够将系统资源集中在对数据库操作的处理上,从而大大提高性能。通常情况下将数据连接的建立和断开委托给一种能够数据库连接池的组件或服务进行管理。而DBCP, C3p0, Proxool等都是常用的开源的连接池组件。
就好像A公司在郊外,他们公司附近没有出租车。如果A公司有人要出去办事,他必须打电话给出租公司订车,用完车后他还要付账报销。 这样每个人出去一趟都必须订车、退车和报销。员工的很多时间白白花费在这上面了。于是A公司跟出租车公司定了一个合同,出租车公司给了他们一个车队。要用车随时去楼下找车队就可以了,用完了也不必结帐,A公司统一跟出租车公司订车和结帐。这个车队就好比连接池,由公司(应用程序)来统一向出租车公司(数据库服务器)订车(建立连接)和退车(关闭连接)。
DBCP的配置参数以及背后的原理
Commons-dbcp连接池的配置参数比较多,也比较复杂,主要分为
· Jdbc连接参数(username, password, url, driverClassName, connectionProperties )
· 事务处理参数 (defaultAutoCommit, defaultReadOnly, defaultTransactionIsolation, defaultCatalog)
· 连接池参数(详见下文)
· 连接池中链接存活性测试参数(详见下文)
· 预处理查询池化参数(poolPreparedStatements, maxOpenPreparedStatements)
· 丢弃失效链接相关参数(详见下文)以及一个控制是否可以正常情况下处于访问连接池包装下的底层JDBC链接参数(accessToUnderlyingConnectionAllowed)
其中Jdbc链接参数、事务处理都跟连接池关系不大,另预处理查询池化参数本文不详细叙述。有关commons-dbcp的详细参数配置信息请参考官方文档。
连接池的配置
在连接池中,这几个参数是十分重要的,官方的说明如下,是我们调节系统性能时需要认真考虑的值。
Parameter
|
Default
|
Description
|
initialSize
|
0
|
The initial number of connections that are created when the pool is started. Since: 1.2 线程池启动时初始化的连接数
|
maxActive
|
8
|
The maximum number of active connections that can be allocated from this pool at the same time, or non-positive for no limit. 最大活动连接数,如果非正整数,则不做限制。
|
maxIdle
|
8
|
The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit. 最大空闲连接数。
|
minIdle
|
0
|
The minimum number of connections that can remain idle in the pool, without extra ones being created, or zero to create none. 最小空闲连接数。
|
maxWait
|
indefinitely
|
The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception, or -1 to wait indefinitely. (在没有连接可用时)连接池等待一个数据连接可用时的以毫秒计的最大等待时间,超时以后抛出异常, -1 则将无限等待
|
实际上,Dbcp 依赖于 commons-pool 来存储连接对象。 BasicDataSource默认使用GenericObjectPool来管理连接对象。除了请求的线程会在请求和返回连接过程中影响池中连接实例外,另有一个跑着GenericObjectPool.Evictor类型 (implements Runnable) 的实例的线程,也会影响池中的数据库连接。
对象池(ObjectPool接口): 可以把它认为是一种容器, 它是用来装池对象的, 并且包含了用来创建池对象的工厂对象
池对象:就是要放到池容器中的对象, 理论上可以是任何对象.
对象池工厂(ObjectPoolFactory接口):用来创建对象池的工厂, 这个没什么好说的.
池对象工厂(PoolableObjectFactory接口):用来创建池对象, 将不用的池对象进行钝化(passivateObject), 对要使用的池对象进行激活(activeObject), 对池对象进行验证(validateObject), 对有问题的池对象进行销毁(destroyObject)等工作
commons-dbcp数据库连接池正是使用commons-pool来创建和数据库之间的连接对象,在对象池中保存这些对象,从而减少了频繁建立连接对象所造成的性能损耗。本文讲述了commons-dbcp是怎样利用commons-pool来建立对象池的。
例如在tomcat中,利用JNDI来查找到资源javax.sql.DataSource的实现,如果使用dbcp连接池,则该实现为org.apache.commons.dbcp.BasicDataSource。我们可以从这个称为“数据源”的类中调用getConnection方法来获得与数据库的连接。但内部是如何实现的呢?对象池在其中占据什么位置呢?这一切对于外部使用者来说是透明的。
BasicDataSource的getConnection首先建立了PoolingDataSource对象来getConnection。这个PoolingDataSource对象中引用了ObjectPool,在getConnection()时,是从ObjectPool中借用了一个对象,既调用ObjectPool.borrowObject()方法。而对于熟悉commons-pool的程序员来说,ObjectPool肯定有与之对应的Factory创建对象,并放到池中。因此dbcp通过实现了接口org.apache.commons.pool.PoolableObjectFactory的类org.apache.commons.dbcp.PoolableConnectionFactory的makeObject方法来创建连接Connection对象。然而PoolableConnectionFactory持有对ConnectionFactory的引用,ConnectionFactory可以有3种策略来创建Connection对象。其中DriverConnectionFactory调用了数据库厂商提供的Driver来获得Connection。如图所示。
在创建连接时,是创建的DelegatingConnection实例,该对象持有对池的引用,对于java.sql.Connectionl.close()方法来说是调用的对象池的returnObject方法来返回池,而不是真正的把连接关掉。而我们在外界调用这个方法时,并未发现这一点。而对于调用Connection的其他方法而言,都是委派到由Driver得到的Connection相对应的方法。即PoolableConnection-->Connection,前者实现了DelegatingConnection。
在用dbcp连接池的时候,若设置了poolPreparedStatements属性为true,则PoolableConnectionFactory在makeObject时,建立的连接存在的委派关系如下:PoolableConnection-->PoolingConnection-->Connection。PoolingConnection实现了KeyedPoolableObjectFactory,从而为与之对应的对象池keyedObjectPool形成双向关联。在对象池中,以PStmtKey(包含有sql等属性)来标示该池中的一类对象。因此在使用dbcp连接池时,若配置了poolPreparedStatements属性,注意尽量保持相同功能的sql写法一致,来充分利用对象池。
分享到:
相关推荐
**标题解析:** "commons-dbcp-1.4.jar依赖包" 指的是Apache Commons DBCP项目的一个特定版本,即1.4版本的jar文件。Apache Commons DBCP是一个...理解并掌握其工作原理和使用方法对于提升Java应用的性能至关重要。
3. **池化PreparedStatement**:DBCP还可以池化预编译的SQL语句(PreparedStatement对象),进一步提高性能,因为预编译的SQL语句只需要一次解析过程,后续多次执行时可以直接使用。 4. **配置灵活性**:DBCP允许...
DBCP1.4源码分析可以帮助我们深入理解其工作原理,从而更好地在实际项目中应用和优化。 DBCP基于Jakarta Pool,实现了JDBC连接池功能。它包含以下几个核心组件: 1. **BasicDataSource**: 这是DBCP的主要类,它...
《Apache Commons DBCP 1.4 源码解析》 Apache Commons DBCP(Database Connection Pool)是Apache软件基金会开发的一个开源项目,它提供了一个数据库连接池组件。DBCP的主要作用在于管理数据库连接,使得多个用户...
**一、DBCP的工作原理** 1. **连接池概念**:DBCP的核心功能是管理数据库连接,即通过连接池来复用已存在的数据库连接,而不是每次请求都创建新的连接。这减少了数据库连接的创建和销毁带来的开销,提高了系统效率...
数据库连接池的工作原理主要包括以下几个步骤: 1. 初始化阶段,连接池创建一定数量的数据库连接并存储起来。 2. 当应用需要访问数据库时,从连接池中获取一个空闲连接,而不是直接建立新的连接。 3. 使用完毕后,...
它内置了SQL解析器,可以统计SQL执行性能,提供Web监控界面,方便开发者实时查看数据库连接池状态。此外,Druid还具有良好的性能和稳定性,尤其是在高并发环境下,它的表现通常优于DBCP和C3P0。 在实际应用中,选择...
6. 连接池的工作原理:连接的获取、使用和归还,以及连接的生命周期管理。 以上是DBCP数据库连接池的基本使用和配置方法,通过这种方式,可以有效地管理和优化数据库的连接,提高系统的运行效率。
《深入解析Apache Commons DBCP 1.4》 Apache Commons DBCP(Database Connection Pool)是Apache软件基金会开发的一个数据库连接池组件,它在Java应用程序中提供了数据库连接的池化管理。在Java环境中,DBCP是实现...
**标题与描述解析** 本文将深入探讨一个基于Tomcat 7.0的DBCP(Database Connection Pool)数据库连接池的封装工具包,该工具包设计为可移植的,适用于JavaSE(标准版)和JavaEE(企业版)环境。这个工具包是为Java...
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- 数据源属性 --> ``` 然后在 `ProcessEngineConfiguration` 中引用这个数据源bean。 总结来说,理解...
### Apache Jakarta Commons 使用手册知识...通过阅读《Apache Jakarta Commons 使用手册》,开发者可以更深入地了解每个组件的工作原理,并学会如何有效地将它们应用于自己的项目中,从而大大提高开发效率和产品质量。
本文将详细介绍两个常用的数据库连接池实现:Apache的DBCP和c3p0,并结合提供的jar包文件,解析其工作原理和使用方法。 一、Apache DBCP(Jakarta Commons DBCP) Apache DBCP是Apache软件基金会提供的一个开源...
DBCP的工作原理包括以下几个关键点: 1. 初始化:应用启动时,DBCP会预先创建一定数量的数据库连接,并将它们存储在连接池中。 2. 连接请求:当应用需要连接时,不是直接创建新的连接,而是从连接池中获取一个已经...
这三种驱动程序各自有其特点和优势,下面将详细阐述它们的原理、使用方法以及适用场景。 1. C3P0 C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。C3P0的主要特性包括: ...
《Tomcat架构解析与优化》一书主要涵盖了Apache Tomcat服务器的基础架构、工作原理以及性能调优策略。Tomcat作为一款广泛使用的Java Servlet容器,它的高效运行和优化对于任何Java Web应用都至关重要。 首先,...
【关键方法解析】 1. **构造函数**:构造函数接收数据库的相关信息,用于初始化连接池的基本参数。 2. **getInitialConnections**和**setInitialConnections**:这两个方法分别用于获取和设置连接池的初始大小,即...