用java通过Connection连接数据库时,会消耗时间与IO资源(会消耗IO资源是因为数据库的数据是在硬盘中的,创建连接的话会将Connection对象加载到内存中,使用到IO流)。而在面临大量数据并发访问的时候,就会频繁的连接数据库,很影响效率。
于是数据库连接池应运而生。
官方介绍的是:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。
(1) 程序初始化时创建连接池(集中创建多个数据库连接)
(2) 使用时向连接池申请可用连接
(3) 使用完毕,将连接返还给连接池(返还给池子,而不是关闭连接)
(4) 程序退出时,断开所有连接,并释放资源
连接池节省了大量的数据库连接打开和关闭的动作
#<!-- 连接设置 -->
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#<!-- 最大连接数量 -->
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间(单位毫秒) -->
maxWait=50000
#<!-- 编码方式 -->
connectionProperties=useUnicode=true;characterEncoding=utf8
##<!-- 指定由连接池所创建的连接自动提交 -->
defaultAutoCommit=true
#<!-- 指定由连接池所创建的连接的事务级别 -->
defaultTransactionIsolation=REPEATABLE_READ
package com.etime01;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class DBCPUtil {
private static DataSource dataSource = null;
// 设置静态代码块的目的是为了让数据库连接只进行一次
// 静态代码块会在类被加载的时候第一个被执行,且只执行一次
// 创建数据库连接池
static {
// new一个Properties对象
Properties properties = new Properties();
try {
// 创建类加载器
ClassLoader classLoader = DBCPUtil.class.getClassLoader();
// 加载配置文件
//Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class com.etime01.DB
//切记dbcpconfig.properties要放在src的根目录下
properties.load(classLoader.getResourceAsStream("dbcpconfig.properties"));
// 创建数据源工厂
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
// 抛出一个异常对象
throw new ExceptionInInitializerError("DBCP初始化错误,请检查配置文件");
}
}
// 创建连接
public static Connection getConnection() {
try {
// 获取Connection对象
return dataSource.getConnection();
} catch (SQLException e) {
// 抛出异常
throw new RuntimeException("数据库连接错误");
}
}
// 释放资源
public static void release(Connection connection, Statement statement, ResultSet resultSet) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
connection = null;
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
statement = null;
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
resultSet = null;
}
}
package com.etime01;
public class Student {
private int studentID;
private String studentName;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(int studentID, String studentName) {
super();
this.studentID = studentID;
this.studentName = studentName;
}
@Override
public String toString() {
return "Student [studentID=" + studentID + ", studentName=" + studentName + "]";
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
}
package com.etime01;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestDBCP {
public static void main(String[] args) {
// new一个本类对象出来调用本类方法
TestDBCP demo = new TestDBCP();
demo.testDBCP();
}
private void testDBCP() {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
// 通过DBCPUtil创建连接
connection = DBCPUtil.getConnection();
String sql = "select studentid,studentname from student";
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
while (resultSet.next()) {
int id = resultSet.getInt("studentid");
String name = resultSet.getString("studentname");
Student student = new Student(id, name);
System.out.println(student);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBCPUtil.release(connection, statement, resultSet);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">15</property>
<property name="maxIdleTime">40</property>
<property name="maxPoolSize">150</property>
<property name="minPoolSize">20</property>
</default-config>
</c3p0-config>
package com.etime02;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Util {
// 创建数据库连接池
private static DataSource dataSource = new ComboPooledDataSource();
// 创建连接
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException("获取数据库连接失败");
}
}
// 释放连接
public static void release(Connection connection, Statement statement, ResultSet resultSet) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
connection = null;
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
statement = null;
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
resultSet = null;
}
}
package com.etime02;
public class Student {
private int studentID;
private String studentName;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(int studentID, String studentName) {
super();
this.studentID = studentID;
this.studentName = studentName;
}
@Override
public String toString() {
return "Student [studentID=" + studentID + ", studentName=" + studentName + "]";
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
}
package com.etime02;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestC3P0 {
public static void main(String[] args) {
TestC3P0 demo = new TestC3P0();
demo.testC3P0();
}
public void testC3P0() {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = C3P0Util.getConnection();
String sql = "select studentid,studentname from student";
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
while (resultSet.next()) {
int id = resultSet.getInt("studentid");
String name = resultSet.getString("studentname");
Student student = new Student(id, name);
System.out.println(student);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
C3P0Util.release(connection, statement, resultSet);
}
}
}
1.dbcp没有自动的去回收空闲连接的功能 c3p0有自动回收空闲连接功能
2.两者主要是对数据连接的处理方式不同!C3P0提供最大空闲时间,DBCP提供最大连接数。
3.前者当连接超过最大空闲连接时间时,当前连接就会被断掉。DBCP当连接数超过最大连接数时,所有连接都会被断开