一、连接池
连接池和线程池类似,连接池是一个用来创建和管理连接对象的容器,使用连接池可以让数据库的连接复用
回顾连接池
线程池是一个负责创建线程和管理线程的容器,使用线程池可以节省资源开销。
常用的连接池
C3P0连接池
DRUID连接池
二、C3P0连接池
C3PO是一个开源的连接池。Hibernate框架默认推荐使用C3PO作为连接池实现。
C3PO地址: https://sourceforge.net/projects/c3p0/?source-navbar
C3PO的jar包: c3pe-0.9.1.2.jar
1、C3P0配置文件
要使用C3PO连接池,需要设置一些参数。使用配置文件设置参数是最方便的方法,我们通过使用配置文件方式去设置C3P0参数。
配置文件的要求:
1、文件名: c3p0-config.xml
2、放在源代码即src目录下
3、配置方式一:使用默认配置(default-config)
4、配置方式二:使用命名配置(named-config)
C3P0配置文件名称必须为c3p0-config.xml,文件里面的命名配置(named-config)可以有多个
C3P0配置文件示例
<c3p0-config>
<!-- 使⽤用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">10</property>
<property name="checkoutTimeout">2000</property>
<property name="maxIdleTime">1000</property>
</default-config>
<!-- 使⽤用命名的配置读取连接池对象 -->
<named-config name="itheimac3p0">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">15</property>
<property name="checkoutTimeout">2000</property>
<property name="maxIdleTime">1000</property>
</named-config>
</c3p0-config>
C3PO参数说明
数据库连接参数(必须项)
driverClass:驱动类全名
jdbcUrl:连接字符串
user:用户名
password:密码
常用的连接池配置参数:
初始连接数:刚创建好连接池的时候准备的连接数量
最大连接数:连接池中最多可以放多少个连接
最大等待时间:连接池中没有连接时最长等待时间
最大空闲回收时间:连接池中的空闲连接多久没有使用就会回收
完整参数表
2、C3P0连接池对象(ComboPooledDatasource类)
com. mchange.v2. c3pe. ComboPooledDatasource类表示C3PO的连接池对象。
常用2种创建连接池的方式:
1、无参构造,使用默认配置
2、有参构造,使用命名配置
ComboPooledDatasource类构造方法
//无参构造使用默认配置(使用xml中default-config标签中对应的参数)
public ComboPooledDataSource()
//有参构造使用命名配置(configName: xml中配置的名称,使用xml中named-config标签中对应的参数)
public ComboPooledDataSource(String configName)
ComboPooledDatasource类对象方法
//从连接池中取出一个连接
public Connection getConnection() throws SQLException
3、C3P0连接池的使用步骤
1、导入jar包
2、准备配置文件
文件名:必须是c3p0-config.xml
文件位置:必须在src目录下
配置方式一:使用默认配置(default-config)
配置方式二:使用命名配置(named-config)
3、在配置文件中编写配置信息
数据库连接参数
url:连接字符串
driverClass:驱动类全名
user:用户名
password:密码
连接池参数
初始化连接数:连接池中一开始创建指定数量的连接对象 5
最大连接数:连接池中可以存储的连接对象最大数量 10
最大等待时间:当连接池中没有连接对象可用时需要等多长时间,当指定时间内没有连接可以则直接抛出异常。
最大空闲时间:2000
4、创建连接池对象
5、调用连接池对象的getConnection方法获得连接对象并操作数据库
6、调用连接对象的close方法将连接对象放回池中等待复用。
4、C3P0连接池使用示例1
在src下,创建C3P0配置文件模板:c3p0-config.xml
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 数据库连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">10</property>
<property name="checkoutTimeout">2000</property>
<property name="maxIdleTime">1000</property>
</default-config>
<!-- 使用命名的配置读取连接池对象 -->
<named-config name="itheimac3p0">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">15</property>
<property name="checkoutTimeout">2000</property>
<property name="maxIdleTime">1000</property>
</named-config>
</c3p0-config>
使用c3p0连接池
package com.itheima._10C3P0连接池;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
/**
目标:创建C3P0连接池并从池中获得连接对象
*/
public class C3P0Demo01 {
public static void main(String[] args)throws Exception {
// 创建连接池对象:使用默认配置
// ComboPooledDataSource ds = new ComboPooledDataSource();
// 创建连接池对象:使用命名配置
ComboPooledDataSource ds = new ComboPooledDataSource("itheimac3p0");
for (int i = 0; i < 16; i++) {
// 从连接池中获得连接对象
Connection conn = ds.getConnection();
System.out.println(i+"="+conn);
if (i == 5) {
// 关闭连接:并不是直接关闭了而是将连接对象放回池中等待复用
// invoke
conn.close();
}
}
}
}
案例效果
正常获取连接池中连接
获取连接池中连接超时
5、C3P0连接池使用示例2
准备数据
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT,
score DOUBLE DEFAULT 0.0
)
配置文件
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 数据库连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">10</property>
<property name="checkoutTimeout">2000</property>
<property name="maxIdleTime">1000</property>
</default-config>
<!-- 使用命名的配置读取连接池对象 -->
<named-config name="itheimac3p0">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">15</property>
<property name="checkoutTimeout">2000</property>
<property name="maxIdleTime">1000</property>
</named-config>
</c3p0-config>
java代码
public class Demo01 {
public static void main(String[] args) throws Exception {
// 方式一: 使用默认配置(default-config)
// new ComboPooledDataSource();
// ComboPooledDataSource ds = new ComboPooledDataSource();
// 方式二: 使用命名配置(named-config:配置名)
// new ComboPooledDataSource("配置名");
ComboPooledDataSource ds = new ComboPooledDataSource("otherc3p0");
// for (int i = 0; i < 10; i++) {
// Connection conn = ds.getConnection();
// System.out.println(conn);
// }
// 从连接池中取出连接
Connection conn = ds.getConnection();
// 执行SQL语句
String sql = "INSERT INTO student VALUES (NULL, ?, ?, ?);";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "张三");
pstmt.setInt(2, 25);
pstmt.setDouble(3, 99.5);
int i = pstmt.executeUpdate();
System.out.println("影响的行数: " + i);
pstmt.close();
conn.close(); // 将连接还回连接池中
}
}
案例效果
使⽤用连接池中的连接往数据库添加数据
总结
配置文件名称必须为:c3pe-config.xml ,将配置文件放在src目录下。使用配置文件方式好处:只需要单独修改配置文件,不用修改代码。
多个命名配置的好处:
1、可以连接不同的数据库: db1,db2。
2、可以使用不同的连接池参数: maxPoolSize
3、可以连接不同厂商的数据库: Oracle或MySQL
三、DRUID连接池
Druid是阿里巴巴开发的号称为监控而生的数据库连接池,,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
Druid地址: https://github.com/alibaba/druid
DRUID连接池使用的jar包: druid-1.0.9.jardruid-1.0.9.jar
为什么使用DRUID连接池
c3p0连接池有点慢,所以使用更好的druid连接池
1、DRUID配置文件
DRUID连接池在创建的时候需要一个Properties对象来设置参数,所以我们使用properties文件来保存对应的参数。DRUID连接池的配置文件名称随便,建议放到src目录下面方便加载。
DRUID配置文件示例
创建properties文件,命名为druid.properties(随意命名)文件内容:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/day25
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
maxIdle=6
minIdle=3
DRUID常用参数说明
2、DRUID连接池对象(DruidDatasourceFactory类)
com.alibaba.druid.pool.DruidDatasourceFactory类有创建连接池的方法
public static DataSource createDataSource (Properties properties)
//创建一个连接池,连接池的参数使用properties中的数据
3、DRUID连接池的使用步骤
1、在src目录下创建一个properties文件,并设置对应参数
2、加载properties文件的内容到Properties对象中
3、创建DRUID连接池,使用配置文件中的参数
4、从DRUID连接池中取出连接
5、执行SQL语句
6、关闭资源
4、DRUID连接池使用示例1
在src目录下新建一个DRUID配置文件,命名为: druid.properties,内容如下
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/day25
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
maxIdle=6
minIdle=3
java代码
/**
目标:创建Druid连接池并从池中获得连接对象
使用步骤:
1. 导入相关jar
2. 准备配置文件
* 文件名任意:一般是druid.properties
* 文件位置:可以存储在任意目录下,一般存储在src目录下
3. 编写配置信息
* 数据库连接参数:连接字符串,驱动类全名,用户名,密码
* 连接池参数:初始连接数,最大连接数,最大等待时间
4. 创建druid连接池对象
* 通过工具类DruidDataSourceFactory方法创建
5. 调用连接池对象的getConnection获得连接对象操作数据
6. 调用连接对象的close方法关闭连接:不是真正关闭而是放回池中
*/
public class DruidDemo01 {
public static void main(String[] args) throws Exception{
// 4. 创建druid连接池对象
// 4.1 创建属性集对象
Properties info = new Properties();
// 4.2 加载配置信息到集合中
info.load(DruidDemo01.class.getResourceAsStream("/druid.properties"));
DataSource ds = DruidDataSourceFactory.createDataSource(info);
// 5. 调用连接池对象的getConnection获得连接对象
for (int i = 0; i < 11; i++) {
Connection conn = ds.getConnection();
if (i == 5) {
// 6. 调用连接对象的close方法关闭连接:不是真正关闭而是放回池中
conn.close();
}
}
}
}
案例效果
正常获取连接池中的连接
获取连接池中的连接超时
5、DRUID连接池使用示例2
java代码
public class Demo02 {
public static void main(String[] args) throws Exception {
// 加载配置文件中的配置参数
InputStream is = Demo03.class.getResourceAsStream("/druid.properties");
Properties pp = new Properties();
pp.load(is);
// 创建连接池,使用配置文件中的参数
DataSource ds = DruidDataSourceFactory.createDataSource(pp);
// for (int i = 0; i < 10; i++) {
// Connection conn = ds.getConnection(); // System.out.println(conn);
// }
// 从连接池中取出连接
Connection conn = ds.getConnection();
// 执行SQL语句
String sql = "INSERT INTO student VALUES (NULL, ?, ?, ?);";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "王五");
pstmt.setInt(2, 35);
pstmt.setDouble(3, 88.5);
int i = pstmt.executeUpdate();
System.out.println("影响的行数: " + i);
// 执行查询
sql = "SELECT * FROM student;";
ResultSet rs = pstmt.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
double score = rs.getDouble("score");
System.out.println("id: " + id + " ,name: " + name + " ,age = " + age + " ,score = " + score);
}
pstmt.close();
conn.close(); // 将连接还回连接池中
}
}
案例效果
使用DRUID连接池中的连接操作数据库
总结
DRUID连接池根据Properties对象中的数据作为连接池参数去创建连接池,我们自己定义properties类型的配置文件,名称自己取,也可以放到其他路径,建议放到src目录下方便加载。
不管是C3PO连接池,还是DRUID连接池,配置大致都可以分为2种:1、连接数据库的参数
2、连接池的参数,这2种配置大致参数作用都相同,只是参数名称可能不一样。
四、DRUID连接池工具类
我们每次操作数据库都需要创建连接池,获取连接,关闭资源,都是重复的代码。我们可以将创建连接池和获取连接池的代码放到一个工具类中,简化代码。
工具类步骤:
1、声明静态数据源成员变量
2、创建连接池对象
3、定义公有的得到数据源的方法
4、定义得到连接对象的方法
5、定义关闭资源的方法
使用连接池工具类后可以简化代码,我们只需要写SQL去执行。
DRUID连接池工具类代码
DataSourceUtils.java
/**
* 数据源工具类
*
* 数据源工具类实现步骤
* 1) 创建私有静态数据源成员变量 DataSource ds
* 2) 在静态代码块中创建连接池
* a) 创建属性集对象
* b) 从类路径下加载属性文件,得到输入流对象
* c) 通过工厂类创建一个数据源
* 3) 创建公有的得到数据源的方法 getDataSource()
* 4) 创建得到连接对象的方法 getConnection()
* 5) 创建释放资源的方法 close(Connction conn, Statement stmt, ResultSet rs)
*/
public class DataSourceUtils {
// 1) 创建私有静态数据源成员变量 DataSource ds
private static DataSource ds = null;
// 2) 在静态代码块中创建连接池
static {
try{
Properties info = new Properties();
// 4.2 加载配置信息到集合中
info.load(DruidDemo01.class.getResourceAsStream("/druid.properties"));
ds = DruidDataSourceFactory.createDataSource(info);
} catch(Exception e){
e.printStackTrace();
}
}
// 3) 创建公有的得到数据源的方法 getDataSource()
public static DataSource getDataSource(){
return ds;
}
// 4) 创建得到连接对象的方法 getConnection()
public static Connection getConnection(){
try {
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 5. 定义关闭资源的方法:close(Connection conn, Statement stmt, ResultSet rs)
public static void close(Connection conn, Statement stmt, ResultSet rs){
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();
}
}
}
// 重载关闭方法:close(Connection conn, Statement stmt)
public static void close(Connection conn, Statement stmt){
close(conn, stmt, null);
}
}
测试连接池工具类
使用数据源工具类获得连接对象并执行数据库操作。
/**
* 数据源工具类测试
*/
public class DataSourceUtilsDemo01 {
public static void main(String[] args)throws Exception {
// 1. 获得连接对象
Connection conn = DataSourceUtils.getConnection();
// 2. 获得预编译对象
PreparedStatement ps = conn.prepareStatement("delete from student where id = ?;");
// 3. 给占位符赋值
ps.setInt(1, 5);
// 4. 执行SQL,返回影响的行数
int row = ps.executeUpdate();
System.out.println(row);
// 5. 关闭资源
DataSourceUtils.close(conn, ps);
}
}
小结
数据源工具类实现步骤
- 创建私有静态数据源成员变量 DataSource ds
- 在静态代码块中创建连接池
a) 创建属性集对象
b) 从类路径下加载属性文件,得到输入流对象
c) 通过工厂类创建一个数据源 - 创建公有的得到数据源的方法 getDataSource()
- 创建得到连接对象的方法 getConnection()
- 创建释放资源的方法 close(Connction conn, Statement stmt, ResultSet rs)
五、连接池硬编码方式(了解)
硬编码方式实现连接池仅作了解即可。硬编码即参数都写死在源码中
使用纯代码获取配置连接池最大的弊端是:所有配置信息都写在代码中。一旦需要改配置信息,就需要改动源代码,非常麻烦。
准备数据
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT,
score DOUBLE DEFAULT 0.0 );
硬编码方式实现C3P0连接池
public class Demo01 {
public static void main(String[] args) throws Exception {
// 2.创建连接池对象ComboPooledDataSource对象
ComboPooledDataSource ds = new ComboPooledDataSource();
// 连接到数据库的相关参数
// 3.设置连接参数:driverClass , jdbcUrl, user, password
ds.setDriverClass("com.mysql.jdbc.Driver"); // 设置驱动的名称
ds.setJdbcUrl("jdbc:mysql://localhost:3306/day25");
ds.setUser("root");
ds.setPassword("root");
// 4.设置连接池参数
// a.初始连接数initialPoolSize
ds.setInitialPoolSize(5);
// b.最大连接数maxPoolSize
ds.setMaxPoolSize(10);
// c.最大等待时间checkoutTimeout
// Java程序去连接池中取连接,最长的等待时间,超过这个时间会有异常
ds.setCheckoutTimeout(5000);
// d.最大空闲回收时间maxIdleTime
// 连接池中的连接超过这个时间没有人使用,就会自动销毁
ds.setMaxIdleTime(3000);
Connection conn = ds.getConnection(); // 从一个连接池中取出一个连接
String sql = "INSERT INTO student VALUES (NULL, ?, ?, ?);";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "张三");
pstmt.setInt(2, 25);
pstmt.setDouble(3, 99.5);
int i = pstmt.executeUpdate();
System.out.println("INSERT 影响的⾏行行数:" + i);
pstmt.close();
conn.close(); // 将连接还回连接池中
}
}
硬编码方式实现DRUID连接池
public class Demo02 {
public static void main(String[] args) throws Exception {
DruidDataSource ds = new DruidDataSource();
// 设置连接参数
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://127.0.0.1:3306/day25");
ds.setUsername("root");
ds.setPassword("root");
// 设置连接池参数
ds.setInitialSize(5);
ds.setMaxActive(10);
ds.setMaxWait(3000);
ds.setMinIdle(3);
// 从连接池中取出连接
Connection conn = ds.getConnection();
// 执行SQL语句
String sql = "INSERT INTO student VALUES (NULL, ?, ?, ?);";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "王五");
pstmt.setInt(2, 35);
pstmt.setDouble(3, 88.5);
int i = pstmt.executeUpdate();
System.out.println("影响的行数: " + i);
pstmt.close();
conn.close(); // 将连接还回连接池中
}
}
转载:https://blog.csdn.net/qq_45942076/article/details/105832072