【Java】JDBC Part5 DataSource 连接池操作

JDBC Part5 DataSource 连接池操作

- javax.sql.DataSource 接口,通常由服务器实现

- DBCP  Tomcat自带相对C3P0速度较快,但存在BUG,已经不更新了

- Proxool  没听过、能监控连接池状态,稳定性差

- C3P0  速度较慢,但是稳定

- Druid  阿里巴巴提供,集成上面的所有优点,

- Hikari  目前最快的连接池依赖,据说有安全问题。。。

DataSource被称为数据源,包含连接池和连接池管理2部分


C3P0实现

官方文档:  https://blog.csdn.net/wangwei_cq/article/details/8930667

Maven依赖

<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.5</version>
</dependency>

第一种,硬编码的连接池

package connector;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @author ArkD42
 * @file Jdbc
 * @create 2020 - 04 - 24 - 17:49
 */
public class C3P0Test {

    @Test
    public void dataSourceByC3p0() throws PropertyVetoException, SQLException {
        // 获取池对象
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        // 配置连接信息
        dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_db?serverTimezone=Asia/Shanghai");
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        //设置初始的连接数
        dataSource.setInitialPoolSize(10); 
        //获取连接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }
}

测试结果

第二种 XML配置文件

配置XML配置文件的信息

<?xml version="1.0" encoding="UTF-8" ?>
<c3p0-config>
    <!-- 自定义的配置命名-->
    <named-config name="c3p0 XML config">

        <!-- 四个基本信息 -->
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <!-- 默认本地可以省略 jdbc:mysql:///jdbc_db?serverTimezone=Asia/Shanghai -->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_db?serverTimezone=Asia/Shanghai</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <!-- 连接池管理信息 -->

        <!-- 连接对象数不够时,每次申请 迭增的连接数 -->
        <property name="acquireIncrement">5</property>
        <!-- 初始池大小存放的连接对象数 -->
        <property name="initialPoolSize">10</property>
        <!-- 最小连接对象数 -->
        <property name="minPoolSize">10</property>
        <!-- 最大连接对象数,不可超出的范围 -->
        <property name="maxPoolSize">100</property>
        <!-- 最多维护的SQL编译对象个数-->
        <property name="maxStatements">50</property>
        <!-- 每个连接对象最多可使用的SQL编译对象的个数 -->
        <property name="maxStatementsPerConnection">2</property>
    </named-config>
</c3p0-config>

注意获取配置名

如果密码错误,其他配置问题,连接池运行一段时间获取不到连接自动超时退出,报异常


封装JdbcForC3P0Util工具类

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ArkD42
 * @file Jdbc
 * @create 2020 - 04 - 24 - 18:23
 */
public class JdbcForC3p0Util {

    // 池对象只需要一个即可
    private static final ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("c3p0 XML config");

    // 获取连接对象,从池对象获取的对象可允许多个
    public static Connection getConnection(){
        try {
            return comboPooledDataSource.getConnection();
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
        return null;
    }

    // 释放资源 对象没有的情况直接null注入
    public static void releaseResource(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){
        try{
            if (resultSet != null) resultSet.close();
            if (preparedStatement != null) preparedStatement.close();
            if (connection != null) connection.close();
        } catch (SQLException sqlException){
            sqlException.printStackTrace();
        }
    }

    // 增删改
    public static int update(String sql,Object[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = getConnection();
            preparedStatement = connection.prepareStatement(sql);
            if (args != null ) for (int i = 0; i < args.length; i++) preparedStatement.setObject(i+1,args[i]);
            int i = preparedStatement.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            releaseResource(connection,preparedStatement,null);
        }
        return 0;
    }
    
    // 查询
    public static <T> List<T> queryList(Class<T> tClass, String sql, Object[] args){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try{
            connection = getConnection();
            preparedStatement = connection.prepareStatement(sql);
            if (args != null) for (int i = 0; i < args.length; i++) preparedStatement.setObject(i+1,args[i]);
            resultSet = preparedStatement.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            List<T> tList = new ArrayList<T>();
            while(resultSet.next()){
                T t = tClass.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    Object columnValue = resultSet.getObject(i + 1);
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    Field field = tClass.getDeclaredField(columnLabel);
                    field.setAccessible( true );
                    field.set(t,columnValue);
                }
                tList.add(t);
            }
            return tList;
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            releaseResource(connection,preparedStatement,resultSet);
        }
        return null;
    }
}

测试,Blob不可封装为实体类对象,所以大文件的字段我删除了


DBCP 连接池操作

Maven依赖

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-dbcp2</artifactId>
  <version>2.7.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-pool2</artifactId>
  <version>2.8.0</version>
</dependency>

连接实现一,硬编码连接

public class DBCP {

    @Test
    public void dbcp() throws Exception{
        // 创建连接池
        BasicDataSource dataSource = new BasicDataSource();

        // 配置信息
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///jdbc_db?serverTimezone=Asia/Shanghai");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");

        // 连接池管理设置
        //dataSource.setInitialSize(10);  //  初始化池种的连接对象个数
        //dataSource.setMaxIdle(10);      //  最大空闲连接对象个数
        //dataSource.setMinIdle(2);       //  最小空闲连接对象个数
        
        // 获取连接对象
        Connection connection = dataSource.getConnection();

        System.out.println(connection);
        connection.close();
    }
}

测试结果


连接实现二,读取配置文件

dbcp.properties配置文件的信息

# 注意这个driverClassName 
driverClassName = com.mysql.cj.jdbc.Driver
url = jdbc:mysql:///jdbc_db?serverTimezone=Asia/Shanghai
# 注意这个username
username = root
password = 123456

测试单元

    @Test
    public void dbcp2() throws Exception{
        InputStream inputStream = DBCP.class.getClassLoader().getResourceAsStream("dbcp.properties");
        Properties properties = new Properties();
        properties.load(inputStream);
        BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }

第一种获取方式【通用】

InputStream inputStream = DBCP.class.getClassLoader().getResourceAsStream("dbcp.properties");

第二种获取方式

// Maven工程的读取路径
InputStream inputStream = new FileInputStream(new File("src/main/resources/dbcp.properties"));

// 普通工程的读取路径
InputStream inputStream = new FileInputStream(new File("src/dbcp.properties"));

第三种获取方式【通用,防空格中文编码不读取】

String file = DBCP.class.getClassLoader().getResource("dbcp.properties").getFile();
String decode = URLDecoder.decode(file, "utf-8");

//System.out.println(file);
//System.out.println(decode);

InputStream inputStream = new FileInputStream(decode);

测试结果

JdbcDbcpUtil 工具类封装

public class JdbcDbcpUtil {

    private static DataSource dataSource = null;
    
    static {
        String path = JdbcDbcpUtil.class.getClassLoader().getResource("dbcp.properties").getFile();
        System.out.println(path);
        try {
            String decode = URLDecoder.decode(path, "utf-8");
            InputStream inputStream = new FileInputStream(decode);
            Properties properties = new Properties();
            properties.load(inputStream);
            dataSource = BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        try {
            return dataSource.getConnection();
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
        return null;
    }

}

测试结果


 

Druid连接池实现

Maven依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.22</version>
</dependency>

硬编码连接

    @Test
    public void dt1() throws SQLException {
        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///jdbc_db?serverTimezone=Asia/Shanghai");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");

        DruidPooledConnection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }

读取配置文件,读取方式跟DBCP几乎一样,配置文件都不需要改

    @Test
    public void dt2() throws Exception {
        String path = DruidTest.class.getClassLoader().getResource("dbcp.properties").getFile();
        String decode = URLDecoder.decode(path, "utf-8");
        FileInputStream inputStream = new FileInputStream(decode);
        Properties properties = new Properties();
        properties.load(inputStream);
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }

JdbcDruidUtils 工具类封装

【对着DBCP的直接改连接池工厂就完事了】

public class JdbcDruidUtil {

    private static DataSource dataSource = null;

    static {
        String path = JdbcDbcpUtil.class.getClassLoader().getResource("druid.properties").getFile();
        System.out.println(path);
        try {
            String decode = URLDecoder.decode(path, "utf-8");
            InputStream inputStream = new FileInputStream(decode);
            Properties properties = new Properties();
            properties.load(inputStream);
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        try {
            return dataSource.getConnection();
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
        return null;
    }
}
原文地址:https://www.cnblogs.com/mindzone/p/12769276.html