遇到的问题:c3p0-config.xml 配置文件名一定要正确,且一定要在resources资源文件中,因resources误打成resourses,调了半天bug。
c3p0
简单的说,c3p0就是一个连接池。Java项目涉及数据库的操作的时候,需要编写代码用jdbc驱动来连接数据库,以此来对数据进行操作。但每访问以此数据库都需要建立连接,做完查询,又断开连接,这样带来的时间开销非常大。而c3p0就是建立一个"池子",这个"池子"里存放了很多它已经预先建立好的连接,但要访问数据库的时候,就直接拿一个连接来用就行,用完之后关掉就行。
传统模式开发存在的主要问题
1.时间和内存资源消耗巨大
普通的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将Connection加载到内存中,再根据JDBC代码(或配置文件)中的用户名和密码进行验证其正确性。这一过程一般会花费0.05~1s,一旦需要数据库连接的时候就必须向数据库请求一个,执行完后再断开连接。显然,如果同一个数据库在同一时间有数十人甚至上百人请求连接势必会占用大量的系统资源,严重的会导致服务器崩溃。
2.有内存泄漏的风险
因为每一次数据库连接使用完后都需要断开连接,但如果程序出现异常致使连接未能及时关闭,这样就可能导致内存泄漏,最终只能以重启数据库的方法来解决;
另外使用传统JDBC模式开发不能控制需要创建的连接数,系统一般会将资源大量分出给连接以防止资源不够用,如果连接数超出一定数量也会有极大的可能导致内存泄漏。
数据库连接池优势
数据库连接池的基本原理就是为数据库建立一个缓冲池。在缓冲池中先创建指定数量的数据库连接,当有连接请求时就从缓冲池中取出处于“空闲”状态的连接,并将此连接标记为“忙碌”,直到该请求进程结束后,它所使用的连接才会重新回到“空闲”状态,并等待下一次请求调用。
1.资源的高效利用
由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销,减小了系统资源消耗的同时也提高了系统运行环境的平稳性。
2.更快的系统反应速度
数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接可以避免数据库在连接初始化和释放过程所需的时间开销,从而减少了系统的响应时间,提高了系统的反应速度。
3.减少了资源独占的风险
新的资源分配手段对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置实现对某一应用最大可用数据库连接数的限制,避免了应用独占所有数据库资源的风险。
4.统一的连接管理,避免数据库连接泄露
在实现较为完善的数据库连接池时,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。
resources中创建c3p0-config.xml文件
配置c3p0-config.xml
<?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/jdbc</property>
<property name="user">root</property>
<property name="password">1234</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>
</c3p0-config>
创建工具类JDBCUtils
package jxnuss.dpc.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.*;
public class JDBCUtils {
private static ComboPooledDataSource cpds = new ComboPooledDataSource();
//获取连接
public static Connection getConnection() {
try {
return cpds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//释放连接
public static void release(Connection con, Statement st, ResultSet rs) {
if(rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(st != null) {
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(con != null) {
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
类中的方法定义成static,方便DAO层直接调用获取连接。记得每次用完调用release方法释放连接。
编写测试代码
package jxnuss.dpc.utils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import static org.junit.Assert.*;
public class JDBCUtilsTest {
@Test
public void getConnection() {
Connection con = null;
PreparedStatement pre = null;
ResultSet rs = null;
String sql = "select * from user";
try {
con = JDBCUtils.getConnection();
pre = con.prepareStatement(sql);
rs = pre.executeQuery();
while (rs.next()) {
System.out.println(rs.getString(2));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JDBCUtils.release(con, pre, rs);
}
}
}