本文着重理解DBCP以及连接池基本运行原理(步骤)
首先我们要知道在连接数据库时
如果频繁的对数据库进行连接,然后又将它释放,对项目的访问效率是一种绝对的降低,
因为在这个过程中,连接(校验密码用户名)·与释放(回收资源)需要1s左右,一旦许多action一起访问,势必对服务器有不小压力
于是乎,数据库连接池就出现了,
常见的两种种为:
1.C3P0 数据库连接池(可百度咨询)
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。
c3p0与dbcp区别
dbcp没有自动回收空闲连接的功能
c3p0有自动回收空闲连接功能
2.DBCP 数据库连接池(本文着重理解DBCP):
DBCP 是 Apache 软件基金组织下的开源连接池实现,要使用DBCP数据源,需要应用程序应在系统中增加如下两个 jar 文件:
Commons-dbcp.jar:连接池的实现
Commons-pool.jar:连接池实现的依赖库
Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
本文着重理解DBCP
连接池基本运行步骤
(1) 程序初始化时创建一定数量(initialSize)连接池
(2) 使用时向连接池申请可用连接
(3) 使用完毕,将连接返还给连接池
(4) 程序退出时,断开所有连接,并释放资源
但我们将使用已经封装好的 DBCP连接池
首先导入包:
Commons-dbcp.jar:连接池的实现
Commons-pool.jar:连接池实现的依赖库
好,开始使用,
使用步骤如下:
1.配置自定义资源文件
config.properties
2.编写一个类调用Commons-dbcp.jar,连接池的实现
config.properties配置:(具体参数具体修改)
(可以定义多个资源文件,并以此加载不同数据库链接)
(重点:资源文件位于src目录!!!!!!!!!)
#连接设置
**driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/userxiu
username=root
password=123456**
#<!-- 初始化连接 -->
initialSize=5
#最大连接数量
maxActive=70
#<!-- 最大空闲连接 -->
maxIdle=50
#<!-- 最小空闲连接 -->
minIdle=2
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=false
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
编写一个类调用Commons-dbcp.jar,连接池的实现
package com.dbcp;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
/**
* dbcp数据库连接池 工具类
* 优点:不重复连接数据库等
* https://www.cnblogs.com/xdp-gacl/p/4002804.html
*/
/**
* @ClassName: Jdbc_DBCP
* @author joker
*/
public class Jdbc_DBCP {
/**
* 在java中,编写数据库连接池需实现java.sql.DataSource接口,每一种数据库连接池都是DataSource接口的实现
* DBCP连接池就是java.sql.DataSource接口的一个具体实现
*/
// 声明一个BasicDataSource源,也就是驱动
private static BasicDataSource ds = null;
//在静态代码块中创建数据库连接池
static{
try {
//加载properties配置文件
InputStream in = Jdbc_DBCP.class.getClassLoader().getResourceAsStream("config.properties");
Properties prop = new Properties();
prop.load(in);
//创建数据源
ds = (BasicDataSource) BasicDataSourceFactory.createDataSource(prop);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
/**
* @Description: 从数据源中获取数据库连接
* @Anthor:joker
* @return Connection
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
//从数据源中获取数据库连接
return ds.getConnection();
}
/**
* @Method: release
* @Description: 释放资源,
* 释放资源
* @Anthor:joker
*
* @param conn
* @param st
* @param rs
*/
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
//关闭存储查询结果的ResultSet对象
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
//关闭负责执行SQL命令的Statement对象
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(conn!=null){
try{
//将Connection连接对象还给数据库连接池
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
剩余的就是调用了(关键代码)
Connection co = Jdbc_DBCP.getConnection();
PreparedStatement p = co.prepareStatement(sql);
ResultSet result = p.executeQuery();
Jdbc_DBCP.release(co, p,result);
这就是数据库连接池优点。
它用完了,关闭时会只关闭逻辑连接,位于服务器的物理连接仍然存在。(为什么,导入的包实现的功能,只要会用,当然可以写,附上编写关键实现)
连接池需实现java.sql.DataSource接口。DataSource接口中定义了两个重载的getConnection方法:
Connection getConnection()
Connection getConnection(String username, String password)
当用户使用完Connection,
调用Connection.close()方法时,Collection对象应保证将自己返回到LinkedList中,而不要把conn还给数据库。
Collection保证将自己返回到LinkedList中是编程的难点。