jdbc连接池-DBCP和C3P0

2012/04/17 2147点热度 0人点赞 0条评论

连接池运作原理  

在实际应用开发中,特别是在WEB应用系统中,如果JSP、Servlet或EJB使用JDBC直接访问数据库中的数据,每一次数据访问请求都必须经历建立数据库连接、打开数据库、存取数据和关闭数据库连接等步骤,而连接并打开数据库是一件既消耗资源又费时的工作,如果频繁发生这种数据库操作,系统的性能必然会急剧下降,甚至会导致系统崩溃。数据库连接池技术是解决这个问题最常用的方法,在许多应用程序服务器(例如:Weblogic,WebSphere,JBoss)中,基本都提供了这项技术,无需自己编程,但是,深入了解这项技术是非常必要的。

  数据库连接池技术的思想非常简单,将数据库连接作为对象存储在一个Vector对象中,一旦数据库连接建立后,不同的数据库访问请求就可以共享这些连接,这样,通过复用这些已经建立的数据库连接,可以克服上述缺点,极大地节省系统资源和时间。

  数据库连接池的主要操作如下:

  (1)建立数据库连接池对象(服务器启动)。

  (2)按照事先指定的参数创建初始数量的数据库连接(即:空闲连接数)。

  (3)对于一个数据库访问请求,直接从连接池中得到一个连接。如果数据库连接池对象中没有空闲的连接,且连接数没有达到最大(即:最大活跃连接数),创建一个新的数据库连接。

  (4)存取数据库。

  (5)关闭数据库,释放所有数据库连接(此时的关闭数据库连接,并非真正关闭,而是将其放入空闲队列中。如实际空闲连接数大于初始空闲连接数则释放连接)。

  (6)释放数据库连接池对象(服务器停止、维护期间,释放数据库连接池对象,并释放所有连接)。

连接池的好处  

连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。

  这种把连接“汇集”起来的技术基于这样的一个事实:对于大多数应用程序,当它们正在处理通常需要数毫秒完成的事务时,仅需要能够访问JDBC 连接的 1 个线程。当不处理事务时,这个连接就会闲置。相反,连接池允许闲置的连接被其它需要的线程使用。

  事实上,当一个线程需要用 JDBC 对一个 GBase 或其它数据库操作时,它从池中请求一个连接。当这个线程使用完了这个连接,将它返回到连接池中,这样这就可以被其它想使用它的线程使用。

  当连接从池中“借出”,它被请求它的线程专有地使用。从编程的角度来看,这和用户的线程每当需要一个 JDBC 连接的时候调用DriverManager.getConnection() 是一样的,采用连接池技术,可通过使用新的或已有的连接结束线程。

  连接池可以极大的改善用户的 Java 应用程序的性能,同时减少全部资源的使用。连接池主要的优点有:

  减少连接创建时间

  虽然与其它数据库相比 GBase 提供了较为快速连接功能,但是创建新的 JDBC 连接仍会招致网络和 JDBC 驱动的开销。如果这类连接是“循环”使用的,使用该方式这些花销就可避免。

  简化的编程模式

  当使用连接池时,每一个单独的线程能够像创建了一个自己的 JDBC 连接一样操作,允许用户直接使用JDBC编程技术。

  受控的资源使用

  如果用户不使用连接池,而是每当线程需要时创建一个新的连接,那么用户的应用程序的资源使用会产生非常大的浪费并且可能会导致高负载下的异常发生。

  注意,每个连到 GBase 的连接在客户端和服务器端都有花销(内存,CPU,上下文切换等等)。每个连接均会对应用程序和 GBase 服务器的可用资源带来一定的限制。不管这些连接是否在做有用的工作,仍将使用这些资源中的相当一部分。

  连接池能够使性能最大化,同时还能将资源利用控制在一定的水平之下,如果超过该水平,应用程序将崩溃而不仅仅是变慢。

手动代码创建DBCP连接池

基于properties文件的连接池

jdbc.properties文件内容

username=root   
password=root
url=jdbc:mysql://localhost:3306/test
driverClassName=com.mysql.jdbc.Driver
initialSize=4
minIdle=4
maxIdle=6   
maxActive=10
maxWait=5000

读取资源文件创建连接池

@Test
    public  void  TestConnection{
        try {
            Properties props=new Properties();
            InputStream inputStream=TestConnection.class.getClassLoader().getResourceAsStream("com/yxkong/dbcp/jdbc.properties");
            props.load(inputStream);
            DataSource dataSource=BasicDataSourceFactory.createDataSource(props);
            for(int i=0;i<10;i++){
                System.out.println(dataSource.getConnection());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

直接代码中配置连接池参数

@Test
    public  void test{
        try {
            BasicDataSource ds=new BasicDataSource();
            ds.setUsername("root");
            ds.setPassword("root");
            ds.setUrl("jdbc:mysql://localhost:3306/test");
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setInitialSize(4);//设置初始化连接数
            ds.setMinIdle(4);//设置最小空闲数
            ds.setMaxIdle(6); //设置最大空闲数 
            ds.setMaxActive(10); //设置最大连接数    
            ds.setMaxWait(5000);//设置最大等待时间
            for(int i=0;i<=10;i++){
                System.out.println(ds.getConnection());
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

手动代码创建C3P0连接池

@Test
    public void test {
        try {
            ComboPooledDataSource cpds = new ComboPooledDataSource();
            cpds.setDriverClass("com.mysql.jdbc.Driver");
            cpds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
            cpds.setUser("root");
            cpds.setPassword("root");
            cpds.setInitialPoolSize(4);// 设置初始化连接数
            cpds.setMinPoolSize(5);// 设置的最小的连接数
            cpds.setAcquireIncrement(5);// 设置一次创建的连接数
            cpds.setMaxPoolSize(10);// 设置的最小的连接数
            cpds.setCheckoutTimeout(5000);//设置最大等待时间
            for (int i = 0; i < 11; i++) {
                System.out.println(cpds.getConnection());
            }
                
        }catch (SQLException e) {
            e.printStackTrace();
        }
    }

基于xml的c3p0连接池

c3p0-config.xml文件内容

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 配置默认的 -->
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">root</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
        <property name="checkoutTimeout">5000</property>
        <property name="initialPoolSize">4</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">10</property>
        <property name="minPoolSize">4</property>
    </default-config>
              
    <!-- 程序通过名称来读取配置文件 -->
    <named-config name="yxkong">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">root</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
        <property name="checkoutTimeout">5000</property>
        <property name="initialPoolSize">4</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">20</property>
        <property name="minPoolSize">4</property>
    </named-config>
</c3p0-config>
@Test
    public  void testxml{
        try {
            /*
             * c3p0-config.xml放置src目录下[类路径---classes路径下]
             *  
             *  ComboPooledDataSource cpds = new ComboPooledDataSource();
             *   * 构造方法没有参数,表示读取<default-config>中的信息
             */
            //ComboPooledDataSource cpds = new ComboPooledDataSource();
            ComboPooledDataSource cpds = new ComboPooledDataSource("yxkong");
            for (int i = 0; i < 11; i++) {
                System.out.println(cpds.getConnection());
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

yxkong

这个人很懒,什么都没留下

文章评论