数据库连接池基本介绍
文章目录
数据库连接池基本介绍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
{
DataSource ds
= new ComboPooledDataSource("otherc3p0");
for (int i
=1;i
<=10;i
++){
Connection conn
= ds
.getConnection();
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
;
public class DruidDemo {
public static void main(String
[] args
) throws Exception
{
Properties pro
= new Properties();
InputStream is
= DruidDemo
.class.getClassLoader().getResourceAsStream("druid.properties");
pro
.load(is
);
DataSource ds
= DruidDataSourceFactory
.createDataSource(pro
);
Connection conn
= ds
.getConnection();
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 {
private static DataSource ds
;
static {
try {
Properties pro
= new Properties();
pro
.load(JDBCUtils
.class.getClassLoader().getResourceAsStream("druid.properties"));
ds
= DruidDataSourceFactory
.createDataSource(pro
);
} catch (IOException e
) {
e
.printStackTrace();
} catch (Exception e
) {
e
.printStackTrace();
}
}
public static Connection
getConnection() throws SQLException
{
return ds
.getConnection();
}
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();
}
}
}
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();
}
}
}
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
;
public class DruidDemo2 {
public static void main(String
[] args
) throws Exception
{
Connection conn
= null
;
PreparedStatement pstmt
= null
;
try {
conn
= JDBCUtils
.getConnection();
String sql
= "insert into account values(null,?,?)";
pstmt
= conn
.prepareStatement(sql
);
pstmt
.setString(1, "张三");
pstmt
.setDouble(2, 2000);
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