java 数据库连接池

1、当我们创建一个数据库连接,经过的过程

1.“DriverManager”检查并注册驱动程序,
2.“com.mysql.jdbc.Driver”就是我们注册了的驱动程序,它会在驱动程序类中调用“connect(url…)”方法。
3.com.mysql.jdbc.Driver 的 connect 方法根据我们请求的“connUrl”,创建一个“Socket 连接”,连接到 IP 为“your.database.domain”,默认端口 3306 的数据库。
4. 创建的 Socket 连接将被用来查询我们指定的数据库,并最终让程序返回得到一个结果。

建立连接是费时的活动,每次连接耗时在 0.05s 到 1 秒,大多时候建立连接比执行 sql 花费的时间都长;数据库连接池就是负责分配,管理,关闭数据库连接,它允许应用程序重复使用同一个数据库连接,避免频繁建立数据库连接。

2、需要注意

1、并发问题

为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为各个语言自身提供了对并发管理的支持像 java,c# 等等,使用 synchronized(java)、lock(C#) 关键字即可确保线程是同步的。

2、事务处理

我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-OR-NOTHING”原则,即对于一组 SQL 语句要么全做,要么全不做。

我们知道当2个线程公用一个连接 Connection 对象,而且各自都有自己的事务要处理时候,对于连接池是一个很头疼的问题,因为即使 Connection 类提供了相应的事务支持,可是我们仍然不能确定那个数据库操作是对应那个事务的,这是由于我们有2个线程都在进行事务操作而引起的。为此我们可以使用每一个事务独占一个连接来实现,虽然这种方法有点浪费连接池资源但是可以大大降低事务管理的复杂性。

3、连接池的分配与释放

连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。

对于连接的管理可使用一个 List。即把已经创建的连接都放入 List 中去统一管理。每当用户请求一个连接时,系统检查这个 List 中有没有可以分配的连接。如果有就把那个最合适的连接分配给他(如何能找到最合适的连接文章将在关键议题中指出);如果没有就抛出一个异常给用户,List 中连接是否可以被分配由一个线程来专门管理。

4、连接池的配置与维护

连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConnection)和最大连接数(maxConnection)等参数来控制连接池中的连接。比方说,最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过软件需求上得到。

如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。

3、Tomcat 连接池

 Tomcat 默认使用的是 DBCP 数据库连接池,其实从本质上讲,Tomcat 是利用 Apache Commons DBCP 来实现的,只不过把特定的功能集成到了 tomcat-dbcp.jar 包中。使用法法如下:

 步骤 1:在 Tomcat 中 Context.xml 中添加

   

    <!--  path 表示站点的访问方式 -->  
<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">    例:http://localhost:8080/test 配置为/test </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> docBase="fileLocation" 应用存储的实际路径,没有的话则从webapps目录找 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> Context标签内的这些属性都可以省略不写,使用默认的设置 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Context </span><span style="color: rgba(255, 0, 0, 1)">path</span><span style="color: rgba(0, 0, 255, 1)">="/TomcatDbPools"</span><span style="color: rgba(255, 0, 0, 1)"> docBase</span><span style="color: rgba(0, 0, 255, 1)">="TomcatDbPools"</span><span style="color: rgba(255, 0, 0, 1)"> debug</span><span style="color: rgba(0, 0, 255, 1)">="0"</span><span style="color: rgba(255, 0, 0, 1)"> reloadable</span><span style="color: rgba(0, 0, 255, 1)">="true"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

            <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">     使用DBCP配置的数据源        </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Resource   

</span><span style="color: rgba(255, 0, 0, 1)">&lt;!-- 指定资源池的Resource的JNDI的名字,就是给连接池起的名字 --</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       name="jdbc/mysql_connect"    

</span><span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 管理权限,指定管理Resource的Manager,可以是Container或Application </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       auth="Container"            

</span><span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">指出Resource所属的类名,是什么类型的数据源</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       type="javax.sql.DataSource"    

</span><span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 数据库驱动类 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       driverClassName="com.mysql.jdbc.Driver"    

</span><span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 数据库连接url</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       url=" jdbc:mysql://localhost:3306/test"    

</span><span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 数据库用户名 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       username="admin"    

</span><span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 数据库密码 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       password="123456"    

</span><span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 连接池最大激活的连接数,设为0表示无限制</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       maxActive="100"    

</span><span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 连接池中最多可空闲的连接数 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       maxIdle="30"    

</span><span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 为连接最大的等待时间,单位毫秒,如果超过此时间将接到异常。设为-1表示无限制</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span><span style="color: rgba(0, 0, 0, 1)">  

       maxWait="10000" /&gt;   

</span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">context</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  </pre>
View Code

注:还可以用 minIdle 配置连接池中最少空闲 maxIdle 个连接,用 initialSize 配置初始化连接数目。可同时配置多个数据源

 

如果在 Tomcat 的 server.xml 文件中配置数据源,有两种方法都可以实现:

方法 1:将上面的配置内容直接添加在 <Host> 节点下。

方法 2:在 <GlobalNamingResources> 节点下添加:

    <GlobalNamingResources>  
<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 这里的factory指的是该Resource 配置使用的是哪个数据源配置类,这里使用的是tomcat自带的标准数据源Resource配置类,</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 这个类也可以自己写,实现javax.naming.spi.ObjectFactory 接口即可。 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 某些地方使用的commons-dbcp.jar中的org.apache.commons.dbcp.BasicDataSourceFactory,</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 如果使用这个就需把commons-dbcp.jar及其依赖的jar包,都放在tomcat的lib下,光放在工程的WEB-INF/lib下是不够的。  </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Resource   

    </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="mysql_connect"</span><span style="color: rgba(255, 0, 0, 1)">                  

    factory</span><span style="color: rgba(0, 0, 255, 1)">="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"</span><span style="color: rgba(255, 0, 0, 1)">  

    maxActive</span><span style="color: rgba(0, 0, 255, 1)">="100"</span><span style="color: rgba(255, 0, 0, 1)">   

    maxIdle</span><span style="color: rgba(0, 0, 255, 1)">="30"</span><span style="color: rgba(255, 0, 0, 1)">   

    maxWait</span><span style="color: rgba(0, 0, 255, 1)">="10000"</span><span style="color: rgba(255, 0, 0, 1)">   

    name</span><span style="color: rgba(0, 0, 255, 1)">="jdbc/TomcatDbPool1"</span><span style="color: rgba(255, 0, 0, 1)">   

    password</span><span style="color: rgba(0, 0, 255, 1)">="123456"</span><span style="color: rgba(255, 0, 0, 1)">   

    type</span><span style="color: rgba(0, 0, 255, 1)">="javax.sql.DataSource"</span><span style="color: rgba(255, 0, 0, 1)">   

    url</span><span style="color: rgba(0, 0, 255, 1)">="jdbc:mysql://localhost:3306/test"</span><span style="color: rgba(255, 0, 0, 1)">   

    username</span><span style="color: rgba(0, 0, 255, 1)">="root"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>               

<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">GlobalNamingResources</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  </pre>
View Code

 


然后在 context.xml 文件中的 <Context></Context> 节点中加入如下内容:

 

    <ResourceLink name="jdbc/mysql_connect" global="mysql_connect" type="javax.sql.DataSource"/>  

 

 

在 server.xml 中配置的数据源是全局的,所有项目都可以使用。全局的 resource 只是为了重用,方便所有该 tomcat 下的 web 工程的数据源管理,但如果你的 tomcat 不会同时加载多个 web 工程,也就是说一个 tomcat 只加载一个 web 工程时,是没有必要配置全局的 resource 的。此外,还需要将 mysql 的 Java 驱动类以及其他依赖包(如果有)放到 tomcat 的 lib 目录下。

 

步骤 2:在 web.xml 中,配置 <resource-ref> 元素以在 web 应用中引用 JNDI 资源。   

    <resource-ref>  
      <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 对该资源的描述语言 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

   <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span> dbcpconnect<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

      <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 引用的资源名,必须与Context.xml中的名字一致 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

   <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">res-ref-name</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span> jdbc/mysql_connect <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">res-ref-name</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

      <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 资源类型 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

  <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">res-type</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>javax.sql.DataSource<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">res-type</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

      <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 管理权限 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

   <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">res-auth</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>Container<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">res-auth</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">resource-ref</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  </pre>

 

 

步骤 3:在 Web 应用中使用数据源

 

    //获得对数据源的引用:  

    Context ctx =new InitialContext();  
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">java:comp/env/是java中JNDI固定写法。  </span>
DataSource ds =(DataSource) ctx.lookup("java:comp/env/jdbc/mysql_connect");
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得数据库连接对象:  </span>
Connection conn= ds.getConnection();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回数据库连接到连接池:  </span>
conn.close();

 

 

4、DBCP 连接池

DBCP 是 Apache 软件基金组织下的开源连接池实现,要使用 DBCP 数据源,需要应用程序应在系统中增加如下两个 jar 文件:Commons-dbcp.jar:连接池的实现  Commons-pool.jar:连接池实现的依赖库。Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。

步骤 1:在类目录下加入 dbcp 的配置文件:dbcp.properties

    #数据库驱动  
driverClassName=com.mysql.jdbc.Driver  

#数据库连接地址  

url=jdbc:mysql://localhost/test  

#用户名  

username=root  

#密码  

password=123456  

#连接池的最大数据库连接数。设为0表示无限制  

maxActive=30  

#最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连  

#接将被标记为不可用,然后被释放。设为0表示无限制  

maxIdle=10  

#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制  

maxWait=1000  

#超过removeAbandonedTimeout时间后,是否进行没用连接(废弃)的回收(默认为false,调整为true)  

removeAbandoned=true  

#超过时间限制,回收没有用(废弃)的连接(默认为 300秒)  

removeAbandonedTimeout=180  </span></pre>

 

步骤 2:在获取数据库连接的工具类 (如 jdbcUtils) 的静态代码块中创建池:

    import java.io.InputStream;  
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.sql.Connection;  

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.sql.ResultSet;  

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.sql.SQLException;  

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.sql.Statement;  

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Properties;  

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.sql.DataSource;  

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.commons.dbcp.BasicDataSourceFactory;  

   

      </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> 

     * 在java中,编写数据库连接池需实现java.sql.DataSource接口,每一种数据库连接池都是DataSource接口的实现 

     * DBCP连接池就是java.sql.DataSource接口的一个具体实现 

     </span><span style="color: rgba(0, 128, 0, 1)">*/</span>  

<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> classJdbcUtils_DBCP {  

    

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> DataSource ds = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;  

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在静态代码块中创建数据库连接池  </span>

    <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)">{  

        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{  

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">加载dbcp.properties配置文件  </span>
InputStream in =JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcp.properties");
            Properties prop </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Properties();  

            prop.load(in);  

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建数据源  </span>
ds =BasicDataSourceFactory.createDataSource(prop);
        }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {  

            </span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> newExceptionInInitializerError(e);  

        }  

    }  

     

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从数据源中获取数据库连接  </span>

    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Connection getConnection()<span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> SQLException{  

        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从数据源中获取数据库连接  </span>

        <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ds.getConnection();  

    }  

     

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">释放连接  </span>

    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> release(Connection conn){  

          </span><span style="color: rgba(0, 0, 255, 1)">if</span>(conn!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){  

            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{  

                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">将Connection连接对象还给数据库连接池  </span>
conn.close();
            }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {  

                e.printStackTrace();  

            }  

      }  

 }  

}  </span></pre>
View Code

 

步骤 3:在应用中获取连接

 

    Connection conn = null;  
PreparedStatement st </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;  

ResultSet rs </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;  

</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{  

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取数据库连接  </span>
conn =JdbcUtils_DBCP.getConnection();
    ……  

}</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {  

    e.printStackTrace();  

}</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">{  

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">释放资源  </span>
JdbcUtils_DBCP.release(conn);
}  </span></pre>

 

 5、c3p0 连接池

c3p0 是一个开源的 JDBC 连接池,它实现了数据源和 JNDI 绑定,支持 JDBC3 规范和 JDBC2 的标准扩展。c3p0 一般是与 Hibernate,Spring 等框架一块使用的,当然也可以单独使用。

dbcp 没有自动回收空闲连接的功能,c3p0 有自动回收空闲连接功能。

使用 c3p0 需要导入c3p0.jar、mchange-commons-.jar,如果操作的是 Oracle 数据库,那么还需要导入 c3p0-oracle-thin-extras-pre1.jar。

步骤 1:在类目录下加入 C3P0 的配置文件:c3p0-config.xml

    <c3p0-config>  
   <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">  C3P0的缺省(默认)配置,</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

   <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 如果在代码中“ComboPooledDataSourceds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

     

   <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">default-config</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="driverClass"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>com.mysql.jdbc.Driver<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="jdbcUrl"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>jdbc:mysql://localhost:3306/anysearch<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="user"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>root<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="password"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>123456<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

             <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default:3 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="acquireIncrement"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>5<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

             <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">初始化的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="initialPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>10<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

             <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">连接池中保留的最小连接数</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="minPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>5<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

             <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">连接池中保留的最大连接数。Default:15 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="maxPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>20<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

             <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="acquireRetryAttempts"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>30<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

             <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">两次连接中间隔时间,单位毫秒。Default: 1000 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="acquireRetryDelay"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>1000<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

             <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">连接关闭时默认将所有未提交的操作回滚。Default: false </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

         <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="autoCommitOnClose"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>false<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">default-config</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

      

    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> C3P0的命名配置,</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 如果在代码中“ComboPooledDataSourceds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>  

      

    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">named-config </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="MySQL"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="driverClass"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>com.mysql.jdbc.Driver<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="jdbcUrl"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>jdbc:mysql://localhost:3306/test2<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="user"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>root<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="password"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>123456<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="acquireIncrement"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>5<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="initialPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>10<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="minPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>5<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="maxPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>20<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">named-config</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  

   

<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">c3p0-config</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>  </pre>
View Code

 

还有更多可设置的参数,具体可查阅相关资料。

步骤 2:在获取数据库连接的工具类 (如 jdbcUtils) 的静态代码块中创建池

    import java.sql.Connection;  
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.sql.ResultSet;  

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.sql.SQLException;  

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.sql.Statement;  

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> com.mchange.v2.c3p0.ComboPooledDataSource;  

   

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> JdbcUtils_C3P0 {  

     

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> ComboPooledDataSource ds =<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;  

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在静态代码块中创建数据库连接池  </span>

    <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)">{  

        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{  

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通过代码创建C3P0数据库连接池  </span>

            <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">ds = new ComboPooledDataSource(); 

           ds.setDriverClass("com.mysql.jdbc.Driver"); 

           ds.setJdbcUrl("jdbc:mysql://localhost:3306/test"); 

            ds.setUser("root"); 

            ds.setPassword("123456"); 

            ds.setInitialPoolSize(10); 

            ds.setMinPoolSize(5); 

            ds.setMaxPoolSize(20);</span><span style="color: rgba(0, 128, 0, 1)">*/</span>  

             

            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通过读取C3P0的xml配置文件创建数据源,C3P0的xml配置文件c3p0-config.xml必须放在src目录下  

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ds = newComboPooledDataSource();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用C3P0的默认配置来创建数据源  </span>
ds = newComboPooledDataSource("MySQL");//使用 C3P0 的命名配置来创建数据源
        }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {  

            </span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> newExceptionInInitializerError(e);  

        }  

    }  

     

   </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从数据源中获取数据库连接  </span>

    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Connection getConnection()<span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> SQLException{  

        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从数据源中获取数据库连接  </span>

        <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ds.getConnection();  

    }  

     

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">释放链接  </span>

    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> release(Connection conn){  

        

        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(conn!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){  

            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{  

                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">将Connection连接对象还给数据库连接池  </span>
conn.close();
            }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {  

                e.printStackTrace();  

            }  

        }  

    }  

}  </span></pre>
View Code

 

步骤 3:在应用中获取连接

    Connection conn = null;  
PreparedStatement st </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;  

ResultSet rs </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;  

</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{  

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取数据库连接  </span>
conn = JdbcUtils_C3P0.getConnection();
    ……  

}</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {  

    e.printStackTrace();  

}</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">{  

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">释放资源  </span>
JdbcUtils_C3P0release(conn);
}  </span></pre>
View Code

6、其他连接池

 此外,还有其他的连接池可供选择,比如使用比较广泛的Proxool。Proxool 是一种 Java 数据库连接池技术。是 sourceforge 下的一个开源项目,这个项目提供一个健壮、易用的连接池,最为关键的是这个连接池提供监控的功能,方便易用,便于发现连接泄漏的情况。proxool 和 c3p0 能够更好的支持高并发,但是在稳定性方面略逊于 dpcp。可根据项目的实际需要来选择连接池。