一、JDBC 连接池的工作原理

当代码执行 Connection conn = DriverManager.getConnection(url,user,pwd); 获取数据库连接时,比较消耗性能,所以有了连接池

java获取dubbo连接池监控数据_开源连接池Druid

二、JDBC 开源连接池——DBCP

  • DBCP是Apache Tomcat 默认的连接池
  • 相对于其他连接池,DBCP的效率较低

1、不使用配置文件

java获取dubbo连接池监控数据_开源连接池DBCP_02


测试类 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、使用配置文件

java获取dubbo连接池监控数据_开源连接池Druid_03


新建数据库配置文件 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、不使用配置文件

java获取dubbo连接池监控数据_开源连接池DBCP_04

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 包下载,请**点击**