📄 dbconnectionmanager.java
字号:
/** * <p>Title: </p> * <p>Description: </p> * <p>Copyright: Copyright (c) 2004</p> * <p>Company: </p> * @author unascribed * @version 1.0 *//****************************************************************************** (C) Copyright 2002 新世界数码科技有限公司。* 保留对所有使用、复制、修改和发布整个软件和相关文档的权利。* 本计算机程序受著作权法和国际公约的保护,未经授权擅自复制或* 传播本程序的全部或部分,可能受到严厉的民事和刑事制裁,并* 在法律允许的范围内受到最大可能的起诉。*/ /***************************************************************************** * @作者:Golden Peng * @版本: 1.0 * @时间: 2002-09-24 */ /***************************************************************************** * 修改记录清单 * 修改人 : * 修改记录: * 修改时间: * 修改描述: * */package com.corp.bisc.ebiz.base;import java.sql.*;import java.util.*;import java.io.*;import com.corp.bisc.ebiz.util.*;import com.corp.bisc.ebiz.exception.*;import com.corp.bisc.ebiz.*;/**************************************************************************** *功能描述: * * */public class DBConnectionManager extends ObjectBase { static private int clients; static private DBConnectionManager instance=null; private Hashtable pools=new Hashtable(); private Vector drivers=new Vector();/** * 构造函数是私有函数,以避免其他类创建其实例,在提供了db.properties文件时调用 **/ private DBConnectionManager() { init(); }/*********************************************************** * * *DBConnetionManager的客户调用getInstance()方法来得到该类的单一实例的引用。 * ***********************************************************/ static synchronized public DBConnectionManager getInstance() { if (instance == null) { instance = new DBConnectionManager(); } clients++; return instance; } /** * 功能描述:私有构造函数,根据驱动名字和连接参数来构造 * @param driverName 需要装载的驱动程序名称 * @param dsconfig 需要连接数据库的连接信息 */private DBConnectionManager(String driverName,DSConfig dsconfig){ loadDrivers(driverName); createPools(dsconfig); } /** * 功能描述:根据确定的信息来装载数据库信息 * @param driverName 需要装载的驱动程序名称 * @param dsconfig 需要连接数据库的连接信息 * @return */ static synchronized public DBConnectionManager getInstance(String driverName,DSConfig dsconfig) { if (instance == null) { instance = new DBConnectionManager(driverName, dsconfig); } clients++; return instance; } /** * 功能描述:私有构造函数 * @param driverNames:多个数据库驱动程序列表 * @param dsconfigs:多个数据库连接信息 */ private DBConnectionManager(ArrayList driverNames,ArrayList dsconfigs){ for(int i=0;i<driverNames.size() ;i++) loadDrivers((String)driverNames.get(i) ); for(int i=0;i<dsconfigs.size() ;i++) createPools((DSConfig)dsconfigs.get(i) ); } /** * 功能描述:供应用程序调用,取的唯一的一个Instance * @param driverNames:多个数据库驱动程序列表 * @param dsconfigs:多个数据库连接信息 * @return 一个DBConnectionManager的实列 */ static synchronized public DBConnectionManager getInstance(ArrayList driverNames,ArrayList dsconfigs) { if (instance == null) { instance = new DBConnectionManager(driverNames, dsconfigs); } clients++; return instance; }/******************************************************** * * 构造函数调用一个私有的init()函数初始化对象。 * *********************************************************/private void init() { InputStream is = getClass().getResourceAsStream("db.properties"); Properties dbProps = new Properties(); try { dbProps.load(is); } catch (Exception e) { log.error(" Can not read the properties file. Make sure db.properties is in the CLASSPATH"); return; } loadDrivers(dbProps); createPools(dbProps);}/***************************************************************** * * 方法getResourceAsStream()是一个标准方法,用来打开一个外部输入文件。文件的位置取决于类加载器,而标准的类加载器从classpath开始搜索。Db.properties文件是一个Porperties格式的文件,保存在连接池中定义的key-value对。下面一些常用的属性可以定义: drivers 以空格分开的jdbc驱动程序的列表 logfile 日志文件的绝对路径 每个连接池中还使用另一些属性。这些属性以连接池的名字开头: .url数据库的JDBC URL .maxconn最大连接数。0表示无限。 .user连接池的用户名 .password相关的密码 url属性是必须的,其他属性可选。用户名和密码必须和所定义的数据库匹配。 下面是windows平台下的一个db.properties文件的例子。有一个InstantDB连接池和一个通过odbc连接的access数据库的数据源,名字叫demo。 drivers=sun.jdbc.odbc.JdbcOdbcDriver jdbc.idbDriver logfile=D:\\user\\src\\java\\DBConnectionManager\\log.txt idb.url=jdbc:idb:c:\\local\\javawebserver1.1\\db\\db.prp idb.maxconn=2 access.url=jdbc:odbc:demo access.user=demo access.password=demopw 注意,反斜线在windows平台下必须双写。 初始化方法init()创建一个Porperties对象并装载db.properties文件,然后读取日志文件属性。 如果日志文件没有命名,则使用缺省的名字DBConnectionManager.log在当前目录下创建。 在此情况下,一个系统错误被纪录。 方法loadDrivers()将指定的所有jdbc驱动程序注册,装载。 *******************************************************************/ private void loadDrivers(Properties props) { String driverClasses = props.getProperty("drivers"); StringTokenizer st = new StringTokenizer(driverClasses); while (st.hasMoreElements()) { String driverClassName = st.nextToken().trim(); try { Driver driver = (Driver) Class.forName(driverClassName).newInstance(); DriverManager.registerDriver(driver); drivers.addElement(driver); //log("Registered JDBC driver " + driverClassName); } catch (Exception e) { //log("Can not register JDBC driver: " + driverClassName + ", Exception: " + e); } }}/******************************************************** * * 根据具体的驱动程序,装载对应的数据库驱动 * *********************************************************/private void loadDrivers(String driverName){ try { Driver driver = (Driver) Class.forName(driverName).newInstance(); DriverManager.registerDriver(driver); drivers.addElement(driver); //log("Registered JDBC driver " + driverClassName); } catch (Exception e) { //log("Can not register JDBC driver: " + driverClassName + ", Exception: " + e); }}/********************************************************** * * 一个枚举对象保存所有的属性名,如果属性名带有.url结尾, * 则表示是一个连接池对象需要被实例化。 * 创建的连接池对象保存在一个Hashtable实例变量中。 * 连接池名字作为索引,连接池对象作为值。 */private void createPools(Properties props) { Enumeration propNames = props.propertyNames(); while (propNames.hasMoreElements()) { DSConfig dsconfig=new DSConfig(); String name = (String) propNames.nextElement(); if (name.endsWith(".url")) { String poolName = name.substring(0, name.lastIndexOf(".")); String url = props.getProperty(poolName + ".url"); if (url == null) { //log("No URL specified for " + poolName); continue; } String user = props.getProperty(poolName + ".user"); String password = props.getProperty(poolName + ".password"); String maxconn = props.getProperty(poolName + ".maxconn", "0"); int max; try { max = Integer.valueOf(maxconn).intValue(); } catch (NumberFormatException e) { //log("Invalid maxconn value " + maxconn + " for " + poolName); max = 0; } dsconfig.name =poolName; dsconfig.user =user; dsconfig.password =password; dsconfig.URL =url; dsconfig.maxConn =max; dsconfig.autoCommit =true; DBConnectionPool pool =new DBConnectionPool(dsconfig); pools.put(poolName, pool); } }}/**************************************************************************** * 功能描述:取的所有连接池的名称,也就是数据库实列名 * */public String[] getDbinstanceNames(){ if(pools.isEmpty()) { String temp[]={"null"}; return temp; } String returnNames[]=new String[pools.size() + 1]; Enumeration dbinstanceNames =pools.keys(); returnNames[0]="null"; int index=1; while(dbinstanceNames.hasMoreElements()) { returnNames[index ++]=(String)dbinstanceNames.nextElement(); } return returnNames;}private void createPools(DSConfig dsconfig){ DBConnectionPool pool =new DBConnectionPool(dsconfig); pools.put(dsconfig.name , pool);}/*********************************************** * *DBConnectionManager提供getConnection()方法和freeConnection方法, *这些方法有客户程序使用。 *所有的方法以连接池名字所参数,并调用特定的连接池对象。 * ****************************************************/public Connection getConnection(String name) throws PortalException{ DBConnectionPool pool = (DBConnectionPool) pools.get(name); if (pool != null) { int checkedOut=pool.getCheckedOut() + 1; return pool.getConnection(); }else throw new DatabaseDeniedException("该[" + name +"]连接池不存在" );}/**************************************************************************** * 功能描述:释放一个数据库连接回连接池中 * @param name 连接池的名称 * @param time 规定或许连接对象时不要超过的时间限制 */public Connection getConnection(String name, long time) throws PortalException{ DBConnectionPool pool = (DBConnectionPool) pools.get(name); if (pool != null) { int checkedOut=pool.getCheckedOut() + 1; return pool.getConnection(time); }else throw new DatabaseDeniedException("该[" + name +"]连接池不存在" );}/**************************************************************************** * 功能描述:释放一个数据库连接回连接池中 * @param name 连接池的名称 * @param con 要释放的数据库连接 */public void freeConnection(String name, Connection con) throws PortalException{ DBConnectionPool pool = (DBConnectionPool) pools.get(name); if (pool != null) { pool.freeConnection(con); }else throw new DatabaseDeniedException("该[" + name +"]连接池不存在" );}/********************************************************* * *最后,由一个release()方法,用来完好地关闭连接池。 *每个DBConnectionManager客户必须调用getInstance()方法引用。 *有一个计数器跟踪客户的数量。 *方法release()在客户关闭时调用,技术器减1。 *当最后一个客户释放,DBConnectionManager关闭所有的连接池。 * *********************************************************/public synchronized void release() {// Wait until called by the last clientif (--clients != 0) { return;}Enumeration allPools = pools.elements();while (allPools.hasMoreElements()) { DBConnectionPool pool = (DBConnectionPool) allPools.nextElement(); try { pool.release(); } catch(Exception ex) { log.error("释放数据库连接池错误"); }}//end whileEnumeration allDrivers = drivers.elements();while (allDrivers.hasMoreElements()) { Driver driver = (Driver) allDrivers.nextElement(); try { DriverManager.deregisterDriver(driver); }catch (SQLException e) { log.error("不能注销 JDBC driver: " + driver.getClass().getName()); } }//end while}//end function}//end class
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -