数据库连接池简单介绍和 C3P0的JDBC配置

前面一节我们介绍了怎样利用jdbc连接数据库,已经实现了数据库的连接,可是在实际的项目开发中,能够发现基本上都使用了数据库连接池技术。为什么要使用数据库连接池呢?根源在于对数据库连接的低效管理

答: 普通的JDBC数据库连接,用户请求一次查询的时候就会向数据库发起一次连接。运行完后就断开连接,这种方式会消耗大量的资源和时间。数据库的连接资源并没有得到非常好的重复利用。

若是同一时候有几百人甚至几千人在线。频繁地进行数据库连接操作,这将会占用非常多的系统资源,严重的甚至会造成server的奔溃。这样频繁的创建销毁数据库连接十分耗费时间和资源,并且开发人员也不能非常好的控制数据库的连接数。有可能由于分配的连接过多而导致内存耗尽。

数据库连接池的实现原理解析,以及设计连接池时须要考虑的因素

  1. 并发问题

    首先必须考虑多线程的环境。 能够使用synchronized关键字,lock等就可以确保线程是同步的,public synchronized Connection getConnection()

  2. 多数据库server和多用户

    设计一个符合单例模式的连接池管理类。在连接池管理类的唯一实例被创建时读取一个资源文件。当中资源文件里存放着多个数据库的url地址等信息。

    依据资源文件提供的信息,创建多个连接池类的实例,每个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字。通过不同的名字来管理不同的连接池。

    对于同一个数据库有多个用户使用不同的名称和密码訪问的情况,也能够通过资源文件处理,即在资源文件里设置多个具有同样url地址,但具有不同username与password的数据库连接信息。

  3. 事务处理

    Connection类本身提供了对事务的支持。能够通过设置connection的autocommit属性为false 然后显式的调用commit或rollback方法来实现。

      try{
          connect.setAutoCommit(false);
          ........ 进行的数据库操作语句
          connect.commit();
      }catch{
          connect.rollback();
      }finally{
         connect.close();
      }

可是当2个线程共用一个连接Connection对象,并且各自都有自己的事务要处理时候。对于连接池是一个非常头疼的问题,由于即使Connection类提供了对应的事务支持。可是我们仍然不能确定那个数据库操作是对应那个事务的。这是由于我们有2个线程都在进行事务操作而引起的。但要高效的进行Connection复用,就必须提供对应的事务支持机制。

可採用每个事务独占一个连接来实现,尽管这个方案有点浪费连接池资源。可是能够大大减少事务管理的复杂性。

4. 连接池的分配与释放

合理的分配与释放。能够提高连接的复用度,从而减少建立新连接的开销。同一时候还能够加快用户的訪问速度。

对于连接的管理可使用空暇池

即把已经创建但尚未分配出去的连接按创建时间存放到一个空暇池中。每当用户请求一个连接时,系统首先检查空暇池内有没有空暇连接。假设有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的推断,假设可用就分配给用户,如不可用就把这个连接从空暇池删掉,又一次检測空暇池是否还有连接)。假设没有则检查当前所开连接池是否达到连接池所同意的最大连接数(maxconn)假设没有达到,就新建一个连接,假设已经达到,就等待一定的时间(timeout)。假设在等待的时间内有连接被释放出来就能够把这个连接分配给等待的用户,假设等待时间超过预定时间timeout 则返回空值(null)。系统对已经分配出去正在使用的连接仅仅做计数,当使用完后再返还给空暇池,可是会发生无法对正在使用的连接进行管理的状况,所以建议使用一个链表存储。

对于空暇连接的状态,可开辟专门的线程定时检測,这样会花费一定的系统开销,但能够保证较快的响应速度。也可採取不开辟专门线程,仅仅是在分配前检測的方法

再分配、释放策略对于有效复用连接非常重要,引用记数模式在复用资源方面用的非常广泛,每个数据库连接,保留一个引用记数,用来记录该连接的使用者的个数,我们对Connection类进行进一步包装来实现引用记数,确定当前被引用多少。详细是哪个用户引用了该连接将在连接池中登记,一旦一个连接被分配出去。那么就会对该连接的申请者进行登记,并且添加引用记数,当被释放回来时候就删除他已经登记的信息,同一时候减少一次引用记数

5、连接池的配置与维护

连接池中究竟应该放置多少连接,才干使系统的性能最佳?系统可採取设置最小连接数(minconn)和最大连接数(maxconn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。假设创建过多。则系统启动就慢,但创建后系统的响应速度会非常快;假设创建过少。则系统启动的非常快。响应起来却慢。这样。能够在开发时。设置较小的最小连接数。开发起来会快,而在系统实际使用时设置较大的,由于这样对訪问客户来说速度会快些。最大连接数是连接池中同意连接的最大数目,详细设置多少。要看系统的訪问量。可通过重复測试。找到最佳点。

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

自己实现一个简易的数据库连接池。仅仅考虑了连接池的一些方面

// 连接池类

我在设计的时候须要考虑的几点

1. 首先是数据库连接的存储,要能非常easy的管理和获取数据库连接。将数据库连接分为两部分。一部分是空暇池,一部分是正在使用的数据库连接使用LinkedList 实现栈来存储空暇的数据库连接,(优势在于每一次获取到的连接都是新的连接。这种连接基本上都是可用的,基本上不会发生连接不可用导致又一次再去获取连接的操作), 使用LinkedList 实现队列来存储正在使用中数据库连接(优势在于,队列的头部就是眼下使用时间最长的连接,方便进行检查,回收这个使用时间超过限制的数据库连接)

2. 怎样回收分配出去的连接,即当外部的连接调用了close方法之后。怎样让它返回到数据库连接池中。而不是销毁?

方法: 使用动态代理, 当请求一个Connection 时,返回用户一个代理的Connection 对象。这样就能够对close方法进行拦截。调用了close方法。会自己主动运行代理类中的invoke方法, 在invoke方法里面就能够实现对实际连接的一些操作了。 详细实现请查看 getConnection() 方法。

3. 事实上获取连接的时候应当首先检查空暇池是否有空暇连接再检查空暇连接是否可用当数据库连接池没有连接的时候,要进行一次性创建新的连接,同一时候要进行检查看能否进行连接的创建,是否达到了最大值等, 所以数据库的一些配置属性须要在静态代码块中通过Properties类读取出来。

public class MyDatabasePool {

    private LinkedList<Connection> idlelist; // 使用LinkedList实现栈存储数据库连接,存放的空暇连接
    private LinkedList<Connection> usinglist; // 使用LinkedList实现队列存储数据库连接,存放的正在使用的连接
    private static Properties props; // 读取配置文件信息
    private static int initialPoolSize; // 初始连接池大小
    private static int maxPoolSize; // 连接池最大连接数
    private static int acquireIncrement; // 无连接时。一次性创建连接数
    static {
        props = new Properties();
        try {
            props.load(new FileInputStream("myPool.properties"));
            initialPoolSize = Integer.parseInt(props
                    .getProperty("initialPoolSize"));
            maxPoolSize = Integer.parseInt(props.getProperty("maxPoolSize"));
            acquireIncrement = Integer.parseInt(props
                    .getProperty("acquireIncrement"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // 构造函数,在数据库连接池里先创建几个连接
    // 我看了一下c3p0的源代码,里面是用的代理连接 new 。而不是真实的物理连接
    public MyDatabasePool() throws ClassNotFoundException, SQLException {
        idlelist = new LinkedList<Connection>();
        usinglist = new LinkedList<Connection>();
        Class.forName(props.getProperty("MySQLdriverClass"));
        for (int i = 0; i < initialPoolSize; i++) {
            Connection conn = DriverManager.getConnection(
                    props.getProperty("MySQLurl"),
                    props.getProperty("MySQLusername"),
                    props.getProperty("MySQLpassword"));
            idlelist.addLast(conn);
        }
    }

    // 获取数据库连接
    public Connection getConnection() throws SQLException {
        if (idlelist.size() > 0) {
            usinglist.addFirst(idlelist.getLast()); // 仅仅是获取第一个连接并没有删除
            Connection conn = idlelist.removeLast(); // 获取第一个连接并删除
            // return conn; //返回真实的物理连接

            // 返回一个真实物理连接的动态代理连接对象
            return (Connection) Proxy.newProxyInstance(ProxyConnection.class
                    .getClassLoader(), new Class<?>[] { Connection.class },
                    new ProxyConnection(conn));
        } else {
            // 创建新的数据库连接
            boolean flag = dynamicIncrement();
            if (flag) {
                usinglist.add(idlelist.getLast()); // 仅仅是获取第一个连接并没有删除
                Connection conn = idlelist.removeLast(); // 获取第一个连接并删除
                // return conn; //返回真实的物理连接

                // 返回一个真实物理连接的动态代理连接对象
                return (Connection) Proxy.newProxyInstance(
                        ProxyConnection.class.getClassLoader(),
                        new Class[] { Connection.class }, new ProxyConnection(
                                conn));
            } else {
                throw new SQLException("没连接了");
            }
        }
    }

    // 连接池里无连接,动态增长
    private boolean dynamicIncrement() throws SQLException {
        int num = idlelist.size() + usinglist.size();
        int num2 = maxPoolSize - num;
        // 假设能够创建连接,并且创建的连接数就是acquireIncrement
        if (num2 >= acquireIncrement) {
            for (int i = 0; i < acquireIncrement; i++) {
                Connection conn = DriverManager.getConnection(
                        props.getProperty("MySQLurl"),
                        props.getProperty("MySQLusername"),
                        props.getProperty("MySQLpassword"));
                idlelist.addLast(conn);
            }
            return true;
        }
        // 假设能够创建连接,可是创建的连接数仅仅能是num2个
        if (num2 > 0) {
            for (int i = 0; i < num2; i++) {
                Connection conn = DriverManager.getConnection(
                        props.getProperty("MySQLurl"),
                        props.getProperty("MySQLusername"),
                        props.getProperty("MySQLpassword"));
                idlelist.addLast(conn);
            }
            return true;
        }
        return false;
    }

    // Connection的动态代理类
    class ProxyConnection implements InvocationHandler {
        private Connection conn;
        public ProxyConnection(Connection conn) {
            this.conn = conn;
        }
        // 关闭数据库连接,放回到空暇池中
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            // TODO Auto-generated method stub
            // 分配出去的代理连接调用了close方法,进行拦截,实现我们自己想要的操作
            if (method.getName().equals("close")) {
                // conn.close(); // 这一句的话就直接关闭连接了,所以不写
                // 应该事先的操作是将 conn 放到空暇池中去,从使用池中移除
                System.out.println(idlelist.size());
                System.out.println(usinglist.size());
                idlelist.addLast(conn);
                usinglist.remove(conn);
                System.out.println(idlelist.size());
                System.out.println(usinglist.size());
                return null;
            }
            // 其它方法仍然调用真实对象的方法
            return method.invoke(conn, args);
        }
    }
}

配置文件 myPool.properties

# mysql database driver
MySQLdriverClass=com.mysql.jdbc.Driver
MySQLurl=jdbc:mysql://127.0.0.1/test?useSSL=false
MySQLusername=root
MySQLpassword=root
initialPoolSize=3
minPoolSize=2
maxPoolSize=50
acquireIncrement=3

JDBC的API中没有提供连接池的方法,所以能够使用例如以下常见的几种数据库连接池:

C3P0

C3P0是一个开源的JDBC连接池,支持JDBC3规范和JDBC2的标准扩展。

c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完毕。扩展这些操作能够有效的提升性能。眼下使用它的开源项目有Hibernate,Spring等c3p0有自己主动回收空暇连接功能。稳定性好,大并发量的压力下稳定性也有一定的保证 无连接池监控

c3p0所需jar:

c3p0-0.9.2.1.jar

mchange-commons-java-0.2.3.4.jar

DBCP

是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件,连接池的基本功能都有,一般不建议使用,无连接池监控

使用dbcp须要2个包:

commons-dbcp.jar

commons-pool.jar

Proxool

Proxool是一种Java数据库连接池技术。Sourceforge下的一个开源项目,这个项目提供一个健壮、易用的连接池,最为关键的是这个连接池提供监控数据库连接的功能,方便易用,便于发现连接泄漏的情况。

Druid

Druid是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和SQL解析器组成。

该项目主要是为了扩展JDBC的一些限制,能够让程序猿实现一些特殊的需求,比方向密钥服务请求凭证、统计SQL信息、SQL性能收集、SQL注入检查、SQL翻译等。程序猿能够通过定制来实现自己须要的功能。

利用C3PO进行配置实现数据库连接池的使用

第一步: 导入jar包 c3p0-0.9.2.1.jar 和 mchange-commons-java-0.2.3.4.jar

第二步: 书写配置文件 c3p0-config.xml; 里面有一个參数是须要注意的。能够详细看看以下的配置文件

注意的是:

1. 文件名称必须为c3p0-config.xml, 这是由于C3P0会默认读取文件名称为c3p0-config.xml的配置文件进而对数据库连接池进行配置。

2. c3p0-config.xml 必须和你写的java代码在同一个文件夹下,一般就是放在项目的 src文件夹下

<?

xml version="1.0" encoding="utf-8"?

>
<c3p0-config>
 <!-- c3p0也能够指定配置文件。并且配置文件能够是properties,也可骒xml的。
 当然xml的高级一些了。

可是c3p0的配置文件名称必须为c3p0-config.xml。
 并且必须放在类路径下 -->

 <!--  默认的配置这里我们默认使用mysql数据库 -->
  <default-config>
    <!--  设置数据库的驱动,url, 用户名, 密码 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://127.0.0.1/test?useSSL=false</property>
    <property name="user">root</property>
    <property name="password">root</property>
     <!--  建立连接池时初始分配的连接池数 = 3-->
    <property name="initialPoolSize">3</property>

     <!--  连接池中的最少连接数 = 2 -->
    <property name="minPoolSize">2</property>

     <!--  连接池中的最大连接数 = 50-->
    <property name="maxPoolSize">50</property>

    <!--  当连接池中连接耗尽时再一次新生成多少个连接 Default: 3 -->
    <property name="acquireIncrement">3</property>

     <!--  最大空暇时间,超过多长时间连接自己主动销毁,秒为单位。默觉得0。即永远不会自己主动销毁  -->
    <property name="maxIdleTime">1800</property> 

    <!--每60秒检查全部连接池中的空暇连接。Default: 0 -->
 <property name="idleConnectionTestPeriod">60</property>

    <!--  c3p0还能够为某个用户设置单独的连接数-->
    <user-overrides user="test-user">
      <property name="maxPoolSize">10</property>
      <property name="minPoolSize">1</property>
      <property name="maxStatements">0</property>
    </user-overrides>
  </default-config>

    <!-- c3p0的配置文件里能够配置多个数据库连接信息。能够给每个配置起个名字。这样能够方便的通过配置名称来切换配置信息 -->
  <!-- 名字为Oracle-config的配置 -->
  <named-config name="Oracle-config">
    <property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
    <property name="jdbcUrl">jdbc:oracle:thin:@localhost:1521:test</property>
    <property name="user">scott</property>
    <property name="password">tiger</property>
  </named-config>

</c3p0-config>

第三步: 能够自己创建一个工具类。从数据库的连接池中获取连接,我这里仅仅是写了一个建议的连接池工具类,当然你能够依据自己的须要进行扩展

import java.sql.Connection;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;

// 数据库连接池的工具类
public final class PoolUtil {
    private static ComboPooledDataSource ds = null;
    static {
        // 两种创建数据库连接池的办法
        // 第一种: 使用配置文件里的默认配置<default-config>
        ds = new ComboPooledDataSource();

        // 另外一种: 使用配置文件里设置的其它配置名字的配置 name-config
        // ds = new ComboPooledDataSource("Oracle-config");

        // 第三种: 我们能够显式的在程序中进行设置数据库连接池的信息
        // ds.setDriverClass("com.mysql.jdbc.Driver");
        // ds.setJdbcUrl("jdbc:mysql://127.0.0.1/test?useSSL=false");
        // ds.setUser("root");
        // ds.setPassword("root");
    }
    // 获取数据库的连接
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
}

第四步 :进行数据库连接池的測试,观測是否成功使用了连接池

在这里须要注意的一点,当你在程序里使用完数据库连接之后,必须显示的调用close()方法, 此时的close语句并不会关闭与数据库的TCP连接,而是将连接归还回到连接池中去。变为空暇状态, 假设不close掉的话,这个连接将会一直被占用

public class PoolTest {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        try {
            conn = PoolUtil.getConnection();
        } catch (SQLException e) {
            System.out.println("未获取数据库连接");
            e.printStackTrace();
        }
        String sql = "select * from user where id = ?";
        PreparedStatement prep = null;
        prep = (PreparedStatement) conn.prepareStatement(sql);
        prep.setInt(1, 1);
        // 查询sql 语句, 返回一个结果集
        ResultSet result = prep.executeQuery();
        // 处理结果集, 释放资源
        while (result.next()) {
            System.out.println(result.getInt("id"));
            System.out.println(result.getString("name"));
            System.out.println(result.getInt("age"));
            System.out.println(result.getString("salary"));
        }
        // 注意的是。即使使用了数据库连接池之后。这里也必须显式的调用close语句,
        // 此时的close语句并不会关闭与数据库的TCP连接。而是将连接归还回到池中去,变为空暇状态
        // 假设不close掉的话。这个连接将会一直被占用
        result.close();
        prep.close();
        conn.close();
    }
}

C3P0的源代码的一些关键解析:

几个关键的类:

C3P0PooledConnectionPoolManager是连接池的管理类,

C3P0PooledConnectionPool是连接池类,

BasicResourcePool是真正管理数据库连接池的类

获取一个连接的代码:

public Connection getConnection() throws SQLException
    {
        PooledConnection pc = getPoolManager().getPool().checkoutPooledConnection();
        return pc.getConnection();
    }

public Object checkoutResource(long timeout)

1) 关键步骤代码:Object resc = prelimCheckoutResource(timeout);

查看池中是否有未使用的connection,有就返回(还要推断是否空暇、是否过期);没有,假设没有达到最大数,就生成一个。或者就等待

2) 关键步骤代码:

boolean refurb = attemptRefurbishResourceOnCheckout (resc);

得到连接后,检測连接的可用性。

3) 连接可用,接着推断连接是否处于管理中。不在就再调用本方法获取一个。在就返回本连接

C3P0**从连接池拿到的连接都是代理的连接。一个对PooledConnection类型对象的代理对象,所以能够放心调用close方法。仅仅是连接进行了归还。不会关闭物理连接 并且C3p0中实际创建的对象是实现了PooledConnection(接口,位于javax.sql)它本身包括Connection,和这个connection相关的全部Statement,Result,能够实现对连接的一些管理。加入监听器等。 所做的全部数据库操作,都被PooledConnection所管理。

**c3p0默认的实现是NewPooledConnection

C3P0使用了LinkedList来存放空暇池中的连接,每次取连接的时候是get(0), 然后remove(0) 应该是使用的队列来实现的空暇池

C3P0 使用的HashMap 来存放的正在使用的连接,这样方便进行查找,连接返回的时候,依据连接能够高速的定位到要remove的那个连接

C3P0 使用HashSet来存储一些失效的,可是仍旧被使用或者检查的资源。

这些数据结构能够在 BasicResourcePool 类中查看到

本博客參考了

http://blog.csdn.net/shuaihj/article/details/14223015

时间: 2024-10-25 07:39:15

数据库连接池简单介绍和 C3P0的JDBC配置的相关文章

数据库连接池php-cp介绍

php-cp(php-connect-pool)是用php扩展写的一个数据库连接池. 我们知道php开发速度快,适合创业快速迭代,但当流量大了之后,php大量的短连接给db层造成多余的消耗,而php处理请求过程中连接会一直持有再加上进程之间不能共享tcp连接会导致撑高mysql的连接,mysql的性能会随着连接数的升高而急速下降,所以很多大公司都强转java,这很大一部分原因是php没有连接池!当然你可以用开源的数据库中间件来缓解这个问题,但是本项目和现有的开源产品有以下几点不同.一.它不同于市

01_数据库连接池,数据源,ResultSetMetaData,jdbc优化

 一.数据库连接池 1. 什么是连接池 传统的开发模式下,Servlet处理用户的请求,找Dao查询数据,dao会创建与数据库之间的连接,完成数据查询后会关闭数据库的链接. 这样的方式会导致用户每次请求都要向数据库建立链接而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出.宕机. 解决方案就是数据库连接池 连接池就是数据库连接对象的一个缓冲池 我们可以先创建10个数

数据库连接池的使用(c3p0,Druid)

package com.fgy.datasource.c3p0; import com.mchange.v2.c3p0.ComboPooledDataSource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; /** * c3p0的使用 */ public class C3P0Demo { public static void main(String[] args)

IPSec VPN 简单介绍以及站点到站点配置

Vpn的连接模式 1)  传输模式 从数据的发出到接收,中间的传输过程全部是加密的(隐藏) 不保护目标和源IP地址(可见) 截获后可以看见目的IP地址和源IP地址,但是看不见里面的数据 多用于一个局域网内通信 2)  隧道模式 隐藏整个数据包 添加一个新的包头,,封装VPN设备的IP地址信息 截获后,既无法看见数据内容,又无法看到通信双方的地址 多用于,总公司和分公司之间通信 VPN的类型: 1)  站点到站点 通过隧道模式在VPN网关之间保护两个或多个站点之间的流量 对于终端用户来说,在VPN

c3p0数据库连接池使用小结

一.C3P0介绍 C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展.目前使用它的开源项目有hibernate,spring等.c3p0的出现,是为了大大提高应用程序和数据库之间访问效率的. 它的特性: 1.编码的简单易用 2.连接的复用 3.连接的管理 二.使用方法 1.下载最新C3PO包文件,下载地址:https://sourceforge.NET/projects/c3p0/files/ 2.将上面的包文件中lib下的c3p0-xxx

DBCP与C3P0数据库连接池

数据库连接池是做什么的? 学过计算机网络的都知道,在一个内部局域网中.大部分用的都是私有地址,要想和外部 打交道,必须要有相应的合法外部地址相相应.然而内部用户数量巨大.一台机子一个外部IP 是不现实的.这样就有了一种叫做连接池的概念.由于不是每个用户都要同一时候上网.当一个 用户须要上网的时候,他就能够从连接池中取得一个外部IP地址,从而对外网进行訪问. 当这 个用户不再须要上网的时候.这一个IP地址被放回连接池中.又能够给其它的用户訪问.这里 的连接池是主要是为了解决IP地址数量问题的.而在

JDBC【数据库连接池、DbUtils框架、分页】

1.数据库连接池 什么是数据库连接池 简单来说:数据库连接池就是提供连接的... 为什么我们要使用数据库连接池 数据库的连接的建立和关闭是非常消耗资源的 频繁地打开.关闭连接造成系统性能低下 编写连接池 编写连接池需实现java.sql.DataSource接口 创建批量的Connection用LinkedList保存[既然是个池,当然用集合保存..LinkedList底层是链表,对增删性能较好] 实现getConnetion(),让getConnection()每次调用,都是在LinkedLi

JAVA JDBC 数据库连接池

1.1 JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤: 在主程序(如servlet.beans)中建立数据库连接 进行sql操作 断开数据库连接 这种模式开发,存在的问题: 普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s-1s的时间).需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接.这样的方式将会消耗大量的资

关于jdbc和数据库连接池的关系(不是封装的关系)

你都说是数据库连接池了.那就是连接数据库用的.JDBC是java封装的对数据库的操作.当然你可以自己进一步封装.数据库连接池是JDBC使用的前提,如果连数据库连接池都没连上,JDBC的操作就谈不上了.而光有数据库连接池也没用啊,你连上了数据库不对其进行操作不是白连了么.所以就需要JDBC了. 一直没有搞清楚,JDBC的数据源与连接池是怎么一样的关系,直到今天做系统的时候,遇到了连接池如果管理有效的连接及资源的占用,释放的问题.    数据源并不等于连接池,它不是必须要求实现连接池的,即连接池是数