一、简介
C3P0是一JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。使用它的开源项目有Hibernate、Spring等。
c3p0与dbcp区别:
- dbcp没有自动回收空闲连接的功能
- c3p0有自动回收空闲连接功能
数据库连接池的重要性:
当我们在进行基于数据库的web程序开发时,我们可以先在主程序(如Servlet、Bean)中通过JDBC中的DriverManager建立数据库连接,然后将要对数据库进行操作的sql语句封装到Statement中,最后在返回结果集后断开数据库连接。以上是较为传统的开发模式,然而用这种模式开发会埋下严重的安全隐患。
JDBC传统模式开发存在的主要问题:
- 时间和内存资源消耗巨大
普通的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将Connection加载到内存中,再根据JDBC代码(或配置文件)中的用户名和密码进行验证其正确性。这一过程一般会花费0.05~1s,一旦需要数据库连接的时候就必须向数据库请求一个,执行完后再断开连接。显然,如果同一个数据库在同一时间有数十人甚至上百人请求连接势必会占用大量的系统资源,严重的会导致服务器崩溃。
- 有内存泄漏的风险
因为每一次数据库连接使用完后都需要断开连接,但如果程序出现异常致使连接未能及时关闭,这样就可能导致内存泄漏,最终只能以重启数据库的方法来解决;
另外使用传统JDBC模式开发不能控制需要创建的连接数,系统一般会将资源大量分出给连接以防止资源不够用,如果连接数超出一定数量也会有极大的可能导致内存泄漏。
二、导入jar包
提取码:xbb8
三、编码测试
1)编写配置文件
<?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/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true</property>
<property name="user">xxxx</property>
<property name="password">xxxx</property>
<property name="initialPoolSize">5</property>
<property name="maxIdleTime">10</property>
<property name="maxPoolSize">5</property>
<property name="minPoolSize">20</property>
</default-config>
<named-config name="MySQL">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
<property name="user">xxxx</property>
<property name="password">xxxx</property>
<property name="initialPoolSize">5</property>
<property name="maxIdleTime">10</property>
<property name="maxPoolSize">5</property>
<property name="minPoolSize">20</property>
</named-config>
</c3p0-config>
2)改写工具类
import com.jdbc.study04.JdbcUtils;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils_DBCP {
private static BasicDataSource dataSource=null;
static {
try{
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties properties = new Properties();
properties.load(in);
//创建数据源 (工厂模式)
dataSource = BasicDataSourceFactory.createDataSource(properties);
}catch (Exception e){
e.printStackTrace();
}
}
//获取连接 数据源中自带连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3)代码测试
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestC3P0 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement st=null;
try {
conn = JdbcUtils_C3P0.getConnection();
String sql="insert into users(`id`,`NAME`,`PASSWORD`,`email`,`birthday`) value (?,?,?,?,?)";
st=conn.prepareStatement(sql);
st.setInt(1,5);
st.setString(2,"alife");
st.setString(3,"123456");
st.setString(4,"alife@qq.com");
st.setDate(5,new Date(new java.util.Date().getTime()));
int i = st.executeUpdate();
if(i>0){
System.out.println("插入成功");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils_C3P0.release(conn,st,null);
}
}
}
总结:
无论使用什么数据源,本质还是一样的,只要DataSource接口不变,方法就不会变