引出数据库连接池
- 编写程序完成连接Mysql5000次的操作
- 看看有什么问题,耗时又是多少 = > 数据库连接池
测试代码
package com.taotao.jdbc.datasource;
import com.taotao.jdbc.utils.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
@SuppressWarnings({"all"})
public class ConQuestion {
@Test
public void testCon(){
for (int i = 0; i < 5000; i++) {
Connection connection = JDBCUtils.getConnection();
}
}
}
报出异常(too many connections)
测试连接后关闭(耗时)
测试代码
package com.taotao.jdbc.datasource;
import com.taotao.jdbc.utils.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
@SuppressWarnings({"all"})
public class ConQuestion {
@Test
public void testCon(){
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
Connection connection = JDBCUtils.getConnection();
JDBCUtils.close(null,null,connection);
}
long end = System.currentTimeMillis();
System.out.println("连接后及时关闭时,需要耗时:" + (end - start) + "毫秒");
}
}
测试结果
9088ms
传统获取Connection问题分析
- 传统的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证IP地址,用户名和密码(0.05s ~ 1s时间)。需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接操作将占用很多的系统资源,容易造成服务器崩溃。
- 每一次数据库连接,使用完后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄露,最终将导致重启数据库
- 传统获取连接的方式,不能控制创建的连接数量,如连接过多,也可能导致内存泄露,MySQL崩溃
- 解决传统开发中的数据库连接问题,可以采用数据库连接池技术(connection pool)
做图分析
数据库连接池种类
- JDBC的数据库连接池使用javax.sql.DataSource 来表示,DataSource只是一个接口,该接口通常由第三方提供实现【提供jar包】
- C3P0数据库连接池,速度相对较慢,稳定性不错(hibernate,spring)
- DBCP数据库连接池,速度相对C3P0较快,但不稳定
- Proxool数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
- BoneCP数据库连接池,速度快
- Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP,C3P0、Proxool优点于一身的数据库连接池
C3P0应用实例
使用代码实现c3p0数据库连接池,配置文件放src目录下
案例代码
package com.taotao.jdbc.datasource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;
@SuppressWarnings({"all"})
public class C3P0_ {
@Test
public void testC3P0_01() throws Exception {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password);
comboPooledDataSource.setInitialPoolSize(10);
comboPooledDataSource.setMaxPoolSize(50);
Connection connection = comboPooledDataSource.getConnection();
System.out.println("连接ok");
connection.close();
}
}
测试C3P0
package com.taotao.jdbc.datasource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;
@SuppressWarnings({"all"})
public class C3P0_ {
@Test
public void testC3P0_01() throws Exception {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password);
comboPooledDataSource.setInitialPoolSize(10);
comboPooledDataSource.setMaxPoolSize(50);
System.out.println("连接开始");
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
Connection connection = comboPooledDataSource.getConnection();
connection.close();
}
long end = System.currentTimeMillis();
System.out.println("连接结束,耗时:" + (end - start));
}
}
测试结果
649ms
XML文件测试连接
xml文件
<c3p0-config>
<named-config name="taotao">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/taotao_db01</property>
<property name="user">root</property>
<property name="password">12345</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">10</property>
<property name="maxStatements">5</property>
<property name="maxStatementsPerConnection">2</property>
</named-config>
</c3p0-config>
测试代码
package com.taotao.jdbc.datasource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
@SuppressWarnings({"all"})
public class C3P0_ {
@Test
public void testC3P0_02() throws SQLException {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("taotao");
Connection connection = comboPooledDataSource.getConnection();
System.out.println("连接成功");
connection.close();
}
}
测试结果
测试XML连接速度
@Test
public void testC3P0_02() throws SQLException {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("taotao");
System.out.println("开始连接");
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
Connection connection = comboPooledDataSource.getConnection();
connection.close();
}
long end = System.currentTimeMillis();
System.out.println("连接耗时:" + (end - start));
}
测试结果
734ms
德鲁伊应用实例
案例代码
package com.taotao.jdbc.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;
@SuppressWarnings({"all"})
public class Druid_ {
@Test
public void testDruid() throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
Connection connection = dataSource.getConnection();
System.out.println("连接成功");
connection.close();
}
}
测试德鲁伊
package com.taotao.jdbc.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;
@SuppressWarnings({"all"})
public class Druid_ {
@Test
public void testDruid() throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
Connection connection = dataSource.getConnection();
connection.close();
}
long end = System.currentTimeMillis();
System.out.println("连接耗时:" + (end - start));
}
}
测试结果
705ms
结论
德鲁伊在应用项目比较大时会非常快,比C3P0还要快,德鲁伊是阿里巴巴实现的
实现德鲁伊连接utils
utils源码
package com.taotao.jdbc.datasource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
@SuppressWarnings({"all"})
public class JDBCUtilsByDruid {
private static DataSource ds;
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\\druid.properties"));
ds = DruidDataSourceFactory.createDataSource(properties);
}catch(Exception e){
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
public static void close(ResultSet resultSet, Statement statement, Connection connection){
try {
if (resultSet != null){
resultSet.close();
}
if (statement != null){
statement.close();
}
if (connection != null){
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
测试德鲁伊utils
package com.taotao.jdbc.datasource;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
@SuppressWarnings({"all"})
public class JDBCUtilsByDruid_USE {
@Test
public void testSelect() {
Connection connection = null;
String sql = "select * from actor where Id = ?";
PreparedStatement preparedStatement = null;
ResultSet set = null;
try {
connection = JDBCUtilsByDruid.getConnection();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 2);
set = preparedStatement.executeQuery();
while (set.next()) {
int id = set.getInt("Id");
String name = set.getString("name");
String sex = set.getString("sex");
Date borndate = set.getDate("borndate");
String phone = set.getString("phone");
System.out.println(id + "\t" + name + "\t" + sex + "\t" + borndate + "\t" + phone);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtilsByDruid.close(set,preparedStatement,connection);
}
}
}
|