数据库链接的建立和关闭是极其耗费系统资源的操作。通过DriverManager获取的数据库连接,一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完后立即关闭连接。频繁的打开、关闭连接将造成系统性能的低下。
对于共享资源的情况,有一个通用版的设计模式:资源池。用于解决资源的频繁请求、释放所造成的性能下降。为了解决数据库连接的频繁请求、释放,JDBC2.0引入了数据库连接池技术。
数据库连接池,在系统启动时,就主动建立足够的数据库连接,并将这些连接组成一个连接池。每次应用程序请求数据库连接时,无须重新打开连接,而是从连接池中取出已有的链接使用,使用完毕后不再关闭数据库连接,而是直接将连接归还给连接池。
数据库连接池是Connection对象的工厂。数据库连接池的常用参数如下:
- 数据库的初始连接池
- 连接池的最大连接数
- 连接池的最小连接池
- 连接池每次增加的容量
JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由商用服务器等提供实现,也有一些开源组织提供实现(DBCP、C3P0)。
DataSource通常被称为数据源,它包含连接池和连接池管理两个部分,但习惯上也经常把DataSource称为连接池。
DataSource有三种类型的实现:
- 基本实现——生成标准Connection对象
- 连接池实现——生成自动参与连接池的Connection 对象。此实现与中间层连接池管理器一起使用。
- 分布式事务实现——生成一个Connection 对象,该对象可用于分布式事务,并且几乎始终参与连接池。此实现与中间层事务管理器一起使用,并且几乎始终与连接池管理器一起使用。DataSource对象的属性在需要时可以修改。例如,如果将数据源移动到另一个服务器,则可更改与服务器相关的属性。其优点是,因为可以更改数据源的属性,所以任何访问该数据源的代码都无需更改。
在Spring与Hibernate、Mybatis等ORM框架的整合过程中,DataSource扮演着非常重要的角色。
DBCP数据源
开源系统:common-pool。如果需要使用该连接池实现,则应在系统中增加如下两个jar文件。
- commons-dbcp.jar:连接池的实现
- commons-pool.jar:连接池实现的依赖库
Tomcat的连接池正是采用该连接池实现的。数据库连接池既可以与应用服务器整合使用,也可以由应用程序独立使用。
//创建数据源对象
BasicDataSource ds = new BasicDataSource();
//设置连接池所需的驱动
ds.setDriverClassName("com.mysql.jdbc.Driver");
//设置链接数据库的URL
ds.setUrl("jdbc:mysql://localhost:3306/javaee");
//设置连接数据库的用户名
ds.setUsername("root");
//设置连接数据库的密码
ds.setPassword("pass");
//设置连接池的初始连接数
ds.setInitialSize(5);
//设置连接池最多可有多少个活动连接数
ds.setMaxActive(20);
//设置连接池中最少有两个空闲的链接
ds.setMinTdle(2);
数据源和数据库连接不同,数据源无须创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。建议把上面的ds设置成static成员变量,并且在应用开始时立即初始化数据源对象,程序中所有需要获取数据库连接的地方直接访问该ds对象。并获取数据库连接即可。
// 通过数据源获取数据库连接
Connection conn = ds.getConnection();
当数据库访问结束后,关闭数据库连接。
// 释放数据库连接
conn.close();
C3P0数据源
相比之下,c3p0 的数据源性能更胜一筹,Hibernate推荐使用该连接池。C3P0连接池不仅可以自动清理不使用的Connection,还可以自动清理Statement和ResultSet。
c3p0-0.9.1.2.jar
//创建连接池实例
ComboPooledDataSource ds = new ComboPooledDataSource();
//设置连接池连接数据库所需的驱动
ds.setDriverClass("com.mysql.jdbc.Driver");
//设置链接数据库的URL
ds.setJdbcUrl("jdbc:mysql://localhost:3306/javaee");
//设置连接数据库的用户名
ds.setUser("root");
//设置连接数据库的密码
ds.setPassword("pass");
//设置连接池的最大连接数
ds.setMaxPoolSize(40);
//设置连接池的最小连接数
ds.setMinPoolSize(2);
//设置连接池的初始连接数
ds.setInitialPoolSize(5);
//设置连接池的缓存Statement的最大数
ds.setMaxStatements(180);
一旦获取了C3P0连接池之后,获取数据库连接:
Connection conn = ds.getConnection();