1.数据库连接池的概念
其实就是一个容器(集合),存放数据库连接的容器。
当系统初始化好后,容器被创建,容器中会申请一些连接对象,
当用户来访问数据库时,从容器中获取连接对象,
用户访问完之后,会将连接对象归还给容器。
2.为什么存在数据库连接池:
因为与数据库建立连接底层是向操作系统申请的资源,
由于每次申请连接资源后,我们就把资源给释放了.
下次需要操作数据库又需要去申请,这个操作是比较耗时的,
所以就出现了数据库连接池的技术。
优点:节约资源、用户访问高效
3.数据库连接池的实现
实现接口
DataSource javax.sql包下的接口
方法
getConnection()获取连接
Connection.close()归还连接
一般我们不去实现DataSource,又提供数据库的厂商来实现。
DBCP连接池
- 导入jar包(两个) commons-dbcp-1.4.jar 、commons-pool-1.5.6.jar
DBCP工具类
package com.sunny.utils;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DBCPUtil {
private static Properties p = new Properties();
private static DataSource ds;
static {
try {
// 从classpath的根路径下去寻找dbcp.properties文件
InputStream inputStream = Thread.currentThread().
getContextClassLoader().getResourceAsStream("dbcp.properties");
p.load(inputStream);
ds = BasicDataSourceFactory.createDataSource(p);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接的方法
*
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 获取连接池的方法
*
* @return
*/
public static DataSource getDataSource() {
return ds;
}
/**
* 释放资源
*
* @param stmt
* @param conn
*/
public static void close(Statement stmt, Connection conn) {
close(null, stmt, conn);
}
/**
* 释放资源
*
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close(); // 归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close(); // 归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
DBCPTest
package com.sunny.datasource.DBCP;
import com.sunny.utils.DBCPUtil;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBCPTest1 {
// 查询zy数据库中emp表中员工的姓名和工资
@Test
public void testQueryEmp() throws SQLException {
String sql = "SELECT * FROM emp";
Connection conn = DBCPUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()){
long id = rs.getLong("id");
String ename = rs.getString("ename");
double salary = rs.getDouble("salary");
System.out.println(id+"\t"+ename+"\t"+salary);
}
DBCPUtil.close(rs, ps, conn);
}
}
c3p0连接池
使用步骤:
- 导入jar包(两个) c3p0-0.9.5.2.jar 、mchange-commons-java-0.2.12.jar
- 定义配置文件 c3p0.properties 或者 c3p0-config.xml直接放在src目录下
- 创建数据库连接池对象 ComboPooledDataSource
- 获取连接 getConnection
/*
c3p0演示
*/
public class C3P0Demo1 {
public static void main(String[] args) throws SQLException {
//1. 创建数据库连接池对象,可以使用默认配置,也可以使用指定配置
//DataSource ds = new ComboPooledDataSource();
DataSource ds = new ComboPooledDataSource("otherc3p0");
//2. 获取连接对象
Connection conn = ds.getConnection();
//3. 打印
System.out.println(conn);
}
}
c3p0-config.xml 使用此名字会自动加载该配置文件
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db</property>
<property name="user">root</property>
<property name="password">1111</property>
<!-- 连接池参数 -->
<!-- 初始化申请的连接池对象 -->
<property name="initialPoolSize">5</property>
<!-- 最大的连接数量 -->
<property name="maxPoolSize">10</property>
<!-- 超时时间 -->
<property name="checkoutTimeout">3000</property>
</default-config>
<!-- 使用otherc3p0的配置 -->
<named-config name="otherc3p0">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db</property>
<property name="user">root</property>
<property name="password">1111</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">8</property>
<property name="checkoutTimeout">1000</property>
</named-config>
</c3p0-config>
除了这种XML的配置文件外,还有.properties文件.
C3P0连接池工具类
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class C3P0Util {
// 创建C3P0连接池对象,内部村粗了多个Connection对象
// 创建对象时,会自动读取src根目录下的配置文件
private static ComboPooledDataSource cpds = new ComboPooledDataSource();
// 私有化构造器
private C3P0Util(){
}
// 定义静态方法,获取Connection对象
public static Connection getConnection() throws Exception{
return cpds.getConnection();
}
/**
* 获取连接池的方法
* @return
*/
public static DataSource getDataSource(){
return cpds;
}
public static void close(Statement stmt, Connection conn){
close(null, stmt, conn);
}
/**
* 释放资源
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs, Statement stmt, Connection conn){
if (rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close(); // 归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close(); // 归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Druid连接池工具类
/**
* Druid连接池工具类
*/
public class JDBCUtils {
//1. 定义成员变量DataSource
private static DataSource ds;
static{
try {
//1. 加载配置文件
Properties pro = new Properties();
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//2. 获取连接池DataSource对象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
}
/**
* 获取连接的方法
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
/**
* 获取连接池的方法
* @return
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt, Connection conn){
close(null, stmt, conn);
}
/**
* 释放资源
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs, Statement stmt, Connection conn){
if (rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close(); // 归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close(); // 归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
使用Druid工具类完成对关系表添加一条记录操作:
/**
* 使用新工具类, 做一个添加的操作
*/
public class DruidDemo2 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
// 给account表添加一条记录
try {
//1. 获取连接
conn = JDBCUtils.getConnection();
//2. 定义sql
String sql = "INSERT INTO account values(null, ?, ?)";
//3. 获取pstmt对象
pstmt = conn.prepareStatement(sql);
//4. 给?赋值
pstmt.setString(1, "朝阳");
pstmt.setDouble(2, 3000);
//5. 执行sql语句
int count = pstmt.executeUpdate();
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放资源
JDBCUtils.close(pstmt, conn);
}
}
}