一、概念

官方:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。

二、原理

传统统链接:
一般来说,Java应用程序访问数据库的过程是:
(1)装载数据库驱动程序;
(2)通过JDBC建立数据库连接;
(3)访问数据库,执行SQL语句;
(4)断开数据库连接。

数据库连接池的机制:
(1)程序初始化时创建连接池
(2)使用时向连接池申请可用连接
(3)使用完毕,将连接返还给连接池
(4)程序退出时,断开所有连接,并释放资源

简单介绍连接池的工作原理:
  连接池技术的核心思想是连接复用,连接池的工作原理主要由三部分组成,分别为连接池的建立连接池中连接的使用管理连接池的关闭

三、各种数据库连接池介绍

Java中常用的数据库连接池有:DBCP 、C3P0、BoneCP、Proxool、DDConnectionBroker、DBPool、XAPool、Primrose、SmartPool、MiniConnectionPoolManager及Druid等。
这里只介绍其中几种:

1.DBCP
  dbcp连接池可以设置最大和最小连接,连接等待时间等基本功能。
  具体配置如下:

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/database
username=admin
password=admin

配置参数详解:
注意JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] 
MaxActive:连接池的最大数据库连接数。设为0表示无限制。maxActive是最大激活连接数,这里取值为20,表示同时最多有20个数据库连接。
maxIdle: 连接池中最多可空闲maxIdle个连接,maxIdle是最大的空闲连接数,这里取值为20,表示即使没有数据库连接时依然可以保持20空闲的连接,而不被清除,随时处于待命状态。
minIdle:连接池中最少空闲maxIdle个连接。
initialSize:初始化连接数目。
maxWait:连接池中连接用完时,新的请求等待时间,毫秒 MaxWait是最大等待秒钟数,这里取值-1,表示无限等待,直到超时为止,也可取值9000,表示9秒后超时。
maxIdle:最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。
defaultAutoCommit:指定由连接池所创建的连接的自动提交(auto-commit)状态,取ture/false。
defaultReadOnly:driver default 指定由连接池所创建的连接的只读(read-only)状态。
defaultTransactionIsolation:定由连接池所创建的连接的事务级别(TransactionIsolation),可以是NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=REPEATABLE_READ。
//JdbcTemplate---Spring对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中。
//JdbcTemplate中用到默认连接池就是DBCP
private JdbcTemplate getJdbcTempalte(DoctorMoveDatasource db){
	BasicDataSource dataSource = new BasicDataSource();
	dataSource.setDriverClassName(db.getDriver());
	dataSource.setUrl(db.getUrl());
	dataSource.setUsername(db.getUsername());
	dataSource.setPassword(db.getPassword());
	dataSource.setMaxActive(2);
	dataSource.setMaxIdle(2);
	dataSource.setDefaultAutoCommit(false);
	dataSource.setInitialSize(2);
	dataSource.setTimeBetweenEvictionRunsMillis(600000L);
	dataSource.setMinEvictableIdleTimeMillis(1800000L);
	return new JdbcTemplate(dataSource);
}

拓展:
JdbcTemplate主要提供以下五类方法:
execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
query方法及queryForXXX方法:用于执行查询相关语句;
call方法:用于执行存储过程、函数相关语句。

2.C3P0
  c3p0是另外一个开源的连接池,在业界也是比较有名的,这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。这个连接池的配置参见附件压缩包中的:c3p0.xml。
  使用评价:在具体项目应用中,发现此连接池的持续运行的稳定性相当不错,在大并发量的压力下稳定性也有一定保证,此外不提供连接池监控。
  
(1)C3P0 数据库连接池技术实现步骤

  1. 导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar (注意:因为是连接数据库,不要忘记导入数据库驱动 jar 包)
  2. 定义配置文件:
    名称:c3p0.properties 或 c3p0-config.xml(名字必须为这两个中一个,因为会自动加载配置文件)
    路径:直接将文件放置 src 目录下即可。
  3. 创建核心对象 数据库连接池对象 ComboPooledDataSource
  4. 获取连接:getConnection()

代码实现:

public static void main(String[] args) throws SQLException {
        // 创建数据库连接对象
        DataSource ds = new ComboPooledDataSource();  // 会自动去加载配置文件

        //获取连接对象
        Connection conn = ds.getConnection();

        // 打印连接对象
        System.out.println(conn);

        // 归还对象
        conn.close();
 }

(2)导入的 jar 包
C3P0-0.9.5.2.jar
mchange-commons-java-0.2.12.jar
mysql-connecter-java-5.1.40-bin.jar

(3)配置文件
c3p0-config.xml 配置文件

<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
      <!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/bookstore</property>
    <property name="user">root</property>
    <property name="password">root</property>

    <!-- 连接池参数 -->
    <!--初始化连接的数量-->
    <property name="initialPoolSize">5</property>
    <!--最大的连接数量-->
    <property name="maxPoolSize">10</property>
    <!--超时时间-->
    <property name="checkoutTimeout">3000</property>
  </default-config>

  <!--通过指定的名字来获取连接的数据库-->
  <named-config name="otherc3p0">
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/bookstore</property>
    <property name="user">root</property>
    <property name="password">root</property>

    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">8</property>
    <property name="checkoutTimeout">1000</property>
  </named-config>
</c3p0-config>

注意:在配置文件中可以连接多个不同的数据库,用 声明即可,到时候使用 name 属性来调用即可,如果没有指定 name,那么调用默认的数据库。

public static void main(String[] args) throws SQLException {
        // 创建数据库连接对象
        //DataSource ds = new ComboPooledDataSource("");        //连接默认的数据库
        DataSource ds = new ComboPooledDataSource("otherc3p0"); //连接 name=otherc3p0数据库

        //2 获取连接
        Connection conn = ds.getConnection();

        Statement stmt = conn.createStatement();

        // 3.归还连接
        conn.close();

    }

3.proxool

4.Druid
(1)Druid数据库连接池技术实现步骤

  1. 导入 jar 包druid-1.0.9.jar
  2. 定义配置文件
    名称:是properties 形式的,需要手动加载
    路径:可以放在任意目录下(建议放在src目录下)
  3. 加载配置文件 properties
  4. 获取数据连接池对象:通过工厂来获取 DruidDataSourceFactory
  5. 获取连接:getConnection
  6. 归还连接:close()

代码实现:

public class DruidDemo1 {
    public static void main(String[] args) throws Exception {
        //1.导入jar包
        //2.定义配置文件

        //3.加载配置文件
        Properties prop = new Properties();
        InputStream is = DruidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
        prop.load(is);

        //4.获取连接池对象
        DataSource ds = DruidDataSourceFactory.createDataSource(prop);


        //5.获取连接
        Connection conn = ds.getConnection();
        System.out.println(conn);

        // 6.归还连接
        conn.close();
    }
}

(2)导入的 jar 包
druid-1.0.9.jar

(3)配置文件

druid.properties 文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/bookstore
username=root
password=root
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 延迟时间
maxWait=3000

(4)Druid 连接池的工具类
可以将数据库连接池封装成一个工具类,这样在获取的连接的时候,直接拿来用即可,不用再创建连接池,更加方便。

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * Druid 连接池的工具类
 */
public class JDBCUtils {

    // 1.定义成员变量
    private static DataSource ds;

    static {
        //加载配置文件
        Properties pro = new Properties();
        try {
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            // 2 获取datasource
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取连接
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    /**
     * 释放资源
     */
    public static void close(Statement stmt, Connection conn) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取连接池方法
     */
    public static DataSource getDataSource() {
        return ds;
    }
}