【JDBC】连接池

连接池

看到本篇博文的同学,可能会有如下问题:

问:为什么要有连接池?

答曰:

由于建立数据库连接是一种非常耗时耗资源的行为,
所以通过连接池预先同数据库建立一些连接放在内存中
应用程序需要建立数据库连接直接到连接池中申请一个就行,使用完毕后再归还到连接池中

基本概念:

功能

数据库连接池负责分配管理释放 数据库连接,
它允许应用程序重复使用一个现有的数据库连接
而不是再重新建立一个
释放空闲时间超过最大空闲时间的数据库连接
避免因为没有释放数据库连接而引起的数据库连接遗漏
这项技术能明显提高对数据库操作的性能

原理

连接池基本的思想是在系统初始化的时候
数据库连接作为对象存储在内存中,
用户需要访问数据库时
并非建立一个新的连接
而是从连接池中取出一个已建立的空闲连接对象
使用完毕后,用户也并非将连接关闭
而是将连接放回连接池中,以供下一个请求访问使用。
连接的建立、断开都由连接池自身来管理
同时,还可以通过设置连接池的参数来控制连接池中的初始连接数连接的上下限数以及每个连接的最大使用次数最大空闲时间等等。
也可以通过其自身的管理机制来监视数据库连接的数量使用情况


目前为止,在Java中开源的数据库连接池共有11种 :

  1. C3P0
  2. Proxool
  3. DBCP
  4. DDConnectionBroker
  5. DBPool
  6. XAPool
  7. Primrose
  8. SmartPool
  9. MiniConnectionPoolManager
  10. BoneCP
  11. Druid

那么,在本篇博文中,本人主要讲解其中的3种:
本人先提供一张供操作的表:


操作表 展示

首先是 DBCP连接池

DBCP连接池:

概念

DBCP(DataBase Connection Pool)数据库连接池,
是Java数据库连接池的一种,由Apache开发,通过数据库连接池,
可以让程序自动管理数据库连接的释放断开

使用步骤

  1. 导入jar包(commons-dbcp-1.4.jar和commons-pool-1.5.6.jar)
  2. 使用api:
  • 硬编码方式
  • 配置文件方式

那么,本人现在来展示下这两种使用方式:
首先是 硬编码方式

硬编码方式:

package edu.youzg.about_jdbc.dbcp;

import org.apache.commons.dbcp.BasicDataSource;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Demo {
    
    public static void main(String[] args) throws SQLException {
        /* 创建 连接池对象 */
        BasicDataSource bds = new BasicDataSource();

        /* 获取连接对象 */
        bds.setDriverClassName("com.mysql.jdbc.Driver");
        bds.setUrl("jdbc:mysql://localhost:3306/dbstudy");
        bds.setUsername("root");
        bds.setPassword("123456");
        Connection connection = bds.getConnection();

        /* 获取操作对象 */
        PreparedStatement statement = connection.prepareStatement("select * from users");
        ResultSet resultSet = statement.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getString(1) + "===" + resultSet.getString(2));
        }

        /* 释放资源 */
        statement.close();
        resultSet.close();
        bds.close();
    }
    
}

那么,本人现在来展示下运行结果:


DBCP硬编码 展示

现在,本人来展示下第二种方式 —— 配置文件方式

配置文件方式:

首先,本人来提供一个配置文件:

#连接基本设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/dbstudy
username=root
password=123456
#
#初始化连接
initialSize=10

#最大连接数量
maxActive=50

#
maxIdle=20

#
minIdle=5

#
maxWait=60000

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

现在,本人在来给出Java代码:

package edu.youzg.about_jdbc.dbcp;

import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class Demo2 {
    
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        //properties.load(new FileInputStream("E:\\AboutJDBC\\JDBCStudy\\src\\dbcp.properties"));
        properties.load(new FileInputStream("src/dbcp.properties"));
        DataSource ds = BasicDataSourceFactory.createDataSource(properties);
        Connection connection = ds.getConnection();
        /* 获取操作对象 */
        PreparedStatement statement = connection.prepareStatement("select * from users");
        ResultSet resultSet = statement.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getString(1) + "===" + resultSet.getString(2));
        }

        //释放资源
        statement.close();
        resultSet.close();
    }
    
}
配置文件方式 展示

C3P0连接池:

概念

C3P0是一个开源的JDBC连接池,
它实现了数据源JNDI绑定,
支持JDBC3规范JDBC2的标准扩展
目前使用它的开源项目有HibernateSpring

c3p0与dbcp区别:

dbcp 没有自动回收空闲连接的功能
c3p0 有自动回收空闲连接功能

使用步骤

  1. 导入jar包(c3p0-0.9.1.2.jar)
  2. 使用api:
  • 硬编码方式
  • 配置文件方式
    (注意:若该方式使用无参初始化,则有如下两个要求:
  1. 配置文件的名称:c3p0.properties 或者 c3p0-config.xml
  2. 配置文件的路径:src下
    )

现在,本人来给出硬编码方式的代码:

硬编码方式:

package edu.youzg.about_jdbc.c3p0;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import edu.youzg.about_jdbc.model.User;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.sql.Array;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class Demo {
    
    public static void main(String[] args) throws Exception {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dbstudy");
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        
        Connection connection = dataSource.getConnection();

        PreparedStatement statement = connection.prepareStatement("select  * from user");
        ResultSet resultSet = statement.executeQuery();
        while (resultSet.next()) {
            String anInt = resultSet.getString(1);
            String string = resultSet.getString(2);
            System.out.println(anInt + "===" + string);
        }

        statement.close();
        resultSet.close();
    }
    
}

那么,现在本人来展示下运行结果:


C3P0硬编码 展示

现在,本人来讲解下通过配置文件的方式来使用C3P0连接池:

配置文件方式:

首先,本人来给出一个配置文件:


    
    
        
        com.mysql.jdbc.Driver
        jdbc:mysql://127.0.0.1:3306/dbstudy
        root
        123456

        
        30000
        30
        10
        30
        100
        10
        200
    


    
    
        com.mysql.jdbc.Driver
        jdbc:mysql://127.0.0.1:3306/mydemo
        root
        123456


        
        5
        20
        10
        40
        20
        5
    

注意:该配置文件必须放在src目录下,且 配置文件名称为"c3p0.properties"或"c3p0-config.xml"
(由C3P0源码决定)

现在,本人来给出相应的Java代码:

package edu.youzg.about_jdbc.c3p0;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Demo2 {

    public static void main(String[] args) throws SQLException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //或 ComboPooledDataSource dataSource = new ComboPooledDataSource("src/c3p0-config.xml");
        Connection connection = dataSource.getConnection();

        //获取操作对象
        PreparedStatement preparedStatement = connection.prepareStatement("select  * from users");
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            int anInt = resultSet.getInt(1);
            String string = resultSet.getString(2);
            System.out.println(anInt + "===" + string);
        }

        //释放资源
        preparedStatement.close();
        resultSet.close();
    }

}

那么,本人现在来展示下运行结果:


C3P0配置文件方式 展示

Druid 阿里德鲁伊 连接池:

概念

DRUID是阿里巴巴开源平台上一个数据库连接池实现,
它结合了C3P0DBCPPROXOOL等DB池的优点
同时加入了日志监控,可以很好的监控DB池连接SQL的执行情况
可以说是针对监控而生DB连接池
(据说是目前最好的连接池,不知道速度有没有BoneCP快)

使用步骤

  1. 导入德鲁伊的jar包
  2. 使用api:
  • 硬编码方式
  • 配置文件方式

那么,本人首先来展示下硬编码的方式

硬编码方式:

package edu.youzg.about_jdbc.druid;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Demo {
    
    public static void main(String[] args) throws SQLException {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/dbstudy");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        DruidPooledConnection connection = dataSource.getConnection();

        /* 获取操作对象 */
        PreparedStatement statement = connection.prepareStatement("select * from users");
        ResultSet resultSet = statement.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getString(1) + "===" + resultSet.getString(2));
        }

        /* 释放资源 */
        statement.close();
        resultSet.close();
    }
    
}

那么,本人现在来展示下运行结果:


Druid硬编码 展示

现在,本人来讲解下通过配置文件的方式来使用Druid连接池:

配置文件方式:

首先,本人来给出一个配置文件:

#基本配置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/dbstudy
username=root
password=123456
#扩展配置
filters=stat
initialSize=2
maxActive=300
maxWait=60000
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
poolPreparedStatements=false
maxPoolPreparedStatementPerConnectionSize=200

现在,本人来展示下相应的Java代码:

package edu.youzg.about_jdbc.druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

/**
 * @Author: Youzg
 * @CreateTime: 2020-04-08 22:28
 * @PROJECT: AboutJDBC
 * @PACKAGE: edu.youzg.about_jdbc.druid
 * @Description:
 */
public class Demo2 {

    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src/druid.properties"));
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
        Connection connection = dataSource.getConnection();

        /* 获取操作对象 */
        PreparedStatement statement = connection.prepareStatement("select * from users");
        ResultSet resultSet = statement.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getString(1) + "===" + resultSet.getString(2));
        }

        /* 释放资源 */
        statement.close();
        resultSet.close();
    }

}

现在,本人来展示下运行结果:


Druid配置文件方式 展示

在上面的讲解中,我们能够看到我们将所需的数据从相应的数据库中去了出来
但是,在我们之后的应用工作中,却不是仅仅在控制台展示出来那么简单
一般都会封装在一个信息类中,再将每一个信息对象放在一个集合中,以便我们之后的处理

但是,我们去new每一个对象,还要将对象放在集合中的操作,可能在操作一个数据库的一张表时很轻松
但若是在我们的工作中,可能会重复这样的代码成千上万遍
所以,前辈们又开发出了一种封装数据的工具类 —— DBUtils类

DBUtils类:

概念

Commons DbUtils是Apache组织(也就是上文中DBCP连接池的开发公司)提供的一个对JDBC进行简单封装的开源工具类库,
使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能

使用步骤:

  1. 导入jar包(commons-dbutils-1.4.jar)
  2. 创建一个queryrunner类:
    queryrunner作用:操作sql语句

构造方法:
new QueryRunner(Datasource ds);

  1. 编写sql
  2. 执行sql
  • query(sql):执行操作
  • update(sql):执行增删改操作

那么,现在本人就来展示下 DBUtils类的使用:

package edu.youzg.about_jdbc.dbutils;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import edu.youzg.about_jdbc.model.Hero;
import edu.youzg.about_jdbc.model.User;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import javax.sql.DataSource;
import java.sql.SQLException;

public class Demo3 {

    public static void main(String[] args) throws SQLException {
        //dbutils 这个工具类,他就封装了数据库操作对象,帮我们进行增删改查,并且还可以封装查询出来的数据

        //创建数据源
        DataSource ds = new ComboPooledDataSource();

        //传入数据源
        QueryRunner queryRunner = new QueryRunner(ds);

        //插入数据
        String sql="insert into users values(?,?)";
        int i = queryRunner.update(sql, 9293, "WaistDrumCrow");
        if (i>0){
            System.out.println("插入成功");
        }else{
            System.out.println("插入失败");
        }
        ////读取数据
        //sql = "select * from users where user_id=?";
        //User user = queryRunner.query(sql, new BeanHandler(User.class), 1868);
    }

}

现在,本人来展示下控制台的信息:

本人再来展示下数据库中目标表的信息:


目标表 展示

那么,本篇博文的知识点在这里就讲解完毕了。
(请观看本人博文 —— 《JDBC 专栏总集篇》)

你可能感兴趣的:(【JDBC】连接池)