数据库连接池

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

       用户每次请求都需要向数据库获得连接,而数据库创建连接通常要消耗相对较大的资源,创建时间也长。假设网站一天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
    评论
数据库连接池配置<br><br>环境:xp2+IE7.0+tomcat5.028+mysql5.018<br><br>1.假定tomcat 安装目录为:D:\Tomcat5<br><br>2.假定程序目录为: D:\web\WebRoot<br><br> 目录设置请看WebRoot.xml 中有下面这句代码:<br><br> <Context path="/WebRoot" docBase="D:/web/WebRoot" debug="0" reloadable="true" ><br><br>3.假定mysql数据库名为:mydb,登录用户名为:root,密码为:123<br> 请看WebRoot.xml 中有下面这句代码:<br><br> <parameter><br> <name>username</name><br> <value>root</value><br> </parameter><br> <parameter><br> <name>password</name><br> <value>123</value><br> </parameter><br><br> <parameter><br> <name>url</name><br> <value>jdbc:mysql://localhost:3306/mydb?autoReconnect=true</value><br> </parameter><br><br><br>4. 请将 WebRoot.xml copy到<br> D:\Tomcat5\conf\Catalina\localhost\下<br> 数据库的配置就在这个文件中<br><br>5. 文件mysql-connector-java-5.0.5-bin.jar 存放于<br> D:\web\WebRoot\WEB-INF\Lib\下,最好在也存一个在<br> D:\Tomcat5\common\lib\下<br><br>6. 我所有配置都没有设计到tomcat的server.xml,有的人在这个文件中做了数据库<br> 的配置是没有必要的,因为WebRoot.xml已经有了这些配置。<br><br>7. web.xml配置 <br><br><web-app xmlns="http://java.sun.com/xml/ns/j2ee"<br> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br> xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee<br>http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"<br> version="2.4"><br> <description>MySQL Connection</description><br> <resource-ref><br> <description>DB Connection</description><br> <res-ref-name>jdbc/mysql</res-ref-name><br> <res-type>javax.sql.DataSource</res-type><br> <res-auth>Container</res-auth><br> </resource-ref><br><br></web-app><br><br>8 .<br> <!-- <br> ======================================================<br> 数据库操作 采用JNDI 连接<br> <br> ======================================================<br>--><br> <%<br> Context ctx=new InitialContext();<br> if(ctx==null)<br> {throw new Exception("没有匹配的环境"); }<br> DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/mysql");<br> if(ds==null)<br> {throw new Exception("没有匹配数据库"); }<br> <br> con=ds.getConnection();<br><br> sql=con.createStatement();<br> <br>%><br><br><br>附:<br><br>最后完成的目录及文件:<br><br>1)D:\Tomcat5\conf\Catalina\localhost\WebRoot.xml <br><br>2)D:\web\WebRoot\WEB-INF\web.xml<br><br><br>3) D:\web\WebRoot\WEB-INF\lib\mysql-connector-java-5.0.5-bin.jar<br> D:\Tomcat5\common\lib\mysql-connector-java-5.0.5-bin.jar(不是必须的)<br><br>4)D:\web\WebRoot\ mysql_JNDI.jsp<br><br><br>最后运行:<br> http://localhost/WebRoot/mysql_JNDI.jsp (我的端口号: 80)<br><br>OK<br>

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值