DataBase | 02 数据库连接池
- 数据库连接池
- 1. 数据库连接池的基本概念
- 1.1 过去的使用方式
- 1.2 数据库连接池的本质
- 1.3 数据库连接池的工作方式
- 1.4 数据库连接池的优势
- 2. 数据库连接池的使用
- 2.1 基本使用步骤
- Tips 2.1:配置连接的两种方式
- Tips 2.2:连接池参数
- 3. 数据库连接池技术实现
- 3.1 标准接口
- 3.2 具体实现
- 3.2.1 C3P0
- 3.2.1.1 C3P0的基本使用
- 3.2.1.2 C3P0的不同点
- 3.2.2 Druid
- 3.2.2.1 Druid的基本使用
- 3.2.2.2 Druid的不同点
- 4. 数据库连接池工具类抽取
- **Tips 4.1:对比JDBC的工具类**
数据库连接池
1. 数据库连接池的基本概念
1.1 过去的使用方式
每次进行SQL操作前从系统底层获取连接资源,执行结束后释放连接
问题:浪费资源同时获取资源的时间长
解决方式:使用数据库连接池这种获取连接的新方式
1.2 数据库连接池的本质
数据库连接池基本思想是为数据库连接建立一个容器(Java中即集合)
这个容器负责分配、管理和释放数据库连接,实质上提供了一种获取连接的新方式
1.3 数据库连接池的工作方式
- 系统初始化好后,容器被创建,容器会申请一些连接对象
- 当用户访问数据库时,从容器中获取连接对象
- 当用户访问完成后,将连接对象归还给容器( 不再需要用户释放 )
1.4 数据库连接池的优势
- 节约资源,申请的连接可以重复使用
- 访问高效,直接获取创建好的连接而不用从系统底层获取资源
- 统一的连接管理,可以避免出现数据库连接泄漏的问题
2. 数据库连接池的使用
2.1 基本使用步骤
- 导入jar包
- 配置连接池
- 加载配置信息
- 创建核心数据库连接池对象
- 获取连接
- 后续与JDBC处理相同
小心别掉坑:在导入jar包时,连接池中的连接也是由驱动创建的所以驱动的jar包也要导入
Tips 2.1:配置连接的两种方式
以C3P0为例
编码的方式:初始化连接池对象,使用方法传入连接参数
//编码方式
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql:///dbtest");
dataSource.setUser("root");
dataSource.setPassword("1234");
配置的方式:在配置文件中设置连接的参数(常用)
<!--配置方式-->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///dbtest</property>
<property name="user">root</property>
<property name="password">1234</property>
Tips 2.2:连接池参数
以C3P0为例
- initialPoolSize:初始化时申请的连接数量,后续连接数量不足可以增加但不可超过最大连接数量
- maxPoolSize:连接池中的最大连接数量,超出后申请请求会进入等待队列直到有其他进程归还连接
- checkoutTimeout:获取连接超时时间,超过该时间会失败报错,毫秒为单位
3. 数据库连接池技术实现
3.1 标准接口
Interface DataSource:数据源工厂
实现功能:
- 获取连接
方法:- 归还连接:
方法:和关闭连接使用相同的方法
Tips:当连接是由连接池获取的close方法不再是关闭连接而是归还连接
3.2 具体实现
Tips:一般不自己编写标准接口DataSource的实现类由数据库厂商提供
3.2.1 C3P0
3.2.1.1 C3P0的基本使用
- C3P0配置文件( c3p0-config.xml )
Tips:注意配置文件的写法
<c3p0-config>
<!--默认配置-->
<default-config>
<!--连接信息-->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///dbtest</property>
<property name="user">root</property>
<property name="password">1234</property>
<!--连接池配置参数-->
<!--不设置c3p0会有默认的设置-->
</default-config>
<!--指定配置,方便配置多个连接池-->
<!--name的值是配置的标识-->
<named-config name="other">
<!--连接信息-->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///dbtest</property>
<property name="user">root</property>
<property name="password">1234</property>
<!--连接池配置参数-->
<!--初始化时申请的连接数量后续可以增加但不可超过最大连接数量-->
<property name="initialPoolSize">5</property>
<!--连接池中可以申请的最大连接数量-->
<property name="maxPoolSize">10</property>
<!--获取连接超时时间,超过该时间会失败报错,毫秒为单位-->
<property name="checkoutTimeout">1000</property>
</named-config>
</c3p0-config>
- C3P0的使用代码
//使用默认的配置创建连接池
public class C3P0Demo1 {
public static void main(String[] args) {
try {
//创建数据库连接池
//C3P0的连接池对象为ComboPooledDataSource
DataSource dataSource = new ComboPooledDataSource();
//获取连接
Connection conn = dataSource.getConnection();
//
//之后与JDBC的使用方式相同
//
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
//使用指定的配置创建连接池
public class C3P0Demo2 {
public static void main(String[] args) {
try {
//使用名为"other"的配置创建连接池
DataSource dataSource = new ComboPooledDataSource("other");
//获取连接
Connection conn = dataSource.getConnection();
System.out.println(conn);
//
//之后与JDBC的使用方式相同
//
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
3.2.1.2 C3P0的不同点
- C3P0会自动加载src目录下命名为c3p0.properties或c3p0-config.xml的配置文件
- C3P0连接池的属性可以在控制台日志中查看
- C3P0的连接池对象为ComboPooledDataSource
3.2.2 Druid
3.2.2.1 Druid的基本使用
- Druid的配置文件( druid.properties )
#连接信息
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///dbtest
username=root
password=1234
#连接池参数
#初始化申请的链接数量
initialSize=5
#最大的连接数量
maxActive=10
#最大获取连接等待时间
maxWait=1000
- Druid的使用代码
public class DruidDemo1 {
public static void main(String[] args) {
try {
//加载配置文件
Properties prop = new Properties();
//获取配置文件的字节输入流InputStream
InputStream in = DruidDemo1.class
.getClassLoader().getResourceAsStream("druid.properties");
prop.load(in);
//创建数据库连接池
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//获取连接
Connection conn = dataSource.getConnection();
//
//之后与JDBC的使用方式相同
//
}catch(IOException e){
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.2.2.2 Druid的不同点
- Druid配置文件为properties形式可以放在任意的目录下,需要手动加载配置
- Druid的连接池对象通过工厂类方法( DruidDataSourceFactory.createDataSource( ) )获取
4. 数据库连接池工具类抽取
在JDBC工具类的基础上增加获取所使用连接池的方法
- 工具类代码
public class JDBCUtil {
private static DataSource dataSource;
//使用静态代码块读取配置文件创建数据库连接池
static{
try {
Properties prop = new Properties();
prop.load(JDBCUtil.class.
getClassLoader().getResourceAsStream("druid.properties"));
dataSource = DruidDataSourceFactory.createDataSource(prop);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取创建的数据库连接池
public static DataSource getDataSource(){
return dataSource;
}
//从数据库连接池中获取连接
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
throw new RuntimeException(throwables);
}
}
//释放资源
public static void close(ResultSet rs, Statement stmt, Connection conn){
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void close(Statement stmt,Connection conn){
close(null,stmt,conn);
}
}
Tips 4.1:对比JDBC的工具类
不再需要连接参数
private static String url;
private static String username;
private static String password;
这些参数都提供给了连接池,使用时获取连接池拿连接即可
private static DataSource dataSource;