数据库连接池DataSource


什么是数据库连接池

数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。

以下是使用连接池与没有使用连接池的一个比较图例



连接池的优点

节省创建连接与释放连接性能消耗

连接池中连接起到复用的作用,提供程序性能

其实使用连接池的时候,也是有点缺点的:

在程序最开始的时候必须加载连接池对象,所以肯定会消耗较多的资源,但是也比每次都创建连接消耗资源强。

连接池的原理

连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

用通俗的话来说就是:弄一个集合,扔几个连接对象到集合(连接池)中,当用户需要获取连接时,从集合(连接池)中取出一个,使用完后再重新放回集合(连接池)中,以供下一次再使用,也就是连接池中的对象是可以重复使用的。


在了解了连接池实现的源码后我试着模拟写一个简单版的连接池大概实现原理

public class MyDataSource {

	private LinkedList<Connection> ll;

	public MyDataSource() throws SQLException {
		ll = new LinkedList<Connection>();
		//当创建MyDataSource时就会向集合中添加10个Connection对象。
		for (int i = 0; i < 10; i++) {
//使用自己封装的JdbcUtils工具类获取一个连接对象
			ll.add(JdbcUtils.getConnection());
		}
	}

	// 获取连接,将集合中的connection返回一个
	public Connection getConnection() {
		return ll.removeLast();
	}
	// 关闭连接,将连接对象重新再放回集合中去
	public void closeConnection(Connection con) {
		ll.addFirst(con);
	}
}
下面是使用上面自己创建的数据库连接池

public class DataSourceDemo1 {
 
public static void main(String[] args) throws SQLException {
String sql = "select * from account";
// 创建一个连接池
MyDataSource mds = new MyDataSource();
// 从连接池中获取一个连接对象
Connection con = mds.getConnection();
 
ResultSet rs = con.prepareStatement(sql).executeQuery();
 
while (rs.next()) {
System.out.println(rs.getInt("id") + "  "
+ rs.getString("username") + "  " + rs.getString("money"));
}
 
rs.close();
//mds.closeConnection(con);//将连接对象重新放回到池中。
con.close();
}
}

连接池规定

javax.sql包下有一个 DataSource

所有的支持java的连接池都应该实现javax.sql.DataSource接口,在这个接口中提供了一个方法  getConnection()它就是获取一个连接对象的。

 

如果连接对象Connection是通过连接池获取的,当通过Connection对象调用close()方法时,不是销毁连接对象,而是将连接对象放回到连接池。所以Connection对象调用close()方法时,具体做什么操作需要看这个Connection对象是怎么来的。

1,如果就是普通获取(驱动管理器DriverManager),那么close()就是关闭连接。

2,如果是通过连接池(DataSource)获取,那么close()就是将连接对象重新放回连接池中。

具体实现方式是使用了动态代理在实现了DataSource接口后对父类Connection的方法进行了重写。


毕竟在开发中,数据库连接池不会让我们去实现,了解了数据库连接池的大概原理后,让我们来看看常用的数据库连接池有哪些以及在开发如何使用。

连接池的使用在项目中一般可以分为两种,一种是直接在java代码中以编码的方式实现,另一种则是通过加载配置文件的方式。

Dbcp连接池(了解)


DBCP Apache 软件基金组织下的开源连接池实现,使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:

Commons-dbcp.jar:连接池的实现

Commons-pool.jar:连接池实现的依赖库

Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。DBCP Apache 软件基金组织下的开源连接池实现,使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:

Commons-dbcp.jar:连接池的实现

Commons-pool.jar:连接池实现的依赖库

Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。


dbcp连接池编码实现

// 1.创建连接池对象
BasicDataSource ds = new BasicDataSource();
// 2.设置相关属性
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql:///day13");
ds.setUsername("root");
ds.setPassword("abc");

dbcp连接池配置文件实现
//1.加载配置信息
Properties props = new Properties();//创建了一个map集合					
props.load(new FileInputStream(properties配置文件路径);
		
properties文件内容
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///数据库名
username=root
password=root

// 2.通过BasicDataSourceFactory获取一个连接池对象
DataSource ds = BasicDataSourceFactory.createDataSource(props);


C3p0连接池


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

c3p0dbcp区别

dbcp没有自动回收空闲连接的功能

c3p0有自动回收空闲连接功能

在使用c3p0连接池时将c3p0jar 复制WEB-INF/lib下,我们使用的版本

c3p0-0.9.1.2.jar


c3p0连接池编码实现

ComboPooledDataSource ds = new ComboPooledDataSource();
// 2.手动配置参数
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql:///day13");
ds.setUser("root");
ds.setPassword("abc");


c3p0连接池配置文件实现

如果配置文件名称是  c3p0.propertiesc3p0-config.xml

那么c3p0就会默认在classpath根目录下查找这个配置文件。

只要在src下创建c3p0.properties or c3p0-config.xml名称的配置文件,c3p0会自动查找.
ComboPooledDataSource ds = new ComboPooledDataSource();
自动查找配置文件
在src/c3p0-config.xml
<c3p0-config>
	<default-config>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql:///数据库名</property>
		<property name="user">root</property>
		<property name="password">abc</property>
	</default-config>
</c3p0-config>

连接池的工具类

public class DataSourceUtils {

	private static ComboPooledDataSource cpds = new ComboPooledDataSource();//自动去加载c3p0-config.xml配置文件读取数据库连接相关信息
	//获取连接对象,从连接池中返回一个连接对象
	public static Connection getConnection() throws SQLException {
		return cpds.getConnection();
		
	}
	//获取连接池对象
	public static DataSource getDataSource() {
		return cpds;
	}

}







猜你喜欢

转载自blog.csdn.net/huangyuhuangyu/article/details/78012244