数据库连接池之Proxool使用
如果想要搭建一个高效的网站,链接池是必须用到的一部分。而连接池的选择是多种多样的。就现在的软件开发界而言,最为多用的是DBCP, c3p0, 和 proxool。而hibernate推荐使用的是c3p0 和proxool,并且宣布不再支持DBCP。 因此,重点就是如果想要在自己的应用程序中加入数据库连接池,就必须掌握其中的一种,而最好得选择就是c3p0和proxool中的任何一种。
下面来说说数据库连接池的相关概念和基本原理,以便于读者更加容易的理解后边的实际应用。
使用过数据库操作的人都知道,当我们需要进行数据库操作时,首先需要对数据库进行连接,然后执行操作,再然后我们使用完毕后需要将数据库关闭。如果在使用后没有关闭数据库连接,那么,这个连接就一直在占用状态。当使用的人数增加,连接也增加,系统会很快就崩溃。在超过负荷之后直接down掉!!!这就是在程序中没有及时的关闭数据库连接的危害。但是,这种每使用一次就连接和关闭一次数据库连接其实际上是对数据库有一定的影响的。因此,才有了数据库连接池的概念。
数据库连接池实际上就是在程序加载时就按照设置的数量先和数据库建立一定量的连接,当需要数据库连接时就直接从最开始建立的连接中取得所需要的连接就行。当不需要时,只需要将连接还给连接池;当建立的连接被取用完后,并且还存在后续的请求,也就是说现在的连接数量已经超过了系统设置的最大连接数。那么,后面的请求只有等待!!
百度给出的解释是:
作者:itRed 邮箱:it_red@sina.com 博客:http://www.cnblogs.com/itred
在进行正式开放之前,了解一下几个专用术语:
maximum-connection-count:最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定
minimum-connection-count:最小连接数(默认2个)
house-keeping-sleep-time:proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒
maximum-new-connections:没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受
prototype-count :最少保持的空闲连接数(默认2个)
test-before-use:在使用之前测试
house-keeping-test-sql:用于保持连接的测试语句
好了!看看具体的实例应用就会明白以上所说的相关概念了。本人按java和web工程来叙述案例,需要声明一下,proxool的应用是没有固定的形式了。并不是只能在java中应用它的xml形式。它的配置可以以任何形式运行。具体的看它的官方文档。本人主要以理解为首,开发为主。因此以web和java工程区分。
先说一下数据库的数据
Demo 1. 在java工程中添加proxool连接池
一.新建java工程,在目录下直接见一个lib包,用来存放项目工程所有的jar包,导入相关的jar包,然后build path。利用proxool实现连接池的jar包如下:
二. 在src目录下新家一个测试包,附加一个测试类Test.java:
包名:com.red.test
Test.java的源码如下:
package com.red.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.Statement; import org.logicalcobwebs.proxool.configuration.JAXPConfigurator; public class Test { public static void main(String[] args) throws Exception { Test obj = new Test(); obj.test2(); } int beginIndex = 0; int endIndex = 10; //取10条记录 String MySQLdbTableName = "user"; String MySQLreq = "select * from " + MySQLdbTableName + " limit " + beginIndex + ", " + endIndex; public void test2() throws Exception { // Java应用中先要加载配置文件,否则谁知道你配置给谁用的 JAXPConfigurator.configure("src/proxool.xml", false); // 1:注册驱动类,这次这个驱动已经不是Oracle的驱动了,是Proxool专用的驱动 Class.forName("org.logicalcobwebs.proxool.ProxoolDriver"); // 2:创建数据库连接,这个参数是一个字符串,是数据源的别名,在配置文件中配置的timalias,参数格式为:proxool.数据源的别名 Connection conn = DriverManager.getConnection("proxool.mysql"); for (int i = 0; i < 20; i++) conn = DriverManager.getConnection("proxool.mysql"); Statement stmt = conn.createStatement(); ResultSet res = stmt.executeQuery(MySQLreq); ResultSetMetaData rsmd = res.getMetaData(); int columnCount = rsmd.getColumnCount(); int rowCount = 0; while (res.next()) { System.out.print(rowCount + " "); rowCount++; for (int j = 1; j <= columnCount; j++) { String strRes = res.getString(j); System.out.print(strRes + "|\t"); } System.out.println(); } conn.close(); } }
三. 在src目录下新建一个xml文件。在这个文件中配置项目与数据库的连接。源码如下:
Proxool.xml源码:
<?xml version="1.0" encoding="UTF-8"?> <something-else-entirely> <proxool> <alias>mysql</alias> <driver-url>jdbc:mysql://127.0.0.1:3306/test</driver-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <driver-properties> <property name="user" value="root" /> <property name="password" value="123456" /> </driver-properties> <!-- 最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定 --> <maximum-connection-count>30</maximum-connection-count> <!--最小连接数(默认2个)--> <minimum-connection-count>1</minimum-connection-count> <!--proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒--> <house-keeping-sleep-time>90000</house-keeping-sleep-time> <!--没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受--> <maximum-new-connections>6</maximum-new-connections> <!--最少保持的空闲连接数(默认2个)--> <prototype-count>5</prototype-count> <!--在使用之前测试--> <test-before-use>true</test-before-use> <!--用于保持连接的测试语句 --> <house-keeping-test-sql>show tables</house-keeping-test-sql> </proxool> </something-else-entirely>
四. 运行结果:
Demo 2. 在java web 项目下使用proxool数据库连接池:
一.新建web工程,导入jar包。过程同上;
二.在src目录下新建两个包,分别是放数据库连接的,还有一个包用来存放测试用的文件。在src目录下新建一个properties文件。
包名:com.red.proxool 目录下的ConnectFactory.java文件 源码:
package com.red.proxool; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.configuration.PropertyConfigurator; public class ConnectFactory { private static ConnectFactory connectFactory = null; private static String defaultaliasname = "test"; public ConnectFactory() { } private ConnectFactory(String name) { init(); } public static ConnectFactory getInstance() { if (null == connectFactory) { connectFactory = new ConnectFactory(defaultaliasname); } return connectFactory; } public Connection getConnect() { try { Connection conn = DriverManager.getConnection("proxool." + defaultaliasname); return conn; } catch (SQLException e) { e.printStackTrace(); } return null; } public Connection getConnect(String aliasname) { try { Connection conn = DriverManager.getConnection("proxool." + aliasname); return conn; } catch (SQLException e) { e.printStackTrace(); } return null; } private static void init() { try { InputStream is = new ConnectFactory().getClass().getResourceAsStream("/proxool.properties"); Properties properties = new Properties(); properties.load(is); PropertyConfigurator.configure(properties); } catch (IOException e) { e.printStackTrace(); } catch (ProxoolException e1) { e1.printStackTrace(); } } public static void closeConnects(Connection conn, Statement state) { try { if (null != state && !conn.isClosed()) conn.close(); if (null != state && !state.isClosed()) state.close(); } catch (SQLException e) { e.printStackTrace(); } } }
包名:com.red.test目录下的Test.java文件 源码:
package com.red.test; import java.sql.ResultSet; import java.sql.SQLException; import com.mysql.jdbc.Connection; import com.mysql.jdbc.Statement; import com.red.proxool.ConnectFactory; public class Test { static ConnectFactory connectionFactory= null; public static void main(String[] args) { connectionFactory = new ConnectFactory(); Connection conn = (Connection) ConnectFactory.getInstance() .getConnect(); String sql = "SELECT * FROM test.user"; Statement stmt = null; ResultSet rs = null; try { stmt = (Statement) conn.createStatement(); rs = stmt.executeQuery(sql); while (rs.next()) { System.out.println("[ " + rs.getString(2) + " ]"); } } catch (SQLException e) { e.printStackTrace(); } finally { ConnectFactory.closeConnects(conn, stmt); } } }
Src目录下的proxool.properties文件 源码:
jdbc-1.proxool.alias=test jdbc-1.proxool.driver-class=com.mysql.jdbc.Driver jdbc-1.proxool.driver-url=jdbc:mysql://127.0.0.1:3306?useUnicode=true&characterEncoding=utf8 jdbc-1.user=root jdbc-1.password=123456 jdbc-1.proxool.maximum-connection-count=50 jdbc-1.proxool.minimum-connection-count=5 jdbc-1.proxool.prototype-count=4 jdbc-1.proxool.house-keeping-test-sql=select now(); jdbc-1.proxool.verbose=true jdbc-1.proxool.statistics=10s,1m,1d jdbc-1.proxool.statistics-log-level=ERROR jdbc-2.proxool.alias=local jdbc-2.proxool.driver-class=com.mysql.jdbc.Driver jdbc-2.proxool.driver-url=jdbc:mysql://127.0.0.1:3306?useUnicode=true&characterEncoding=utf8 jdbc-2.user=root jdbc-2.password=123456 jdbc-2.proxool.maximum-connection-count=50 jdbc-2.proxool.minimum-connection-count=2 jdbc-2.proxool.prototype-count=4 jdbc-2.proxool.house-keeping-test-sql=select now(); jdbc-2.proxool.verbose=true jdbc-2.proxool.statistics=10s,1m,1d jdbc-2.proxool.statistics-log-level=ERROR
三.正如proxool.properties设置的一样。其中可以有两个或两个以上的数据库。本文用了两个。更多地情况,读者可以自己尝试。
调用时只需要将它的别名作为参数就行。
public Connection getConnect(String aliasname)
四. 测试运行结果:
我相信通过以上两个例子,你应该对proxool连接池有了更深入的认识。本人只是希望这篇博客能够给刚接触proxool连接池的菜鸟朋友起一个抛砖引玉的作用。个人感觉只要这两个案例程序调试出来了,基本上在程序开发的过程中也就够用了。如果喜欢或者希望更加深入的理解proxool连接池还是需要去详细的阅读它的API文档。另外欢迎大神拍砖指教!
本文源码下载
作者:itRed 邮箱:it_red@sina.com 博客:http://www.cnblogs.com/itred
版权声明:本文版权归作者和博客园共有,欢迎转载,但请在文章显眼位置标明文章出处。未经本人书面同意,将其作为他用,本人保留追究责任的所有权利。
了解一下几个专用术语: