一、概述

  • 在JDBC程序中,每次Java程序与数据库建立连接时,数据库端都要验证用户密码,Java端都要加载connection对象,若有大量的并发访问时,主机的资源消耗非常大,所有需要连接池技术。

  • 数据库连接池负责分配、管理、释放数据库连接。连接池在初始化时会创建一定数量的connection对象存放在连接池中,应用程序访问数据库时,只需向连接池申请一个connection即可,用完归还,连接池再交付其他线程使用。

  • DataSource接口 ,位于javax.sql.DataSource,是连接池的抽象,其实现对象被称为“数据源”(池塘=水源)。

  • DataSource接口等同于JDBC,是应用程序和数据库间的中介,又作为连接池管理connection对象。

  • DataSource接口定义了申请连接的方法:

    • Connection getConnection ()
    • Connection getConnection (String user, String password)
  • DataSource接口有两个常用的接口实现工具:BDCP连接池、C3P0连接池。

    数据库连接池_数据库

二、DBCP连接池

DBCP(DataBase Connection Pool)是Apache组织的开源连接池工具,同时是Tomcat服务器使用的连接池组件。官网Apache基金会

1. 工具包

引入的两个jar包均为版本一,版本二(DBCP2)的用法不一样

  • commons-dbcp-1.4.jar

    ​ 包含了所有使用数据库连接池的方法。

  • commons-pool-1.6.jar

    ​ 是连接池的依赖包,提供方法支持,必须有。

2. 工具类

  1. BasicDataSource类

​ 是DataSource接口的实现类,其实例就是连接池,功能包括连接数据库和操作连接池。

方法 功能
void setDriverClassName (String DriverName) 设置数据库的JDBC驱动
void setUrl (String url) 设置数据库的连接路径
void setUsername (String username) 设置数据库的登录账号
void setPassword (String password) 设置数据库的登录密码
void setInitialSize (int num) 设置连接池初始化时的连接数
void setMaxActive (int num) 限制连接池最大的活跃连接数目
void setMinIdle (int num) 设置连接池最少的闲置连接数目
Connection getConnection () 申请一个连接对象
  1. BasicDataSourceFactory类

    用于以配置文件方式创建BasicDataSource对象,具有一个静态方法:

    • static BasicDataSource createDataSource (Properties prop)

3. 实现示例

  1. 通过BasicDataSource类直接创建连接池

    一般习惯用DataSource原始接口引用连接池,实现工具类只用来创建、初始化和配置连接池,因为使用连接池的功能时原始接口更方便。

    import java.sql.Connection;
    import java.sql.SQLException;
    import org.apache.commons.dbcp.BasicDataSource;
    import java.sql.DatabaseMetaData;
    
    public class Example01 {
    	public static void main(String[] args) {
      	   	DataSource ds = null;   //用原始接口引用连接池
    		try {
    			// 1. 创建DBCP连接池。
    			BasicDataSource bds = new BasicDataSource();
    			// 2. 设置连接数据库的参数
    			bds.setDriverClassName("com.mysql.jdbc.Driver");
    			bds.setUrl("jdbc:mysql://localhost:3306/db_practice?useUnicode=true&characterEncoding=utf-8&useSSL=true");
    			bds.setUsername("root");
    			bds.setPassword("123456");
    			// 3. 设置DBCP连接池的使用参数
    			bds.setInitialSize(5);
    			bds.setMaxActive(10);
    			// 4. 从连接池申请一个连接
                ds = bds;                 //用原始接口引用以配置好的连接池
    			Connection conn = ds.getConnection();
    			// 查看数据库连接的元信息
    			DatabaseMetaData metaData = conn.getMetaData();
    			System.out.println("url: " +metaData.getURL());
    			System.out.println("UserName: " +metaData.getUserName());
    			System.out.println("Driver: " +metaData.getDriverName());
                
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
  2. 以读取配置文件的方式创建连接池

    • 说明

      • 一般习惯用原始接口引用连接池,实现工具类只用来创建、初始化和配置连接池,因为使用连接池的功能时原始接口更方便。
      • “主类名.class"是本类的反射对象,由此可获得本类的类加载器(因为类加载器是对象方法)。
    • 主类

      import java.io.InputStream;
      import java.sql.Connection;
      import java.util.Properties;
      import javax.sql.DataSource;
      import org.apache.commons.dbcp.BasicDataSourceFactory;
      import java.sql.DatabaseMetaData;
      
      public class Example02 {
      	public static void main(String[] args) {	
      		DataSource ds = null;
      		Properties prop = new Properties();	
      		try {
      			// 1. 使用本类的类加载器读取配置文件作为输入流
      			InputStream in = Example02.class.getClassLoader().getResourceAsStream("dbcpConfig.properties");
      			// 2. 配置器加载文件流获得配置参数
      			prop.load(in);
      			// 3. 连接池工厂根据配置器的参数创建连接池
      			ds = BasicDataSourceFactory.createDataSource(prop);
      			// 4. 向连接池申请连接
      			Connection conn = ds.getConnection();
      			// 查看数据库连接的元信息
      			DatabaseMetaData metaData = conn.getMetaData();
      			System.out.println("url: " +metaData.getURL());
      			System.out.println("UserName: " +metaData.getUserName());
      			System.out.println("Driver: " +metaData.getDriverName());
                  
      		} catch (Exception e) {
      			e.printStackTrace();
      		}	
      	}
      }
      
    • 配置文件

      说明:本示例的配置文件dbcpConfig.properties放在src目录下

      # 连接数据库的参数
      driverClassName = com.mysql.jdbc.Driver
      url=jdbc:mysql://localhost:3306/db_practice?useUnicode=true&characterEncoding=utf-8&useSSL=true
      username=root
      password=123456
      # 连接池的使用参数
      initialSize=5
      maxActive=10
      maxIdle=10
      

三、C3P0连接池

C3P0是目前最流行的连接池之一,支持JDBC2和JDBC3标准,易于扩展且性能优越,Hibernate和Spring等框架都支持该连接池。

1. 工具包

  • c3p0-0.9.2.1.jar
  • mchange-common-java.0.2.3.4.jar

mchange-commons.java.jar包是c3p0连接池的依赖包,如果没有这个包,会无定义异常报警ClassNotFoundException,这个依赖包是c3p0-0.9.2版本后才分离出来的包,0.9.1版本之前的话只需一个c3p0.jar包即可。

2. ComboPooledDataSource工具类

是DataSource接口的实现类,其实例就是连接池,功能包括连接数据库,初始化和配置连接池参数,且可通过配置文件来创建连接池。

  1. 构造器

    • ComboPooledDataSource()

      ​ 无参构成时需要手动配置连接池参数。

    • ComboPooledDataSource(Sting configName)

      • 有参构成时,构造器会自动配置文件,可以是c3p0-config.xml 或者 c3p0.properties。
      • 参数是xml文件中的自定义配置名称。
      • .properties文件只能配置默认参数,不能配置自定义参数。
      • 构造器读取的路径和文件名是固定的,配置文件必须放在src目录下,且文件名不能改。
  2. 对象方法

    ​ 主要是设置数据库连接的方法和连接池初始化的方法。

    方法 功能
    void setDriverClass (String DriverName) 设置数据库的JDBC驱动
    void setJdbcUrl (String url) 设置数据库的连接路径
    void setUser (String username) 设置数据库的登录账号
    void setPassword (String password) 设置数据库的登录密码
    void setInitialPoolSize (int num) 设置连接池初始化时的连接数
    void setMaxPoolSize (int num) 限制连接池最大的活跃连接数目
    void setMinIdle (int num) 设置连接池最少的闲置连接数目
    Connection getConnection () 申请一个连接对象

3. 实现示例

  1. 无参构造连接池,手动设置参数

    ​ 一般习惯用DataSource原始接口引用连接池,实现工具类只用来创建、初始化和配置连接池,因为使用连接池的功能时原始接口更方便。

    import java.sql.Connection;
    import javax.sql.DataSource;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class Example01 {
    	public static void main(String[] args) {	
    		DataSource ds = null;         //用原始接口引用连接池
    		try {
                // 1. 无参构成连接池
                ComboPooledDataSource cpds = new ComboPooledDataSource();
                // 2. 手动设置参数
    			cpds.setDriverClass("com.mysql.jdbc.Driver");
    			cpds.setJdbcUrl("jdbc:mysql://localhost:3306/db_practice?useUnicode=true&characterEncoding=utf-8&useSSL=true");
    			cpds.setUser("root");
    			cpds.setPassword("123456");
    			cpds.setInitialPoolSize(5);
    			cpds.setMaxPoolSize(15);
                // 3. 向连接池申请连接
    			ds = cpds;                  
    			Connection conn = ds.getConnection();
    			System.out.println("连接信息:" +conn);
    		
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
  2. 以读取配置文件的方式创建连接池

    • 主类

      import java.sql.Connection;
      import java.sql.SQLException;
      import javax.sql.DataSource;
      import com.mchange.v2.c3p0.ComboPooledDataSource;
      
      public class Example02 {
      	public static void main(String[] args) {
      		DataSource ds = null;
      		try {
                  
      			ComboPooledDataSource cpds = new ComboPooledDataSource("config02");
      			ds = cpds;
      			Connection conn = ds.getConnection();
      			System.out.println("连接信息:" +conn);
                  
      		} catch (SQLException e) {
      			e.printStackTrace();
      		}
      	}
      }
      
    • 以xml文件配置

      • xml文件中分为默认配置和自定义配置,当没有指定配置名或找不到指定配置名时,自动使用默认配置。
      • 这种配置的好处是方便更换连接池配置。
      <?xml version="1.0" encoding="utf-8" standalone="yes"?>
      <c3p0-config>
      	<!-- 默认配置 -->
      	<default-config>
      		<!-- 默认连接数据库配置 -->
      		<property name="driverClass">com.mysql.jdbc.Driver</property>
      		<property name="jdbcUrl">
      			jdbc:mysql://localhost:3306/db_practice?useSSL=true
      		</property>
      		<property name="user">root</property>
      		<property name="password">123456</property>
      		<!-- 默认线程池使用配置 -->
      		<property name="checkoutTimeout">30000</property>
      		<property name="initialPoolSize">10</property>
      		<property name="maxIdleTime">30</property>
      		<property name="maxPoolSize">100</property>
      		<property name="minPoolSize">10</property>
      		<property name="maxStatements">200</property>
      	</default-config>
      	
      	<!-- 自定义配置 -->
      	<named-config name="config02">
      		<!-- 连接数据库配置 -->
      		<property name="driverClass">com.mysql.jdbc.Driver</property>
      		<property name="jdbcUrl">
      			jdbc:mysql://localhost:3306/db_practice?useSSL=true
      		</property>
      		<property name="user">root</property>
      		<property name="password">123456</property>
      		<!-- 自定义线程池使用配置 -->
      		<property name="initialPoolSize">5</property>
      		<property name="maxIdleTime">15</property>
      		<property name="maxPoolSize">15</property>
      	</named-config>
      </c3p0-config>
      
    • 以properties文件配置

      ​ 这种方法只能配置初始化时的默认参数,无需指定配置名

      # 连接数据库的参数
      c3p0.driverClass=com.mysql.jdbc.Driver  
      c3p0.jdbcUrl=jdbc:mysql://localhost:3306/jdbc  
      c3p0.user=root  
      c3p0.password=lovejava  
      #-------------------------------  
      #连接池初始化时创建的连接数  
      c3p0.initialPoolSize=3  
      #连接池保持的最小连接数  
      c3p0.minPoolSize=3  
      #连接池在无空闲连接可用时一次性创建的新数据库连接数,default:3  
      c3p0.acquireIncrement=3  
      #连接池中拥有的最大连接数,如果获得新连接时会使连接总数超过这个值则不会再获取新连接,而是等待其他连接释放,所以这个值有可能会设计地很大,default : 15  
      c3p0.maxPoolSize=15  
      #连接的最大空闲时间,如果超过这个时间,某个数据库连接还没有被使用,则会断开掉这个连接,单位秒  
      c3p0.maxIdleTime=100  
      #连接池在获得新连接失败时重试的次数,如果小于等于0则无限重试直至连接获得成功  
      c3p0.acquireRetryAttempts=30  
      #连接池在获得新连接时的间隔时间  
      c3p0.acquireRetryDelay=1000