一、JDBC 连接池的工作原理
当代码执行 Connection conn = DriverManager.getConnection(url,user,pwd);
获取数据库连接时,比较消耗性能,所以有了连接池
二、JDBC 开源连接池——DBCP
- DBCP是Apache Tomcat 默认的连接池
- 相对于其他连接池,DBCP的效率较低
1、不使用配置文件
测试类 Test.java
package DBCP;
import jdbcutils.JdbcUtils;
import org.apache.commons.dbcp.BasicDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test {
public static void main(String[] args){
Connection conn = null;
PreparedStatement ps = null;
try {
BasicDataSource bds = new BasicDataSource();//Datesource 获得连接,就是从连接池中获取连接
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUrl("jdbc:mysql://localhost:3306/db_test");
bds.setUsername("root");
bds.setPassword("lemon");
bds.setMaxActive(50);//设置最大连接数
bds.setMaxIdle(10);//设置最小连接数
conn = bds.getConnection();//从连接池里获取连接
ps = conn.prepareStatement("update account set balance = balance - 500 where id = 1");
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//这里不叫释放资源了,叫 把连接还给池
JdbcUtils.close(conn,ps);
}
}
}
2、使用配置文件
新建数据库配置文件 config.txt
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db_test
username=root
password=lemon
maxActive=50
maxIdle=10
测试类 ConfigTest.java
package DBCP;
import jdbcutils.JdbcUtils;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Properties;
public class ConfigTest {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
try {
BasicDataSourceFactory factory = new BasicDataSourceFactory();
Properties properties = new Properties();
InputStream is = ConfigTest.class.getClassLoader().getResourceAsStream("config.txt");
properties.load(is);
DataSource dataSource = factory.createDataSource(properties);
//连接从连接池中获取
conn = dataSource.getConnection();
ps = conn.prepareStatement("update account set balance = balance - 500 where id = 1");
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
//把连接还给池
JdbcUtils.close(conn,ps);
}
}
}
三、JDBC 开源连接池——C3P0
- C3P0 相对于DBCP连接池来说,稳定,效率高
- C3P0 属于第三方类库
- 实际开发中常用
1、不使用配置文件
package c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import jdbcutils.JdbcUtils;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class Test {
public static void main(String[] args){
Connection conn = null;
PreparedStatement ps = null;
try {
ComboPooledDataSource dataSource = new ComboPooledDataSource();//从连接池中获取连接
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/db_test?characterEncoding=utf8");
dataSource.setUser("root");
dataSource.setPassword("lemon");
dataSource.setMaxPoolSize(50);//设置最大连接数
dataSource.setMinPoolSize(10);//设置最小连接数
conn = dataSource.getConnection();//连接从连接池中获取
ps = conn.prepareStatement("update account set balance = balance - 500 where id = 1");
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtils.close(conn,ps);
}
}
}
运行后会提日志
2、使用配置文件
C3P0提供独有的配置文件 c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- default-config 默认的配置, -->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost/db_test</property>
<property name="user">root</property>
<property name="password">lemon</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>
创建 Test.java 文件,注意:Test.java 文件会自动读取 C3P0的配置文件 c3p0-config.xml
package c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import jdbcutils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class Test {
public static void main(String[] args){
Connection conn = null;
PreparedStatement ps = null;
try {
ComboPooledDataSource dataSource = new ComboPooledDataSource();//从连接池中获取连接
//自动读取 c3p0-config.xml 配置文件
conn = dataSource.getConnection();//连接从连接池中获取
ps = conn.prepareStatement("update account set balance = balance - 500 where id = 1");
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtils.close(conn,ps);
}
}
}
四、JDBC 开源连接池——Druid
- Druid 是阿里巴巴开发的第三方类库
- 效率最高的连接池框架
阿里提供的配置文件 druid.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db_test
username=root
password=lemon
initialSize=5
maxActive=10
maxWait=3000
package druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import jdbcutils.JdbcUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Properties;
public class Test {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
try {
Properties pro = new Properties();//相当于 Map<String,String> = Properties;
pro.load(Test.class.getResourceAsStream("/druid.properties"));//读取配置文件
//System.out.println(pro.getProperty("password"));//打印获取文件的password
DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);
//连接从连接池中获取
conn = dataSource.getConnection();
ps = conn.prepareStatement("update account set balance = balance - 500 where id = 1");
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
//把连接还给池
JdbcUtils.close(conn,ps);
}
}
}
五、操作数据库的工具类JdbcUtils.java 修改
在上面的三种数据库连接池中,都用到了数据库的工具类 JdbcUtils.java,它的代码为:
package jdbcutils;
import java.sql.*;
public class JdbcUtils {
private static final String URL = "jdbc:mysql://localhost:3306/db_test";
private static final String USER = "root";
private static final String PWD = "lemon";
private static final String DRIVER = "com.mysql.jdbc.Driver";
Connection conn = null;
Statement sta = null;
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(URL,USER,PWD);
}
public static void close(Connection conn,Statement sta){
if (sta != null){
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Connection conn, Statement sta, ResultSet rs){
if (rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (sta != null){
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
查看以上代码得知:数据库的工具类 JdbcUtils.java并未使用开源连接池,所以我们要修改这个工具类,让它使用开源连接池Druid
package jdbcutils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils {
private static DataSource dataSource;
static {
try {
//druid 的连接池
Properties pro = new Properties();//加载配置文件
pro.load(JdbcUtils.class.getResourceAsStream("/druid.properties"));//使用ClassLoad加载配置文件,获取字节输入流
dataSource = DruidDataSourceFactory.createDataSource(pro);//初始化连接池对象
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDataSource() {//获取连接池对象
return dataSource;
}
public static Connection getConnection() throws SQLException {//获取Connection 对象
return dataSource.getConnection();
}
//释放资源
public static void close(Connection conn,Statement sta){
if (sta != null){
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Connection conn, Statement sta, ResultSet rs){
if (rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (sta != null){
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
以上代码所需要的 jar 包下载,请**点击**