数据库连接池——C3P0&Druid

mac2024-05-22  41

数据库连接池基本介绍

文章目录

数据库连接池基本介绍1. 基本概念2. 数据源标准接口 —— javax.sql.DataSource2.1 DataSource 的三种实现类型2.2 部分相关的方法及描述 2.3 C3P0 数据库连接池2.3.1 使用步骤2.3.2 配置文件2.3.3 Java代码基本演示:获取连接对象并打印到控制台 2.4 Druid 数据库连接池2.4.1 使用步骤2.4.2 配置文件2.4.3 Java代码基本演示:获取并打印连接对象2.4.4 Druid 工具类编写



1. 基本概念

  数据库连接池的本质上是一个容器(集合),存放数据库连接的容器,当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完后,会将连接对象归还给容器。百度百科介绍   使用数据库连接池可以:节约资源、提高访问效率。



2. 数据源标准接口 —— javax.sql.DataSource

  DataSource 是一个连接物理数据源的工厂,用于连接到此 DataSource 对象表示的物理数据源 。

  除了用 DriverManager 对象获取数据库连接外,DataSource 对象是获得数据库连接的首选方法。

  DataSource 的 API 介绍


2.1 DataSource 的三种实现类型

实现类型描述基本实现创建一个标准的 Connection 对象。连接池实现创建一个 Connection 对象,该对象将自动参与连接池。分布式事务实现创建一个 Connection 可用于分布式事务的对象

2.2 部分相关的方法及描述

方法名描述Connection getConnection()尝试与数据源建立连接,返回连接对象。Connection getConnection​(String username, String password)尝试与数据源建立连接,返回连接对象。void close()归还该 Connection 对象的数据库 和 JDBC资源。PrintWriter getLogWriter()检索此 DataSource 对象的日志编写器。

2.3 C3P0 数据库连接池

  C3P0是一个开源的JDBC连接池,目前使用它的开源项目有Hibernate、Spring等。

  C3P0 百度百科

  C3P0 API 文档


2.3.1 使用步骤

导入jar包

C3P0 jar包下载地址mysql-connector-java-8.0.17.jar : 注意与自己装的数据库版本对应。c3p0-0.9.5.2.jarmchange-commons-java-0.2.11.jar

定义配置文件

命名固定:c3p0.properties 或 c3p0-config.xml放置路径:src 路径下配置内容可以查看百度百科,后文会简单介绍几个。

创建核心对象

ComboPooledDataSource

获取连接对象

方法:getConnection

获取连接对象后就可以进行其他JDBC相关的操作了,这里不再演示。


2.3.2 配置文件

<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- 默认配置 --> <default-config> <!--连接参数,数据库相关参数配置--> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC</property> <property name="user">root</property> <property name="password">root</property> <!--连接池参数--> <!--初始化申请的连接数量--> <property name="initialPoolSize">10</property> <!--最大的连接池数量--> <property name="maxPoolSize">10</property> <!--超时时间,单位为毫秒--> <property name="checkoutTimeout">3000</property> </default-config> <!-- 命名配置 --> <named-config name="otherc3p0"> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC</property> <property name="user">root</property> <property name="password">root</property> <property name="initialPoolSize">5</property> <property name="maxPoolSize">8</property> <property name="checkoutTimeout">3000</property> </named-config> </c3p0-config>

注意数据库参数配置:

mysql 5.0 的驱动路径为:com.mysql.jdbc.DriverMySQL 8.0 的驱动路径为:com.mysql.cj.jdbc.DriverMySQL 8.0 之后必须加 : ?serverTimezone=UTC 如:jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC否则会报错时区错误。

2.3.3 Java代码基本演示:获取连接对象并打印到控制台

package com.base.datasource.c3p0; import com.mchange.v2.c3p0.ComboPooledDataSource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; public class C3P0Demo1 { public static void main(String[] args) throws SQLException { //1.1 获取DataSource,使用默认配置 // DataSource ds = new ComboPooledDataSource(); //1.2 获取连接对象 // Connection conn = ds.getConnection(); //3. 打印 // System.out.println(conn); // 2.1 获取DataSource,使用指定名称的配置 DataSource ds = new ComboPooledDataSource("otherc3p0"); for (int i=1;i<=10;i++){ // 2.2 获取连接对象 Connection conn = ds.getConnection(); // 2.2 打印 System.out.println(i +" : "+ conn); if (i == 5){ conn.close(); } } } }

运行结果:

1 : com.mchange.v2.c3p0.impl.NewProxyConnection@6a5fc7f7 [wrapping: com.mysql.cj.jdbc.ConnectionImpl@3b6eb2ec] 2 : com.mchange.v2.c3p0.impl.NewProxyConnection@6e8dacdf [wrapping: com.mysql.cj.jdbc.ConnectionImpl@7a79be86] 3 : com.mchange.v2.c3p0.impl.NewProxyConnection@b684286 [wrapping: com.mysql.cj.jdbc.ConnectionImpl@880ec60] 4 : com.mchange.v2.c3p0.impl.NewProxyConnection@7f63425a [wrapping: com.mysql.cj.jdbc.ConnectionImpl@36d64342] 5 : com.mchange.v2.c3p0.impl.NewProxyConnection@511baa65 [wrapping: com.mysql.cj.jdbc.ConnectionImpl@340f438e] 6 : com.mchange.v2.c3p0.impl.NewProxyConnection@19dfb72a [wrapping: com.mysql.cj.jdbc.ConnectionImpl@17c68925] 7 : com.mchange.v2.c3p0.impl.NewProxyConnection@3d24753a [wrapping: com.mysql.cj.jdbc.ConnectionImpl@340f438e] 8 : com.mchange.v2.c3p0.impl.NewProxyConnection@7a0ac6e3 [wrapping: com.mysql.cj.jdbc.ConnectionImpl@71be98f5] 9 : com.mchange.v2.c3p0.impl.NewProxyConnection@17f6480 [wrapping: com.mysql.cj.jdbc.ConnectionImpl@2d6e8792] Exception in thread "main" java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.

注意:

配置文件里面配置的初始化创建的连接池对象是5个,最大连接池对象是8个。代码展示中一共创建了10个连接对象,但是只成功创建了9个连接对象,还剩一个出现超时异常(3秒左右)能够创建9个连接对象的原因是,我们归还了第五个连接池对象,这个连接池对象被第七个连接对象获取了,通过后面的哈希值可以判断出这两个连接池对象是同一个。最后一个连接对象没有创建成功的原因是,连接对象已经达到我们设定的最大连接数量 8个,如果没有归还的话,其他连接对象就不能被创建出来。

2.4 Druid 数据库连接池

  Apache Druid 是一个分布式内存实时分析系统,用于解决如何在大规模数据集下进行快速的、交互式的查询和分析。

  阿里云开元组件介绍——Druid


2.4.1 使用步骤

导入jar包

maven仓库下载地址mysql-connector-java-8.0.17.jardruid-1.1.9.jar

配置文件

命名不固定。是 properties 形式的。可以放在任意路径下。

加载配置文件

类:Properties方法: getClassLoader()getResourceAsStream()load()

获取数据库连接池对象

通过工厂类获取:DruidDataSourceFactory

获取连接

获取方法:getConnection()

2.4.2 配置文件

  因为命名没有限制,这里取名为:druid.properties,内容如下:

# 数据库连接参数信息 driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC username=root password=root # 初始化连接数量 initialSize=5 # 最大连接数 maxActive=10 # 最大等待时间 maxWait=3000

2.4.3 Java代码基本演示:获取并打印连接对象

package com.base.datasource.druid; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.util.Properties; /** * Druid连接池基本演示 */ public class DruidDemo { public static void main(String[] args) throws Exception { //1. 加载配置文件,类加载器 Properties pro = new Properties(); InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); //2. 获取连接池对象 DataSource ds = DruidDataSourceFactory.createDataSource(pro); //3. 获取连接对象 Connection conn = ds.getConnection(); //4. 打印连接对象 System.out.println(conn); } }

运行结果:

com.mysql.cj.jdbc.ConnectionImpl@62e136d3

2.4.4 Druid 工具类编写

编写工具类 JDBCUtils package com.base.utils; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtils { //1. 定义成员变量 DataSource private static DataSource ds; static { try { //1. 加载配置文件 Properties pro = new Properties(); pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties")); //2. 获取 DataSource ds = DruidDataSourceFactory.createDataSource(pro); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 获取连接 * @return Connection 对象 * @throws SQLException */ public static Connection getConnection() throws SQLException { return ds.getConnection(); } /** * 释放资源 * @param stmt Statement对象 * @param conn Connection对象 */ public static void close(Statement stmt, Connection conn) { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 释放资源方法重载 * @param rs ResultSet对象 * @param stmt Statement 对象 * @param conn Connection 对象 */ public static void close(ResultSet rs, Statement stmt, Connection conn) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 获取连接池对象 * @return ds 连接池对象 */ public static DataSource getDataSource() { return ds; } } 使用工具类创建连接,并执行简单数据库操作。 package com.base.datasource.druid; import com.base.utils.JDBCUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /** * 使用JDBC工具类 * 完成添加操作,给account添加一条记录。 */ public class DruidDemo2 { public static void main(String[] args) throws Exception { Connection conn = null; PreparedStatement pstmt = null; try { //1. 获取连接 conn = JDBCUtils.getConnection(); //2. 定义 SQL String sql = "insert into account values(null,?,?)"; //3. 获取 pstmt 对象 pstmt = conn.prepareStatement(sql); //4. 给占位符(?)赋值 pstmt.setString(1, "张三"); pstmt.setDouble(2, 2000); //5. 执行 sql int count = pstmt.executeUpdate(); System.out.println(count); } catch (SQLException e) { e.printStackTrace(); } finally { // 释放资源 JDBCUtils.close(pstmt, conn); } } }

运行结果:

十月 31, 2019 4:24:03 下午 com.alibaba.druid.pool.DruidDataSource info 信息: {dataSource-1} inited 1

注意:没有数据库和对应的表需要提前创建一个,下面提供SQL代码。

-- 创建数据库 CREATE DATABASE IF NOT EXISTS demo_test CHARACTER SET utf8 ; USE demo_test; CREATE TABLE account( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(32) UNIQUE NOT NULL, money VARCHAR(32) NOT NULL );

时间:2019年10月31日15:59:13


最新回复(0)