您的位置:首页 > 编程语言 > Java开发

Java建立数据库连接池

2011-08-02 16:22 127 查看
package mc;

import java.util.*;

import java.util.Date;

import java.sql.*;

import java.io.*;

public class DBConnectionManager {

/** 日志文件写入流对象 */

private PrintWriter log;

/** 存放连接池对象Hashtable */

private Hashtable pools;

/** DBConnectionManager 唯一实例 */

static private DBConnectionManager instance;

/** 记录客户机的连接数 */

static private int remotes;

/** 存放数据库连接驱动 */

private Vector drivers;

/**

* 类名: DBConnectionManager<br>

* 函数功能: 私有构造方法<br>

* 返回值: 无<br>

* 参数说明: 无<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

private DBConnectionManager()

{

init();

}

/**

* 类名: DBConnectionManager<br>

* 函数功能: 初始化类属性<br>

* 返回值: 无<br>

* 参数说明: 无<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

private void init()

{

pools = new Hashtable();

drivers = new Vector();

//建立属性对象

Properties prop = new Properties();

//把属性文件的属性列表读到属性对象

try {

InputStream is = getClass().getResourceAsStream("db.properties");

prop.load(is);

} catch (IOException e) {

e.printStackTrace();

System.out.println("读取属性文件错误!");

}

// 建立日志文件输入流对象

String logFilePath = prop.getProperty("logFile");

try {

log = new PrintWriter(new FileWriter(logFilePath,true),true);

} catch (IOException e) {

e.printStackTrace();

System.out.println("无法打开日志文件:" + logFilePath);

log = new PrintWriter(System.err);

}

// 加载和注册数据库驱动

loadDriver(prop);

// 初始化和创建连接池实例

createPools(prop);

}

/**

* 类名: DBConnectionManager<br>

* 函数功能: 返回 DBConnectionManager 唯一实例.如果是第一次调用此方法,则创建实例<br>

* 返回值: DBConnectionManager 对象<br>

* 参数说明: 无<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

static synchronized public DBConnectionManager getInstance()

{

if(instance == null){

instance = new DBConnectionManager();

}

remotes++;

return instance;

}

/**

* 类名: DBConnectionManager<br>

* 函数功能: 把文本信息写入日志文件<br>

* 返回值: 无<br>

* 参数说明: String message 信息描述字符串<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

private void logWriter(String message)

{

log.println("日期: " + new Date() + message);

}

private void logWriter(Throwable e,String errMessage)

{

log.println("日期: " + new Date() + errMessage + "\n错误: ");

e.printStackTrace(log); // 把异常描述写入日志文件

}

/**

* 类名: DBConnectionManager<br>

* 函数功能: 获取一个数据库连接<br>

* 返回值: Connection类型<br>

* 参数说明: String poolName 接收连接池名称<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

public Connection getConnection(String poolName)

{

// 通过连接池名称返回连接池对象

DBConnectionPool pool = (DBConnectionPool) pools.get(poolName);

if(pool == null){

logWriter("试图使用不存在的连接池" + poolName);

return null;

}

// 返回连接给用户.

return pool.getConnection();

}

/**

* 类名: DBConnectionManager<br>

* 函数功能: 释放连接,把用完的连接归还给连接池<br>

* 返回值: 无<br>

* 参数说明: String poolName 连接池名称,Connection conn 连接对象<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

public void RefeaseConnection(String poolName,Connection conn)

{

DBConnectionPool pool = (DBConnectionPool) pools.get(poolName);

if(pool == null){

logWriter("释放连错误!请检查连接池名称.");

return;

}else{

pool.freeConnection(conn);

}

}

/**

* 类名: DBConnectionManager<br>

* 函数功能: 释放连接,把用完的连接归还给连接池<br>

* 返回值: 无<br>

* 参数说明: String poolName 连接池名称,Connection conn 连接对象<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

public void RefeaseConnection

(String poolName,Connection conn,Statement stn,PreparedStatement ptn,ResultSet result)

{

try {

if (stn != null)

stn.close();

if (ptn != null)

ptn.close();

if (result != null)

result.close();

}catch(Exception ex)

{

ex.printStackTrace(System.out);

System.out.println(ex.getMessage());

}

DBConnectionPool pool = (DBConnectionPool) pools.get(poolName);

if(pool == null){

logWriter("释放连错误!请检查连接池名称.");

return;

}else{

pool.freeConnection(conn);

}

}

/**

* 类名: DBConnectionManager<br>

* 函数功能: 释放所有的连接,注销驱动<br>

* 返回值: 无<br>

* 参数说明: 无<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

public synchronized void releas()

{

if(--remotes != 0){

return;

}

Enumeration ePools = pools.elements();

while(ePools.hasMoreElements()){

DBConnectionPool pool = (DBConnectionPool) ePools.nextElement();

//关闭所有的连接对象

pool.release();

}

Enumeration eDrivers = drivers.elements();

while(eDrivers.hasMoreElements()){

Driver driver = (Driver) eDrivers.nextElement();

try {

DriverManager.deregisterDriver(driver);

logWriter("注销" + driver.getClass().getName() + "成功!");

} catch (SQLException e) {

logWriter(e,"无法注销" + driver.getClass().getName() + "驱动!");

e.printStackTrace();

}

}

}

/**

* 类名: DBConnectionManager<br>

* 函数功能: 加载和注册数据库驱动程序<br>

* 返回值: 无<br>

* 参数说明: Properties prop变量接收数据库属性列表<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

private void loadDriver(Properties prop)

{

// 从prop属性对象中取出驱动字符串

String driverClass = prop.getProperty("drivers");

// 把驱动字符串分解为标记

StringTokenizer st = new StringTokenizer(driverClass);

while(st.hasMoreTokens()){

String driverClassName = st.nextToken().trim();

try {

// 加载数据库驱动

Driver driver = (Driver) Class.forName(driverClassName).newInstance();

// 注册数据库驱动

DriverManager.registerDriver(driver);

drivers.addElement(driver);

// 把注册相关信息写入日志文件

logWriter("成功注册数据库驱动.");

} catch (InstantiationException e) {

logWriter("加载数据库驱动错误:" + e.getMessage());

e.printStackTrace();

} catch (IllegalAccessException e) {

logWriter("加载数据库驱动错误:" + e.getMessage());

e.printStackTrace();

} catch (ClassNotFoundException e) {

logWriter("加载数据库驱动错误:" + e.getMessage());

e.printStackTrace();

} catch (SQLException e) {

logWriter("无法数据库驱动:" + e.getMessage());

e.printStackTrace();

}

}

}

/**

* 类名: DBConnectionManager<br>

* 函数功能: 初始化和建立连接池实例<br>

* 返回值: 无<br>

* 参数说明: Properties prop 变量接收设置连接池属性列表;如 最大连接数,最少连接数等<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

private void createPools(Properties prop)

{

/** 返回属性列表中所有键的枚举 */

Enumeration propNames = prop.propertyNames();

while(propNames.hasMoreElements()){

String name = (String) propNames.nextElement();

if(name.endsWith(".url")){

// propName 以后用做连接池名称

String poolName = name.substring(0,name.indexOf("."));

String url = prop.getProperty(poolName + ".url").trim();

if(poolName == null || url == null){

log.print("没有连接池:" + poolName + " 指定的URL");

continue;

}

String user = prop.getProperty(poolName + ".user").trim();

String password = prop.getProperty(poolName + ".password").trim();

String strMaxConn = prop.getProperty(poolName + ".maxConn").trim();

String strMinConn = prop.getProperty(poolName + ".minConn").trim();

int maxConn = 0,minConn = 0;

try{

maxConn = Integer.parseInt(strMaxConn);

minConn = Integer.parseInt(strMinConn);

}catch(NumberFormatException ne){

maxConn = 100;

minConn = 50;

logWriter(ne," 属性文件中的最大连接数错误,请检查书写是否正确!" +

"此错误出现后,系统自动设置最大连接数为100");

}

//取得数据库属性文件中的相关设置后开始建立连接池

DBConnectionPool pool = new DBConnectionPool(poolName,url,user,password,maxConn,minConn);

//把连接池放到 Hashtable

pools.put(poolName, pool);

logWriter("连接池创建成功!");

}

}

}

/**

* 类名: DBConnectionPool类是DBConnectionManager类的内部类<br>

* 内部类功能: 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最大连接数为止.

在返回连接给客户程序之前,它能够验证连接的有效性.<br>

* 返回值: 无<br>

* 参数说明: <br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

class DBConnectionPool

{

/** 记录分出的连接数 */

private int checkOut;

/** 存放连接的 Vector 对象 */

private Vector freeConnection;

/** 数据库帐户 */

private String user;

/** 登陆密码 */

private String password;

/** 连接池名称 */

private String poolName;

/** 数据源URL */

private String url;

/** 最大连接数 */

private int maxConn;

/** 最小连接数 */

private int minConn;

/**

* 类名: DBConnectionPool<br>

* 函数功能: 构造方法<br>

* 返回值: 无<br>

* 参数说明: String poolName 接收连接池名称; String url 数据源URL;

String user 数据库帐户; String password 密码; int maxConn 设置最大的连接数<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

public DBConnectionPool(String poolName, String url, String user,

String password, int maxConn,int minConn) {

freeConnection = new Vector();

this.poolName = poolName;

this.url = url;

this.user = user;

this.password = password;

this.maxConn = maxConn;

this.minConn = minConn;

init();

}

/**

* 类名: DBConnectionPool<br>

* 函数功能: 该方法在程序第一次运行时生成最小连接数。<br>

* 返回值: Connection 对象<br>

* 参数说明: 无<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

private void init() {

Connection conn = null;

for (int i = 0; i < minConn; i++) {

try {

conn = DriverManager.getConnection(url, user, password);

logWriter("连接池: " + poolName + " 创建了一个新连接");

} catch (SQLException e) {

logWriter(e, "无法建立:" + url + "连接");

e.printStackTrace();

}

freeConnection.addElement(conn);

}

}

/**

* 类名: DBConnectionPool<br>

* 函数功能: 返回连接对象<br>

* 返回值: Connection 对象<br>

* 参数说明: 无<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

public Connection getConnection(){

Connection conn = null;

if(freeConnection.size() > 0){

//当连接池中有空闲的连接,就从池中取出一条连接

conn = (Connection) freeConnection.firstElement();

//连接取出后,从连接池中删除该连接的记录.

freeConnection.removeElementAt(0);

try {

//判断所取出的连接是否有效

if(conn.isClosed()){

logWriter("从连接池 "+ poolName +" 中删除一条无效的连接");

//递归调用自己,获取可用的连接

conn = getConnection();

}

} catch (SQLException e) {

logWriter("从连接池 "+ poolName +" 中删除一条无效的连接");

e.printStackTrace();

//递归调用自己,获取可用的连接

conn = getConnection();

}

// 当连接池中没有可用的连接,且当前的连接数在设置最大的连接数以下.新建一个连接

}else if(checkOut < maxConn){

conn = newConnection();

// 当连接池中没有可用的连接,且当前连接已经达到最大连接数.

}else{

try {

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

//等待500毫秒后,递归调用自己,获取可用的连接

conn = getConnection();

}

// 记录分出去的连接数

checkOut++;

return conn;

}

/**

* 类名: DBConnectionPool<br>

* 函数功能: 返回新建的连接对象<br>

* 返回值: Connection 对象<br>

* 参数说明: 无<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

public Connection newConnection(){

Connection conn = null;

try {

conn = DriverManager.getConnection(url,user,password);

logWriter("连接池: " + poolName + " 创建了一个新连接");

} catch (SQLException e) {

logWriter(e,"无法建立:" + url + "连接");

e.printStackTrace();

}

return conn;

}

/**

* 类名: DBConnectionPool<br>

* 函数功能: 释放连接对象<br>

* 返回值: 无<br>

* 参数说明: 无<br>

* 创建人: andy<br>

* 创建时间: 2006年9月1日

* 最后修改: 无<br>

*/

synchronized public void freeConnection(Connection conn)

{

// 把连接对象放回 Vector 里

freeConnection.addElement(conn);

// 连接数减1

checkOut--;

// 唤醒在此对象监视器上等待的所有线程

notifyAll();

}

public synchronized void release()

{

Enumeration allConn = freeConnection.elements();

while(allConn.hasMoreElements()){

Connection conn = (Connection) allConn.nextElement();

try {

conn.close();

logWriter("成功关闭连接!");

} catch (SQLException e) {

logWriter(e,"无法关闭连接池" + poolName + "中连接!");

e.printStackTrace();

}

//清空 Vector 中的所有元素

freeConnection.removeAllElements();

}

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: