为什么必须使用数据库连接池:
使用连接池和不使用连接池的区别在哪里?上
普通的JDBC数据库连接(Connection对象)使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s~1s的时间)—->建立JDBC连接的开销(成本)是很多。
需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。
数据库的连接资源并没有得到很好的重复利用.若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。
对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。
这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃.
连接池最大的好处: 重复利用了每一个Connection对象,节省了性能开销.
连接池概述:
在Java中,连接池使用javax.sql.DataSource接口来表示连接池/数据源.
注意:DataSource和JDBC一样仅仅只是一个接口,由各大服务器厂商来实现(Tomcat,JBoss等).
DataSource(数据源)和连接池(Connection Pool)是同一个.
如何获取连接对象:
没有连接池: 通过DriverManager来获取,直接和DBMS连接.
存在连接池: 直接通过连接池来获取连接对象.
Connection conn = DataSource对象.getConnection();
释放连接对象:
没有连接池: conn.close():和数据库服务器(DBMS)断开连接.
存在连接池: conn.close():把Connection对象归还给连接池,并没有和DBMS断开.
接下来介绍主流的几个连接池项目之一
DBCP连接池和Druid连接池对比:
常用的DataSource的实现:
C3P0: Hibernate推荐的,但是该连接池在07年之后就不再更新了,不建议使用:性能太太差了.
DBCP: Apache组织的项目,Spring推荐的. 真心不错.
Druid连接池(德鲁伊),阿里巴巴的连接池,世界上最好的连接池.
https://github.com/alibaba/druid/wiki
Java语言领域性能最好的数据库连接池//性能超群
类似于DBCP连接池.
连接池(Connection pool)管理连接Connection对象
数据源(DataSource)用来连接数据库,创建连接Connection对象
另外要提及的一点是:Druid和DBCP的连接属性是完全相同的,创建连接池的对象不同.
DBCP和Druid连接池使用代码如下除了几条语句不一样之外,其他代码都一样:
public class DBCPTestDemo {
/**
*使用dbcp连接池来做操作 需要添加2个jar包
* commons-dbcp.jar
* commons-poor.jar
* 使用Druid连接池做操作 需添加的jar包
* druid.jar
* 连接池连接数据库 然后客户端从连接池中获取连接对象
* 这里记得方法后可以传入一个URL参数 这里就不传入直接设置URL做测试
*/
@Test
public void testDruid() throws Exception {
String sql = "SELECT * FROM t_student";
//BasicDataSource dataSource = new BasicDataSource();//DBCP
DruidDataSource dataSource = new DruidDataSource();//Druid
//以上是二种不同连接池下的DataSource对象获取区别
dataSource.setUsername("root");
dataSource.setPassword("admin");
dataSource.setUrl("jdbc:mysql:///jdbc");
Connection conn = dataSource.getConnection();
//利用datasource连接池对象中的getConnection()方法获取Connection连接对象.
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet set = ps.executeQuery();
while (set.next()) {
long id = set.getLong("id");
String name = set.getString("name");
int age = set.getInt("age");
System.out.println("id=" + id + "name=" + name + "age=" + age );
}
jdbcUtil.close(conn, ps, set);
}
}
拓展:利用properties文件来解决硬编码问题,将数据库连接池的属性内容存于此文件中.
DBCP的properties文件代码(Druid连接池的properties文件属性一致):
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///jdbc
username=root
password=admin
maxActive=5//此值是设置连接池的最大连接数
将获取连接池中的Connection对象封装成为一个Util工具类:
public class DruidUtil {
private static DataSource dataSource;
static{
try {
Properties p = new Properties();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream input = loader.getResourceAsStream("druid.properties");
p.load(input);
//以下是二种不同连接池获取Datasource对象的区别对比:
//dataSource = BasicDataSourceFactory.createDataSource(p);//DBCP
dataSource = DruidDataSourceFactory.createDataSource(p);//Druid
//对比以上二条代码,比较可以看出DBCP连接池和Druid连接池获取datasource对象的方式别无差异
} catch (Exception e) {
throw new RuntimeException("加载classpath根路径下的dbcp.properties文件失败",e);
}
}
public static Connection getConn()
{
try {
return dataSource.getConnection();
} catch (Exception e) {
throw new RuntimeException("数据库连接异常",e);
}
}
public static void close(Connection conn, Statement st, ResultSet res) {
//释放资源Util抽取
try {
if (st != null) {
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
测试执行申请归还连接1,000,000(一百万)次总耗时性能对比。
Java6的环境下:
Java7的环境下:
结论1.Druid是性能最好的数据库连接池,tomcat-jdbc和druid性能接近。
2.proxool在激烈并发时会抛异常,完全不靠谱。
3.c3p0和proxool都相当慢,慢到影响sql执行效率的地步。
4.bonecp性能并不优越,采用LinkedTransferQueue并没有能够获得性能提升。
5.除了bonecp,其他的在JDK 7上跑得比JDK 6上快
6.jboss-datasource虽然稳定,但是性能很糟糕
而且可以目前的所有的数据库连接池中Druid还提供更新支持,以及有很多强大的功能,例如SQL语句检查和日志分析功能等.反正以后就使用Druid连接池就可以了,即使当前你企业的连接池配置是DBCP以及其他的,也能很快的转配成Druid的.