1.什么是数据库连接池?
数据库连接池(Database Connection Pooling)是一种在企业级软件开发中广泛使用的资源管理策略。它的主要目的是解决数据库连接频繁创建和销毁所带来的性能问题。数据库连接池作为一个容器,负责存储和管理数据库连接,并且可以根据应用程序的需求动态地分配、回收这些连接。
连接池的概念: 连接池就是一个容器,连接池中保存了一些数据库连接,这些连接是可以重复使用的。
2.Druid连接池
Druid 是一个开源的数据库连接池,由阿里巴巴集团开发。它旨在提供高性能、高可用性、可扩展性和透明化的数据库连接管理。Druid 结合了 C3P0、DBCP、Proxool 等数据库连接池的优点,并加入了日志监控功能,可以很好地监控数据库连接和 SQL 执行情况。
3.为什么选择Druid连接池
-
高性能:Druid 提供了对 JDBC 的优化实现,减少了数据库连接创建和销毁的开销,从而提高了性能。
-
高可用性:Druid 支持自动重连,可以在数据库连接断开后自动重新连接,保证了应用的持续可用性。
-
可扩展性:Druid 支持动态扩展,可以根据应用的需求动态调整最大连接数等参数。
-
透明化:Druid 对数据库连接的创建、使用和销毁过程进行了日志记录,方便开发者监控和调试。
-
监控功能:Druid 内置了监控功能,可以实时显示数据库连接的使用情况,包括连接数、活跃连接数、等待连接的线程数等。
-
支持多种数据库:Druid 支持多种数据库,包括 MySQL、Oracle、PostgreSQL、SQL Server 等。
-
配置灵活:Druid 提供了丰富的配置项,可以满足不同应用的需求。
4.配置和使用Druid连接池
com.alibaba.druid.pool.DruidDataSourceFactory类有创建连接池的方法
public static DataSource createDataSource(Properties properties) 创建一个连接池,连接池的参数使用properties中的数据
我们可以看到Druid连接池在创建的时候需要一个Properties对象来设置参数,所以我们使用properties文件来保存对应的参数。Druid连接池的配置文件名称随便,放到src目录下面方便加载
druid.properties文件内容:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db1
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
druid的使用步骤:
1.导入druid.jar的jar包
2.复制druid.properties文件到src下,并设置对应参数
3.加载properties文件的内容到Properties对象中
4.创建Druid连接池,使用配置文件中的参数
5.从Druid连接池中取出连接
6.执行SQL语句
7.关闭资源
5.使用Druid连接池
在我们配置好Druid连接池以后,就可以使用它来获取数据库的连接和执行SQL语句
以下是一个简单的实例:
创建数据库连接池的工具类:
public class DruidDateUtils {
//静态资源可以被使用
public static DataSource ds = null;
//如果资源只需要加载一次,后续使用的都是同样的资源,可以直接写在静态代码块里面
static {
try {
//3.加载properties文件的内容到Properties对象中
Properties pp = new Properties();
FileInputStream fis = new FileInputStream("配置路径druid.properties");
pp.load(fis);
// 4.创建Druid连接池,使用配置文件中的参数
ds = DruidDataSourceFactory.createDataSource(pp);
fis.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//提供给别人获取连接池中连接的方法工具类中方法经常被别人调用,有异常一般是是调用谁处理
public static Connection getConnection() throws Exception{
return ds.getConnection();
}
}
连接池的使用:
public class Demo {
public static void main(String[] args) throws Exception{
// 从Druid连接池中取出连接
Connection cn = DruidDateUtils.getConnection();
// 执行SQL语句,预编译的方式
String sql = "insert into user values (null,?,?);";
// 创建预编译的对象
PreparedStatement pstate = cn.prepareStatement(sql);
pstate.setString(1,"jack");
pstate.setString(2,"123123");
int row = pstate.executeUpdate();
System.out.println(row);
// 关闭资源
pstate.close();
//使用连接池之后,这里的cn.close()不是关闭连接,而是放回连接池
cn.close();
}
}
总结:这是一个简单的Druid连接池使用的示例,我们首先定义了一个Druid的工具类,并在使用中直接使用工具类来获取数据库的连接,然后关闭资源放回连接。
6.应用了Druid连接池的一个简单案例
建表代码:
-- 删除tb_brand表
DROP TABLE IF EXISTS tb_brand;
-- 创建tb_brand表
CREATE TABLE tb_brand
(
-- id 主键
id INT PRIMARY KEY AUTO_INCREMENT,
-- 品牌名称
brand_name VARCHAR(20),
-- 企业名称
company_name VARCHAR(20),
-- 排序字段
ordered INT,
-- 描述信息
DESCRIPTION VARCHAR(100),
-- 状态:0:禁用 1:启用
STATUS INT
);
-- 添加数据
INSERT INTO tb_brand (brand_name, company_name, ordered, DESCRIPTION, STATUS)
VALUES ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1);
SELECT * FROM tb_brand;
Brand类:用来保存数据库tb_brand表数据的
public class Brand {
private Integer id;
private String brandName;
private String companyName;
private Integer ordered;
private String description;
private Integer status;
public Brand() {
}
public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {
this.id = id;
this.brandName = brandName;
this.companyName = companyName;
this.ordered = ordered;
this.description = description;
this.status = status;
}
/**
* 获取
* @return id
*/
public Integer getId() {
return id;
}
/**
* 设置
* @param id
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取
* @return brandName
*/
public String getBrandName() {
return brandName;
}
/**
* 设置
* @param brandName
*/
public void setBrandName(String brandName) {
this.brandName = brandName;
}
/**
* 获取
* @return companyName
*/
public String getCompanyName() {
return companyName;
}
/**
* 设置
* @param companyName
*/
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
/**
* 获取
* @return ordered
*/
public Integer getOrdered() {
return ordered;
}
/**
* 设置
* @param ordered
*/
public void setOrdered(Integer ordered) {
this.ordered = ordered;
}
/**
* 获取
* @return description
*/
public String getDescription() {
return description;
}
/**
* 设置
* @param description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* 获取
* @return status
*/
public Integer getStatus() {
return status;
}
/**
* 设置
* @param status
*/
public void setStatus(Integer status) {
this.status = status;
}
public String toString() {
return "Brand{id = " + id + ", brandName = " + brandName + ", companyName = " + companyName + ", ordered = " + ordered + ", description = " + description + ", status = " + status + "}";
}
}
测试代码:
/**
* 品牌数据的增删改查操作
*/
public class BrandTest {
public static void main(String[] args) throws Exception {
// queryAll();
// add();
// update();
// delete();
}
private static void delete() throws Exception {
//1.获取连接
Connection cn = DruidDateUtils.getConnection();
//2.编写SQL语句
String sql = "DELETE FROM tb_brand WHERE id=?;";
//3.生成对应的预编译对象
PreparedStatement pstate= cn.prepareStatement(sql);
//3.1设置?参数
pstate.setInt(1,3);
//4.执行SQL
int row = pstate.executeUpdate();
//5.处理返回的结果
System.out.println(row);
//6.释放资源
pstate.close();
cn.close();
}
private static void update() throws Exception {
//1.获取连接
Connection cn = DruidDateUtils.getConnection();
//2.编写SQL语句
String sql = "UPDATE tb_brand SET brand_name =?,company_name =?,ordered =?,description =?,status =? where id = ?;";
//3.生成对应的预编译对象
PreparedStatement pstate = cn.prepareStatement(sql);
//3.1设置?参数
pstate.setString(1,"OPPO");
pstate.setString(2,"OPPO有限公司");
pstate.setInt(3,1);
pstate.setString(4,"充电五分钟,通话两小时");
pstate.setInt(5,1);
pstate.setInt(6,1);
//4.执行SQL
int row = pstate.executeUpdate();
//5.处理返回的结果
System.out.println(row);
//6.释放资源
pstate.close();
cn.close();
}
private static void add() throws Exception {
//1.获取连接
Connection cn = DruidDateUtils.getConnection();
//2.编写SQL语句
String sql = "INSERT INTO tb_brand VALUES (null,?,?,?,?,?);";
//3.生成对应的预编译对象
PreparedStatement pstate = cn.prepareStatement(sql);
//3.1设置?参数
pstate.setString(1,"Redmi");
pstate.setString(2,"小米科技有限公司");
pstate.setInt(3,1);
pstate.setString(4,"做好产品");
pstate.setInt(5,1);
//4.执行SQL
int row = pstate.executeUpdate();
//5.处理返回的结果
System.out.println(row);
//6.释放资源
pstate.close();
cn.close();
}
private static void queryAll() throws Exception {
//1.获取连接
Connection cn = DruidDateUtils.getConnection();
//2.编写SQL语句
String sql = "SELECT * FROM tb_brand ;";
//3.生成对应的预编译对象
PreparedStatement pstate = cn.prepareStatement(sql);
//4.执行SQL
ResultSet rs = pstate.executeQuery();
//用集合来获取所得信息
List<Brand> list = new ArrayList<>();
//5.处理返回的结果
while (rs.next()){
//获取数据
int id = rs.getInt("id");
String brandName = rs.getString("brand_name");
String companyName = rs.getString("company_name");
int ordered = rs.getInt("ordered");
String description = rs.getString("description");
int status = rs.getInt("status");
Brand brand = new Brand(id, brandName, companyName, ordered, description, status);
list.add(brand);
}
//6.释放资源
rs.close();
pstate.close();
cn.close();//还给数据库连接池
//打印数据
list.forEach(System.out::println);
}
}
7.总结
数据库连接池是现代软件架构中不可或缺的一部分,它确保了数据库资源的高效利用,并提升了应用程序的整体性能。Druid 连接池是一个功能丰富、适用于多种场景下的数据库连接池工具,能够帮助企业级应用提高性能、保证高可用性,并简化数据库连接管理。在实际开发中,根据我们的需求配置并使用Druid连接池,有助于我们提高资源的利用率,不过也要记得使用完及时关闭资源,以避免泄露。