数据库连接池

一、为什么使用数据库连接池

       用户每次请求都需要向数据库获得连接,而数据库创建连接通常要消耗相对较大的资源,创建时间也长。假设网站一天10万的访问量,数据库服务器就需要创建10万次连接,极大浪费数据库的资源,并且极易造成数据库服务器内存溢出、宕机。连接池工作原理图:

 

             应用程序一开始就向数据库要了一批连接构成连接池,用户访问 Servlet,Servlet 向 Dao 要数据,此时 Dao 层不是直接向数据库要连接,而是向连接池中拿一个空闲的连接。当 Dao 用完连接以后,将连接还给连接池。

 

二、编写数据库连接池

       1、编写连接池需要实现 java.sql.DataSource 接口。DataSource 接口中定义了两个重载的 getConnection 方法:

              Connection.getConnection();

              Connection.getConnection(String username, String password);

         2、实现 DataSource 接口并实现连接池功能的步骤:

              在 DataSource 构造函数中批量创建与数据库的连接,并把创建连接加入到 LinkedList 对象中。实现 getConnection 方法,让 getConnection 方法每次调用时,从 LinkedList 中取一个 Connection 返回给用户。当用户使用完 Connection 对象应保证将连接返回到 LinkedList 中,而不是还给数据库。

 

              在自己编写数据库连接池时,我们要考虑到,从数据库获取连接的时候容易,但是当用户用完连接,调用 connection.close() 方法的时候,会直接将连接交还给数据库而不是再放回连接池中。所以我们要动态的改变 connection 方法。有三种方式可以实现 (1)写一个 connection 的子类,复写所有方法。但是这种方法有一个问题,因为 connection 对象中封装了太多数据,我们如何将 connection 的数据拷贝到我们当前的子类中呢?这是一个复杂的过程。(2)用装饰模式,装饰模式可以动态的为一个类增加新功能。装饰模式有几个步骤,首先装饰类和被装饰类要有一个共同的父接口,其次装饰类中维护着一个被装饰类的对象,同时在装饰类的构造函数中要将被装饰的对象传进来,目的是赋值。然后我们可以为根据需求增加修改原来的功能。当我们要使用被装饰类的时候,我们给用户返回的是我们装饰后的对象,  从而达到目的。但是装饰模式比较适用于简单类,不适合用于方法多的对象,因为我们有时仅仅需要修改一部分功能,而其它功能还是希望调用被装饰类本身的方法,那么这样我们就必须一个一个方法进行修改,来调用被装饰类的方法,这个工程非常庞大。(3)使用动态代理,动态代理可以实现拦截对对象的直接访问。如果我们想修改某一个方法,只需要在调用对象之前进行判断即可,如果是我们想修改的,我们直接拦截,如果不是我们想要的,我们可以直接交给被代理对象处理。由于动态代理是基于代理对象和被代理对象要有相同接口,所以我们可以基于接口统一调用,运行时以多态的形式表现出来。

 

public class DataSourcePool {

	private static LinkedList<Connection> list = new LinkedList<Connection>();

	static {
		for (int i = 0; i < 5; i++) {
			Connection con = DBHelper.getConnection();
			list.add(con);
		}
	}

	public Connection getConnection() throws SQLException {
		if (list.size() > 0) {
			System.out.println("当前连接池有:" + list.size() + "个连接");
			final Connection con = list.removeFirst();
			System.out.println("当前连接池有:" + list.size() + "个连接");
			return (Connection) Proxy.newProxyInstance(DataSourcePool.class.getClassLoader(), con.getClass().getInterfaces(), new InvocationHandler() {

				public Object invoke(Object proxy, Method method, Object[] args)
						throws Throwable {
					String methodName = method.getName();
					if(methodName.equals("close")){
						list.add(con);
						System.out.println("当前连接池有:" + list.size() + "个连接");
						return null;
					}else{
						return method.invoke(con, args);
					}
				}

			});
		}
		return null;
	}
}

 

三、开源数据库连接池

       现在很多 Web 服务器都提供了 DataSource 的实现,即连接池的实现,通常我们把 DataSource 的实现按英文含义称之为数据源。也有一些开源组织提供了数据源的独立实现:DBCP、C3P0、apache dbcp,Tomcat 内置的 dbcp 也就是 DBCP。

 

          1、DBCP

               DBCP 是 Apache 软件组织下的开源连接池,使用 DBCP 数据源,应用程序应在系统中增加两个 jar 包:Commons-dbcp.jar(连接池的实现)、Commons-pool.jar(连接池实现的依赖库),DBCP 连接池既可以与应用服务器整合使用,也可以由应用程序独立使用。

               BasicDataSourceFactory factory = new BasicDataSourceFactory();

               factory.createDateSource(P);

               在创建数据源的时候,DBCP 采用的是读取配置文件的形式,返回一个 DataSrouce。DBCP 是采用装饰模式来创建连接池的。

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day15
username=root
password=root

#<!-- 初始化连接 -->
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000


 

        2、c3p0

              c3p0 在创建连接池的时候,可以手动指定连接的方式,也可以通过 xml 和配置文件的形式创建连接池。

              ComboPooledDataSource source = new ComboPooledDataSource("配置名");

 

        3、配置 Tomcat 内置 dbcp 连接池

             Tomcat 采用的是 JNDI 容器存放连接的,在服务器启动的时候,会在 JNDI 容器中创建一批连接,应用程序需要连接的时候直接在 JNDI 容器中查找。我们在使用时首先应该初始化 JNDI ,然后获取 Tomcat 中 JNDI 容器,最后在 JNDI 容器中检索连接池。

                          Context initCtx = new InitialContext();
			Context envCtx = (Context) initCtx.lookup("java:comp/env");
			DataSource source = (DataSource) envCtx.lookup("jdbc/EmployeeDB");


 

 

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值