1.1、数据库的由来
用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。
如下图所示:
数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正式针对这个问题提出来的。数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
如下图所示:
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中, 这些数据库连接的数量是由最小数据库连接数来设定的.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。当一个连接用close()方法关闭时,并不是真正的关闭连接,而是将连接还给连接池等待下一次被连接。
1.2、数据库连接池的最小连接数和最大连接数的设置要考虑到以下几个因素:
1.最小连接数(MinActive):是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费。
2.最大连接数(MaxActive):是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作。
3.如果最小连接数与最大连接数相差很大:那么最先连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接.不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,他将被放到连接池中等待重复使用或是空间超时后被释放。
二、dbcp数据库连接池
2.1、dbcp简介
dbcp是Apache软件基金组织下的开源连接池实现,要使用dbcp数据源,需要应用程序应在系统中增加一下三个jar文件:
commons-dbcp2-2.2.0.jar
commons-pool2-2.5.0.jar
commons-logging-1.2.jar
2.2、通过一个例子来了解dbcp的基本操作
DbcpUtil 类:用来封装连接池的对象和获取连接的方法
Dbcp_test 类:用来测试DbcpUtil类
代码:
package dbcp_demo2;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbcp2.BasicDataSource;
public class DbcpUtil {
private static String driverName="com.mysql.cj.jdbc.Driver";
private static String url="jdbc:mysql://localhost:3306/demo1?useSSL=false";
private static String userName="root";
private static String password="123";
private static BasicDataSource datasource=new BasicDataSource();//获取基本数据源,可以理解为未配置的连接池
static {
//必须要配置的四大参数信息
datasource.setDriverClassName(driverName);
datasource.setUrl(url);
datasource.setUsername(userName);
datasource.setPassword(password);
//配置扩展信息
datasource.setInitialSize(10);//当连接池被开启时,连接池中初始创建的连接为10个
datasource.setMaxTotal(20);//在同一时间内连接池最多可分配的连接数量为20个
datasource.setMaxIdle(15);//最大有15个连接可以被闲置在连接池中
datasource.setMinIdle(3);//最小有3个连接池可以被闲置在连接池中
datasource.setMaxWaitMillis(1000);//当在同一时间内,连接超过了连接池最多分配的连接数量,请求的连接最多要等待1000毫秒,超过1000毫秒后就会抛出异常
}
//获取连接池对象的方法
public BasicDataSource getDataSource() {
return datasource;
}
//获取从连接池得到连接的方法
public Connection getConnection() throws SQLException {
return datasource.getConnection();
}
}
package dbcp_demo2;
import java.sql.Connection;
import java.sql.SQLException;
public class Dbcp_test {
public static void main(String[] args) throws SQLException {
DbcpUtil util=new DbcpUtil();//创造DbcpUtil类的对象
Connection con=util.getConnection();//获取连接
System.out.println(con.getCatalog());//打印出连接的数据库名
con.close(); //将连接还给连接池
}
}
三、c3p0数据库连接池
3.1、c3p0简介
c3p0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。
- dbcp没有自动回收空闲连接的功能
- c3p0有自动回收空闲连接功能
3.3、通过一个例子了解c3p0的基本操作
c3p0-config.xml :c3p0的配置文件
C3p0Util 类:用来封装连接池的对象和获取连接的方法
C3p0_test 类:用来测试C3p0Util 类
说明:c3p0有三种配置方法,我这里是用xml配置的。三种具体配置方法请看这篇文章:C3P0连接池的三种实现方式
代码:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="myc3p0xml">
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/demo1?useSSL=false</property>
<property name="user">root</property>
<property name="password">yooneiweiyoonei.</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="maxPoolSize">20</property>
<property name="minPoolSize">3</property>
<property name="maxIdleTime">150</property>
</named-config>
</c3p0-config>
package demo1;
import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0Util {
public static ComboPooledDataSource datasource;
static {
datasource=new ComboPooledDataSource("myc3p0xml");
}
//获取连接池的方法
public ComboPooledDataSource getDatasource() {
return C3p0Util.datasource;
}
//获取连接池连接的方法
public Connection getConnection() throws SQLException {
return datasource.getConnection();
}
}
package demo1;
import java.sql.Connection;
import java.sql.SQLException;
public class C3p0_test {
public static void main(String[] args) throws SQLException {
C3p0Util c3p0=new C3p0Util();
Connection con=c3p0.getConnection();
System.out.print(con.getCatalog());
con.close();
}
}