主流Java数据库连接池比较与开发配置实战

1.数据库连接池概述

数据库连接的建立是一种耗时、性能低、代价高的操作,频繁的数据库连接的建立和关闭极大的影响了系统的性能。数据库连接池是系统初始化过程中创建一定数量的数据库连接放于连接池中,当程序需要访问数据库时,不再建立一个新的连接,而是从连接池中取出一个已建立的空闲连接,使用完毕后,程序将连接归还到连接池中,供其他请求使用,从而实现的资源的共享,连接的建立、断开都由连接池自身来管理。

数据库连接池为系统的运行带来了以下优势:昂贵的数据库连接资源得到重用;减少了数据库连接建立和释放的时间开销,提高了系统响应速度;统一的数据库连接管理,避免了连接资源的泄露。

数据库连接池运行机制:

系统初始化时创建连接池,程序操作数据库时从连接池中获取空闲连接,程序使用完毕将连接归还到连接池中,系统退出时,断开所有数据库连接并释放内存资源。

主流Java数据库连接池比较与开发配置实战_第1张图片

2.主流数据库连接池比较

常用的主流开源数据库连接池有C3P0、DBCP、Tomcat Jdbc Pool、BoneCP、Druid等

C3p0: 开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。单线程,性能较差,适用于小型系统,代码600KB左右。

DBCP (Database Connection Pool):由Apache开发的一个Java数据库连接池项目, Jakarta commons-pool对象池机制,Tomcat使用的连接池组件就是DBCP。单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar,预先将数据库连接放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完再放回。单线程,并发量低,性能不好,适用于小型系统。

Tomcat Jdbc Pool:Tomcat在7.0以前都是使用common-dbcp做为连接池组件,但是dbcp是单线程,为保证线程安全会锁整个连接池,性能较差,dbcp有超过60个类,也相对复杂。Tomcat从7.0开始引入了新增连接池模块叫做Tomcat jdbc pool,基于Tomcat JULI,使用Tomcat日志框架,完全兼容dbcp,通过异步方式获取连接,支持高并发应用环境,超级简单核心文件只有8个,支持JMX,支持XA Connection。

BoneCP:官方说法BoneCP是一个高效、免费、开源的Java数据库连接池实现库。设计初衷就是为了提高数据库连接池性能,根据某些测试数据显示,BoneCP的速度是最快的,要比当时第二快速的连接池快25倍左右,完美集成到一些持久化产品如Hibernate和DataNucleus中。BoneCP特色:高度可扩展,快速;连接状态切换的回调机制;允许直接访问连接;自动化重置能力;JMX支持;懒加载能力;支持XML和属性文件配置方式;较好的Java代码组织,100%单元测试分支代码覆盖率;代码40KB左右。

Druid:Druid是Java语言中最好的数据库连接池,Druid能够提供强大的监控和扩展功能,是一个可用于大数据实时查询和分析的高容错、高性能的开源分布式系统,尤其是当发生代码部署、机器故障以及其他产品系统遇到宕机等情况时,Druid仍能够保持100%正常运行。主要特色:为分析监控设计;快速的交互式查询;高可用;可扩展;Druid是一个开源项目,源码托管在github上。

主流连接池各项功能对比如下:

主流Java数据库连接池比较与开发配置实战_第2张图片

3.数据库连接池Spring集成配置与JNDI配置

下面针对每一种连接池的使用方法,在开发中如何配置给出spring集成配置和在tomcat的conf/context.xml文件中配置2种方式,限于篇幅只给出基本参数,详细参数可自行研究。

3.1 阿里Druid连接池

Maven依赖

<dependency>
  <groupId>com.alibabagroupId>
  <artifactId>druidartifactId>
  <version>1.0.28version>
dependency>

Spring集成配置方式

[html]  view plain  copy
  1.   
  2.     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">  
  3.           
  4.         <property name="url" value="${jdbc.url}" />  
  5.         <property name="username" value="${jdbc.username}" />  
  6.         <property name="password" value="${jdbc.password}" />  
  7.           
  8.         <property name="initialSize" value="1" />  
  9.         <property name="minIdle" value="1" />  
  10.         <property name="maxActive" value="20" />  
  11.           
  12.         <property name="maxWait" value="60000" />  
  13.           
  14.         <property name="timeBetweenEvictionRunsMillis" value="60000" />  
  15.           
  16.         <property name="minEvictableIdleTimeMillis" value="300000" />  
  17.           
  18.         <property name="poolPreparedStatements" value="true" />  
  19.         <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />  
  20.           
  21.         <property name="filters" value="stat" />  
  22.     bean>  
  23.     Web.xml配置  
  24.        
  25.       <filter>  
  26.         <filter-name>DruidWebStatFilterfilter-name>  
  27.         <filter-class>com.alibaba.druid.support.http.WebStatFilterfilter-class>  
  28.         <init-param>  
  29.           <param-name>exclusionsparam-name>  
  30.           <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*param-value>  
  31.         init-param>  
  32.       filter>  
  33.       <filter-mapping>  
  34.         <filter-name>DruidWebStatFilterfilter-name>  
  35.         <url-pattern>/*url-pattern>  
  36.       filter-mapping>  
  37.         
  38.       <servlet>  
  39.         <servlet-name>DruidStatViewservlet-name>  
  40.         <servlet-class>com.alibaba.druid.support.http.StatViewServletservlet-class>  
  41.       servlet>  
  42.       <servlet-mapping>  
  43.         <servlet-name>DruidStatViewservlet-name>  
  44.         <url-pattern>/druid/*url-pattern>  
  45.       servlet-mapping>  

Tomcat中context.xml文件JNDI配置方式

com.alibaba.druid.pool.DruidDataSourceFactory实现了javax.naming.spi.ObjectFactory,可以作为JNDI数据源来配置
/conf/context.xml配置JNDI方式

[html]  view plain  copy
  1. <Resource  
  2.         name="jdbc/MysqlDataSource"  
  3.         factory="com.alibaba.druid.pool.DruidDataSourceFactory"  
  4.         auth="Container"  
  5.         type="javax.sql.DataSource"  
  6.         driverClassName="com.mysql.jdbc.Driver"  
  7.         url="jdbc:mysql://192.168.1.233:3306/lead_oams?useUnicode=true&characterEncoding=utf-8"  
  8.         username="lead_system"  
  9.         password="password"  
  10.         maxActive="50"  
  11.         maxWait="10000"  
  12.         removeabandoned="true"  
  13.         removeabandonedtimeout="60"  
  14.         logabandoned="false"  
  15.         filters="stat"/>  
 web.xml配置

[html]  view plain  copy
  1.   
  2.   <resource-ref>  
  3.       <description>MySQL DB Connectiondescription>  
  4.       <res-ref-name>jdbc/MysqlDataSourceres-ref-name>  
  5.       <res-type>javax.sql.DataSourceres-type>  
  6.       <res-auth>Containerres-auth>  
  7.   resource-ref>  

Java代码中获取JNDI数据源

  //1、初始化名称查找上下文

  Context ctx =new InitialContext();

  //2、通过JNDI名称找到DataSource

 DruidDataSource ds = (DruidDataSource)ctx.lookup("java:comp/env/jdbc/MysqlDataSource");

  //3、通过ds获取数据库连接对象

  Connectionconn = ds.getConnection();

3.2 BoneCP连接池

Maven依赖

<dependency>
  <groupId>com.jolboxgroupId>
  <artifactId>bonecp-springartifactId>
  <version>0.8.0.RELEASEversion>
dependency>

Spring集成BoneCP配置方式

[html]  view plain  copy
  1.   
  2.     <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">  
  3.           
  4.         <property name="driverClass" value="${jdbc.driver}" />  
  5.           
  6.         <property name="jdbcUrl" value="${jdbc.url}" />  
  7.           
  8.         <property name="username" value="${jdbc.username}" />  
  9.           
  10.         <property name="password" value="${jdbc.password}" />  
  11.           
  12.         <property name="idleConnectionTestPeriod" value="60" />  
  13.           
  14.         <property name="idleMaxAge" value="30" />  
  15.           
  16.         <property name="maxConnectionsPerPartition" value="150" />  
  17.           
  18.         <property name="minConnectionsPerPartition" value="5" />  
  19.     bean>  

Tomcat中BoneCP使用JNDI配置方式

[html]  view plain  copy
  1. <Resource  
  2.   name="JNDIName"  
  3.   auth="Container"  
  4.   type="com.jolbox.bonecp.BoneCPDataSource"  
  5.   factory="org.apache.naming.factory.BeanFactory"  
  6.   driverClass="oracle.jdbc.driver.OracleDriver"  
  7.   username="root"   
  8.     password="root"   
  9.   jdbcUrl="jdbc:mysql://localhost:3306/test"  
  10.   idleConnectionTestPeriod="0"  
  11.   idleMaxAge="10"  
  12.   partitionCount="1"  
  13.   maxConnectionsPerPartition="5"  
  14.   minConnectionsPerPartition="1"  
  15.   connectionTestStatement=""  
  16.   initSQL="select 1 from dual"/>  

Java代码中获取JNDI数据源

  //1、初始化名称查找上下文

  Context ctx =new InitialContext();

  //2、通过JNDI名称找到DataSource

  DataSource ds= (DataSource) ctx.lookup("java:comp/env/jdbc/MysqlDataSource");

  //3、通过ds获取数据库连接对象

  Connectionconn = ds.getConnection();

3.3 Tomcat Jdbc Pool连接池

Maven依赖

<dependency>
  <groupId>org.apache.tomcatgroupId>
  <artifactId>tomcat-jdbcartifactId>
  <version>7.0.75version>
dependency>
<dependency>
  <groupId>org.apache.tomcatgroupId>
  <artifactId>tomcat-juliartifactId>
  <version>7.0.75version>
dependency>

Spring集成Tomcat Jbdc Pool配置方式

[html]  view plain  copy
  1.    
  2.     <bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">  
  3.         <property name="poolProperties">  
  4.         <bean class="org.apache.tomcat.jdbc.pool.PoolProperties">  
  5.           
  6.         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  7.         <property name="url" value="jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8"/>  
  8.         <property name="username" value="root"/>  
  9.         <property name="password" value="root"/>  
  10.           
  11.         <property name="jmxEnabled" value="true"/>  
  12.         <property name="testWhileIdle" value="true"/>  
  13.         <property name="testOnBorrow" value="true"/>  
  14.         <property name="testOnReturn" value="false"/>  
  15.         <property name="validationInterval" value="30000"/>  
  16.         <property name="validationQuery" value="SELECT 1"/>  
  17.         <property name="timeBetweenEvictionRunsMillis" value="30000"/>  
  18.           
  19.         <property name="maxActive" value="50"/>  
  20.           
  21.         <property name="initialSize" value="5"/>  
  22.           
  23.         <property name="maxWait" value="10000"/>  
  24.         <property name="minEvictableIdleTimeMillis" value="30000"/>  
  25.         <property name="minIdle" value="10"/>  
  26.           
  27.         <property name="logAbandoned" value="false"/>  
  28.         <property name="removeAbandoned" value="true"/>  
  29.         <property name="removeAbandonedTimeout" value="60"/>  
  30.         <property name="jdbcInterceptors" value="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"/>  
  31.     bean>  

Tomcat中context.xml文件JNDI配置方式

[html]  view plain  copy
  1. <Resource     
  2.     name="jdbc/test"    
  3.     auth="Container"    
  4.     factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"    
  5.     testWhileIdle="true"    
  6.     testOnBorrow="true"    
  7.     testOnReturn="false"    
  8.     validationQuery="SELECT 1"    
  9.     validationInterval="30000"    
  10.     timeBetweenEvictionRunsMillis="30000"    
  11.     driverClassName="com.mysql.jdbc.Driver"    
  12.     maxActive="100"    
  13.     maxIdle="40"  
  14.     maxWait="12000"    
  15.     initialSize="10"    
  16.     removeAbandonedTimeout="60"    
  17.     removeAbandoned="true"    
  18.     logAbandoned="true"    
  19.     minEvictableIdleTimeMillis="30000"    
  20.     jmxEnabled="true"    
  21.     jdbcInterceptors=    
  22.      "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"    
  23.     username="root"   
  24.     password="root"   
  25.     type="javax.sql.DataSource"     
  26.     url="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"/>       

Java代码中获取JNDI数据源

//1、初始化名称查找上下文

  Context ctx =new InitialContext();

  //2、通过JNDI名称找到DataSource

  DataSource ds= (DataSource) ctx.lookup("java:comp/env/jdbc/test");

  //3、通过ds获取数据库连接对象

  Connectionconn = ds.getConnection();

3.4 Apache DBCP连接池

Maven依赖

<dependency>
  <groupId>commons-dbcpgroupId>
  <artifactId>commons-dbcpartifactId>
  <version>1.4version>
dependency>
<dependency>
  <groupId>commons-collectionsgroupId>
  <artifactId>commons-collectionsartifactId>
  <version>3.2.2version>
dependency>
<dependency>
  <groupId>commons-poolgroupId>
  <artifactId>commons-poolartifactId>
  <version>1.6version>
dependency>

Spring集成DBCP配置方式

[html]  view plain  copy
  1.   
  2.      <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">  
  3.        <property name="driverClassName" value="${jdbc.driverClassName}"/>  
  4.        <property name="url" value="${jdbc.url}"/>  
  5.        <property name="username" value="${jdbc.username}"/>  
  6.        <property name="password" value="${jdbc.password}"/>  
  7.          
  8.        <property name="initialSize" value="5"/>  
  9.          
  10.        <property name="maxActive" value="50"/>  
  11.          
  12.        <property name="maxIdle" value="10"/>  
  13.          
  14.        <property name="minIdle" value="3"/>  
  15.            
  16.        <property name="removeAbandoned" value="true" />  
  17.            
  18.        <property name="removeAbandonedTimeout" value="200"/>  
  19.           
  20.        <property name="logAbandoned" value="true"/>  
  21.            
  22.        <property name="maxWait" value="100"/>    
  23.      bean>  
  24.     

Tomcat中context.xml文件JNDI配置方式

[html]  view plain  copy
  1. <Resource name="/jdbc/test"   
  2.         type="javax.sql.DataSource"   
  3.         driverClassName="com.sybase.jdbc3.jdbc.SybDataSource"   
  4.         url="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"   
  5.         username="root"   
  6.         password="root"   
  7.         initialSize="5"  
  8.         maxActive="50"   
  9.         maxIdle="10"   
  10.         minIdle="3"  
  11.         maxWait="50000" />     

Java代码中获取JNDI数据源

//1、初始化名称查找上下文

  Context ctx =new InitialContext();

  //2、通过JNDI名称找到DataSource

  DataSource ds= (DataSource) ctx.lookup("java:comp/env/jdbc/test");

  //3、通过ds获取数据库连接对象

  Connectionconn = ds.getConnection();

3.5 C3p0连接池

Maven依赖

<dependency>
  <groupId>c3p0groupId>
  <artifactId>c3p0artifactId>
  <version>0.9.1.2version>
dependency>

Spring集成配置方式

[html]  view plain  copy
  1.   
  2.     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">  
  3.         <property name="jdbcUrl" value="${jdbc.url}" />  
  4.         <property name="driverClass" value="${jdbc.driverClassName}" />  
  5.         <property name="user" value="${jdbc.username}" />  
  6.         <property name="password" value="${jdbc.password}" />  
  7.           
  8.         <property name="maxPoolSize" value="100" />  
  9.           
  10.         <property name="minPoolSize" value="1" />  
  11.           
  12.         <property name="initialPoolSize" value="10" />  
  13.           
  14.         <property name="maxIdleTime" value="30" />  
  15.           
  16.         <property name="acquireIncrement" value="5" />  
  17.           
  18.         <property name="maxStatements" value="0" />  
  19.           
  20.         <property name="idleConnectionTestPeriod" value="60" />  
  21.           
  22.         <property name="acquireRetryAttempts" value="30" />  
  23.           
  24.         <property name="breakAfterAcquireFailure" value="true" />  
  25.           
  26.         <property name="testConnectionOnCheckout"  value="false" />          
  27.     bean>  

Tomcat中context.xml文件JNDI配置方式

[html]  view plain  copy
  1. <Resource   
  2.          name="jdbc/MysqlDataSource"   
  3.          auth="Container"  
  4.          factory="org.apache.naming.factory.BeanFactory"   
  5.          type="com.mchange.v2.c3p0.ComboPooledDataSource"  
  6.          driverClass="com.mysql.jdbc.Driver"  
  7.          idleConnectionTestPeriod="60"  
  8.         maxPoolSize="50"   
  9.         minPoolSize="2"  
  10.         acquireIncrement="2"   
  11.         user="root"   
  12.         password="root"  
  13.         jdbcUrl="jdbc:mysql://localhost:3306/test"/>   

Java代码中获取JNDI数据源

  //1、初始化名称查找上下文

  Context ctx =new InitialContext();

  //2、通过JNDI名称找到DataSource

  DataSource ds= (DataSource) ctx.lookup("java:comp/env/jdbc/MysqlDataSource");

  //3、通过ds获取数据库连接对象

  Connectionconn = ds.getConnection();

4.总结

     本文所比较的5种数据库连接池在性能方面,根据个人测试结果和参考网上资料Druid > TomcatJDBC > DBCP > C3P0,BoneCP的性能方面没有深入比较,应该和Tomcat Jdbc差不多。对于小型的系统,并发压力不大时,选择哪一种数据库连接池差别不会很大,主要考虑的应该是连接池的稳定性。当并发量较高时,一般不会选择使用DBCP和C3P0,选择Druid是较好的。本文给出了5种数据库连接池通过Spring配置和Tomcat JNDI方式配置两种方式,Spring配置一般使用单独的属性文件,每一个连接池都提供了使用代码创建的方式,使用方式也比较类似,感兴趣可以自行研究。另外连接不同的数据库时,在配置方面的差异主要在driverClass和jdbcUrl两项,优化配置项可以另行考虑。

欢迎大家关注博主订阅号“Java技术日志”,提供Java相关技术分享,从Java编程基础到Java高级技术,从JavaWeb技术基础Jsp、Servlet、JDBC到SSH、SSM开发框架,从REST风格接口设计到分布式项目实战。剖析主流开源技术框架,用亲身实践来谱写深度Java技术日志。

你可能感兴趣的:(DataSource)