数据库连接池 - (druid、c3p0、dbcp)

时间:2021-12-09 19:35:56

概述:

在这里所谓的数据库连接是指通过网络协议与数据库服务之间建立的TCP连接。通常,与数据库服务进行通信的网络协议无需由应用程序本身实现。

原因有三:

  1. 实现复杂度大,需要充分理解和掌握相应的通信协议。
  2. 代码难以复用,每个应用程序都需要独立实现一套对应的网络协议(不同公司之间,同一公司的不同技术栈之间难以复用实现相同协议的代码)
  3. 性能难以保证,不同的网络协议实现可能存在巨大的性能差距。

正因为如此,所以现实的实现方式是:

首先,定义网络协议标准,这样只要支持这个标准协议的数据库就可以使用相应的客户端与之通信。

其次,将实现这个标准协议的客户端独立为一个通信库,这样只需要在应用程序中使用这个通信组件库就可以方便地实现与数据库进行交互。

通常,我们将实现了网络协议的通信库称之为数据库驱动程序。当然,对于不同的编程语言,需要对应编写相应的数据库驱动实现。以与关系型数据库通信为例,在Java中实现的驱动程序为JDBC,Python中的驱动程序为MySQLdb。

由于通过TCP与数据库建立网络连接的代价非常高昂,而且耗时(TCP建立连接需要“三次握手”,断开连接需要“四次握手”)。所以在实践中通常不直接单独使用连接进行数据库操作,而是使用连接池的方式,这主要是处于以下两方面的考虑:

  1. 应用程序本身需要更低的响应时间,如果每次数据库操作都需要经过“建立连接->通信(增删改查)->断开连接”这个过程,那么势必会导致响应延时的增加。
  2. 避免服务器资源被耗尽,随着业务量的增大,对应的数据库操作必然会随之增加,如果对客户端的连接数不加以控制,可能会导致数据库服务器的CPU和内存资源被大量的网络连接快速耗尽,这样将导致服务不可用。

数据库连接池 - (druid、c3p0、dbcp)

在Java中使用得比较流行的数据库连接池主要有:DBCP,c3p0,druid。
另外,不论使用什么连接池,低层都是使用JDBC连接,即:在应用程序中都需要加载JDBC驱动程序。

Druid:

概述:druid:阿里出品,淘宝和支付宝专用数据库连接池,支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。

Druid是Java语言中最好的数据库连接池,Druid能够提供强大的监控和扩展功能,是一个可用于大数据实时查询和分析的高容错、高性能的开源分布式系统,尤其是当发生代码部署、机器故障以及其他产品系统遇到宕机等情况时,Druid仍能够保持100%正常运行。

主要特色:为分析监控设计;快速的交互式查询;高可用;可扩展;Druid是一个开源项目,源码托管在github上。

Druid针对Oracle和MySql做了特别优化。

依赖Jar包:不分版本号

● druid-1.1.5.jar

● mysql-connector-java-8.0.14.jar

DruidDataSource dataSource = new DruidDataSource();
//获取驱动
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
//建立连接
dataSource.setUrl("jdbc:mysql://localhost:3306/class38?serverTimezone=Asia/Shanghai");
dataSource.setUsername("root");
dataSource.setPassword("123456");
try {
//获取连接
DruidPooledConnection conn = dataSource.getConnection();
PreparedStatement statement = conn.prepareStatement("insert into student values(?,?,?,?)");
statement.setInt(1, 13);
statement.setString(2, "小明");
statement.setString(3, "数据库");
statement.setInt(4, 150);
int i = statement.executeUpdate();
System.out.println(i);
} catch (SQLException e) {
e.printStackTrace();
}

设置配置文件:druid.properties

driverClassName = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/class38?serverTimezone=Asia/Shanghai
username = root
password = 123456

通过配置文件实现连接:

//建立工厂
DruidDataSourceFactory factory = new DruidDataSourceFactory();
Properties p = new Properties();
InputStream in = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
try {
//读取配置文件中的信息
p.load(in);
DataSource dataSource = factory.createDataSource(p);
Connection conn = dataSource.getConnection();
PreparedStatement statement = conn.prepareStatement("select * from student");
ResultSet result = statement.executeQuery();
while(result.next()){
System.out.println(result.getInt(1)+","+result.getString(2)+","+result.getString(3)+","+result.getInt(4));
}
} catch (Exception e) {
e.printStackTrace();
}

C3P0

开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。

数据库连接池C3P0框架是个非常优异的开源jar,高性能的管理着数据源,c3p0有两种数据源管理方式,一种是通过程序变本身来进行管理,还有一种是通过容器管理,

c3p0有自动回收空闲连接功能。单线程,性能较差,适用于小型系统,代码600KB左右。

依赖Jar包:不分版本号

● mysql-connector-java-8.0.14.jar

● c3p0-0.9.5.2.jar

● mchange-commons-java-0.2.11.jar

连接使用C3P0

1.1 - 使用Java API方式配置c3p0

ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/class38?serverTimezone=Asia/Shanghai");
dataSource.setUser("root");
dataSource.setPassword("123456");
Connection conn = dataSource.getConnection();
PreparedStatement statement = conn.prepareStatement("delete from student where id=?");
statement.setInt(1, 11);
int i = statement.executeUpdate();
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
}
}

1.2 - 直接在连接池中获取连接

DataSource ds = new ComboPooledDataSource();/
try {
Connection connection = ds.getConnection();
String sql = "select * from goods";
PreparedStatement prepareStatement = connection.prepareStatement(sql);// 设置sql语句
ResultSet executeQuery = prepareStatement.executeQuery();// 运行
while (executeQuery.next()) {
System.out.println("商品:" + executeQuery.getObject(2).toString());
}
executeQuery.close();
prepareStatement.close();
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

1.3 - 使用DBUtils工具连接:需要配置XML数据源,使用工具连接不需要close

//获取数据源,读取的是C3P0-config默认配置创建数据库连接池对象
DataSource ds = new ComboPooledDataSource();
//创建QueryRunner带参对象
QueryRunner queryRunner = new QueryRunner(ds);
//SQL UPDATE语句
String sql = "DELETE FROM type WHERE id in(?,?)";
//执行UPDATE语句,返回一个int类型的结果
int update = queryRunner.update(sql,6,7);
System.out.println(update);

② 使用c3p0.properties文件进行配置

数据源配置:c3p0.properties

需要在classpath路径下添加配置文件:c3p0.properties,内容如下:

c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://host:port/db
c3p0.user=root
c3p0.password=
c3p0.minPoolSize=5
c3p0.maxPoolSize=20
c3p0.acquireIncrement=5

在应用程序中只需要直接创建ComboPooledDataSource对象即可(c3p0会自动从classpath加载c3p0.properties中的配置信息):

ComboPooledDataSource cpds = new ComboPooledDataSource();
Connection conn = cpds.getConnection();
query(conn);
cpds.close();

注意: 使用c3p0.properties作为配置文件时,每个参数的name前缀必须是“c3p0”,如:“c3p0.driverClass=com.mysql.jdbc.Driver”。

使用c3p0-config.xml文件进行配置

数据源配置:c3p0-config.xml

使用这种方式会比使用c3p0.properties更加高级,支持配置多个数据源,同样需要在classpath路径下添加文件:c3p0-config.xml

<c3p0-config>
<!-- 这是默认配置信息 -->
<default-config>
<!-- 连接四大参数配置 -->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl"><!--CDATA里面的特殊符号都当字符串处理-->
<![CDATA[jdbc:mysql://localhost:3306/cakeshop?useUnicode=true&character=UTF-8&serverTimezone=GMT%2B8&useSSL=true]]>
</property>
<property name="user">用户名</property>
<property name="password">密码</property>
<!-- 池参数配置 -->
<property name="acquireIncrement">3</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">2</property>
<property name="maxPoolSize">10</property>
</default-config>
</c3p0-config>

在应用程序中只需要直接创建ComboPooledDataSource对象即可(c3p0会自动从classpath加载c3p0-config.xml中的配置信息):

// 使用默认数据源
// ComboPooledDataSource cpds = new ComboPooledDataSource(); // 使用指定名称的数据源
ComboPooledDataSource cpds = new ComboPooledDataSource("myDataSource");
Connection conn = cpds.getConnection();
query(conn);
cpds.close();

DBCP

由Apache开发的一个Java数据库连接池项目, Jakarta commons-pool对象池机制,Tomcat使用的连接池组件就是DBCP。

单独使用dbcp需要3个包,预先将数据库连接放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完再放回。

单线程,并发量低,性能不好,适用于小型系统。

依赖Jar包:不分版本号

● mysql-connector-java-8.0.14.jar

● commons-dbcp2-2.4.0.jar

● commons-pool2-2.6.2.jar

● commons-logging-1.2.jar

//创建连接池对象
BasicDataSource dataSource = new BasicDataSource();
//设置参数
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/class38?serverTimezone=Asia/Shanghai");
dataSource.setUsername("root");
dataSource.setPassword("123456");
try {
//获取连接对象
Connection conn = dataSource.getConnection();
//生成预编译Statement对象
PreparedStatement statement = conn.prepareStatement("insert into student values(null,?,?,?)");
statement.setString(1, "帅帅");
statement.setString(2, "大数据");
statement.setInt(3, 100);
//执行sql语句
int i = statement.executeUpdate();
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
}

配置文件内容:dbcp.properties

driverClassName = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/class38?serverTimezone=Asia/Shanghai
username = root
password = 123456

通过Properties配置文件连接:

BasicDataSourceFactory factory = new BasicDataSourceFactory();
Properties p = new Properties();
try {
InputStream in = DBCPDemo.class.getClassLoader().getResourceAsStream("dbcp.properties");
//加载配置文件
p.load(in);
//创建一个对象并返回
DataSource dataSource = factory.createDataSource(p);
Connection conn = dataSource.getConnection();
PreparedStatement statement = conn.prepareStatement("select * from student");
ResultSet result = statement.executeQuery();
while(result.next()){
System.out.println(result.getInt(1)+","+result.getString(2)+","+result.getString(3)+","+result.getInt(4));
}
} catch (Exception e) {
e.printStackTrace();
}

@ 转载至网络