JDBC访问数据库操作详解(三)之数据库连接池:以MySQL为例
1. 数据库连接池简介
传统获取数据库连接的方式存在的问题:
- 每一次获取连接时都需要向数据库发送请求建立连接,耗时、效率低
- 访问结束后会断开与数据库的连接,下次访问时需要重新建立连接
- 并发访问量较大时,网站性能会受到很大的影响
- 安全性和稳定性相对较差
使用连接池技术:
- 原理:创建一个连接池pool,在该连接池创建时,会先向数据库申请建立多个连接(初始连接数),当用户需要连接时直接从连接池中获取即可
- 访问结束后会将连接归还给连接池,可以被其他用户重复使用
2. 常用连接池
开源的数据库连接池:
- dbcp
Apache开源项目,全程Database Connection Pool,也称为commons-dbcp
Apache是一个运作开源项目的非盈利性组织,提供了很多开源项目(jar包、软件)
Apache官网:http://www.apache.org/
-
druid
阿里巴巴的开源项目,俗称为“德鲁伊”
-
c3p0(已经没落)
3.用法
3.1 使用dbcp
添加jar包:commons-dbcp.jar、commons-pool.jar前者依赖于后者
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbcp2.BasicDataSource;
public class Test8 {
public static void main(String[] args) throws SQLException {
test01();
}
//基本用法
public static void test01() throws SQLException {
//创建数据库连接池(数据源)
BasicDataSource ds = new BasicDataSource();
//设置连接池的属性(参数)(驱动、url、用户名、密码也都要设置)
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/my_database?useUnicode=true"
+ "&characterEncoding=utf8&serverTimezone=GMT&rewriteBatchedStatements=true");
ds.setUsername("root");
ds.setPassword("aa677877");
//初始化连接数
ds.setInitialSize(10);
//设置最大的活跃连接数
ds.setMaxTotal(50);
//设置最大的空闲连接数,多余的空闲连接与数据库断开连接
ds.setMaxIdle(20);
//设置最小的空闲连接数
ds.setMinIdle(5);
//超时等待时间,单位为毫秒
ds.setMaxWaitMillis(6000);
//从连接池中获取连接
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
如果你和我一样出现了下图所示的异常的话,那你还需要去Apache下载一个commons-logging.jar
并添加到构建路径中
3.2 使用druid
添加jar包:druid-1.1.9.jar
下载地址:https://repo1.maven.org/maven2/com/alibaba/druid/
import java.sql.Connection;
import java.sql.SQLException;
import com.alibaba.druid.pool.DruidDataSource;
public class Test8 {
public static void main(String[] args) throws SQLException {
test01();
}
//基本用法
public static void test01() throws SQLException {
//创建数据库连接池(数据源)
DruidDataSource ds = new DruidDataSource();
//设置连接池的属性(参数)(驱动、url、用户名、密码也都要设置)
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/my_database?useUnicode=true"
+ "&characterEncoding=utf8&serverTimezone=GMT&rewriteBatchedStatements=true");
ds.setUsername("root");
ds.setPassword("aa677877");
//初始化连接数
ds.setInitialSize(10);
//设置最大的活跃连接数
ds.setMaxActive(50);
//设置最小的空闲连接数
ds.setMinIdle(5);
//超时等待时间,单位为毫秒
ds.setMaxWait(6000);
//从连接池中获取连接
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
3.3 dbcp与druid用法的区别
-
dbcp创建数据库连接池用的类是BasicDataSource,druid创建数据库连接池用的类是DruidDataSource
-
druid的setMaxActive()和setMaxWait()在dbcp2以后的版本中已经改名成setMaxTotal()和 setMaxWaitMillis()
-
dbcp需要调用setMaxIdle()设置最大活跃连接数;而druid中该方法已经过时,不需要设置
3.4 连接池基本用法进阶
在上面的代码中,连接池的属性是我们一个个固定写死了,那么将来如果要修改就会很麻烦。我们可以换一种做法,将信息存储到属性文件中,通过对属性文件中配置信息的读取来创建连接池。
import java.io.IOException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
public class Test8 {
public static void main(String[] args) {
test02();
}
//读取属性文件中的配置信息,创建连接池
public static void test02() {
//Properties是配置信息的集合,先在src下建一个datasource.properties文件来存放属性信息
Properties p = new Properties();
try {
//Properties集合使用load()方法读取属性文件,参数传入一个输入流
p.load(Test8.class.getClassLoader().getResourceAsStream("datasource.properties"));
//通过工厂创建DataSource
DataSource ds = BasicDataSourceFactory.createDataSource(p);
System.out.println(ds.getConnection());
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意:属性文件(datasource.properties)的写法
- 属性文件采用键值对的方法书写,格式为key=values
- key是之前使用一堆set方法设置时set后面的名字,首字母变成小写
4. 实战:改写学生管理(具体请参见之前博客)
主要功能:
学生管理
- 查询所有学生
- 根据学号查询学生
- 根据姓名和年龄范围查询学生
- 添加学生
- 修改学生
- 根据学号删除学生
班级管理
- 查询所有班级
- 根据班级号查询班级
- 添加班级
改写技术点:
- 使用连接池技术
- 实体类(entity):实体类对应数据库中的表,类的属性对应表的字段
- 简单的Java对象(pojo):Plain Ordinary Java Object,类中包含:属性/get/set/构造方法,不允许有业务逻辑
- 值对象(vo):Value Object,用于封装值/数据的对象,可自定义属性
源码会上传,感兴趣的朋友可以下载!