package com.db;
/**
* 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接池的访问。
* 客户程序可以调用getInstance()方法访问本类的唯一实例。
* 装载和注册JDBC驱动程序。
* 根据在属性文件中定义的属性创建连接池对象。
* 实现连接池名字与其实例之间的映射。
* 跟踪客户程序对连接池的引用,保证在最后一个客户程序结束时安全地关闭所有连接池。
*/
import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;
public class DBConnectionManager {
static public DBConnectionManager instance; // 唯一实例
static public int clients;
public Vector drivers = new Vector(); // 驱动
public PrintWriter log; // 日志
public Hashtable pools = new Hashtable(); // 连接
/**
* 返回唯一实例.如果是第一次调用此方法,则创建实例
*
* @return DBConnectionManager 唯一实例
*/
static synchronized public DBConnectionManager getInstance() {
if (instance == null) {
instance = new DBConnectionManager();
}
clients++;
return instance;
}
/**
* 建构函数私有以防止其它对象创建本类实例
*/
public DBConnectionManager() {
init();
}
/**
* 将连接对象返回给由名字指定的连接池
*
* @param name
* 在属性文件中定义的连接池名字
* @param con
* 连接对象
*/
public void freeConnection(String name, Connection con) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
pool.freeConnection(con);
} else {
System.out.println("pool ==null");
}
clients--;
}
/**
* 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数 限制,则创建并返回新连接
*
* @param name
* 在属性文件中定义的连接池名字
* @return Connection 可用连接或null
*/
public Connection getConnection(String name) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
// return pool.getConnection();
return pool.returnConnection();
}
return null;
}
/**
* 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制, 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.
*
* @param name
* 连接池名字
* @param time
* 以毫秒计的等待时间
* @return Connection 可用连接或null
*/
public Connection getConnection(String name, long time) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
return pool.getConnection(time);
}
return null;
}
/**
* 关闭所有连接,撤销驱动程序的注册
*/
public synchronized void release() {
// 等待直到最后一个客户程序调用
if (--clients != 0) {
return;
}
Enumeration allPools = pools.elements();
while (allPools.hasMoreElements()) {
DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();
pool.release();
}
Enumeration allDrivers = drivers.elements();
while (allDrivers.hasMoreElements()) {
Driver driver = (Driver) allDrivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
log("撤销JDBC驱动程序 " + driver.getClass().getName() + "的注册");
} catch (SQLException e) {
log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());
}
}
}
/**
* 读取属性完成初始化
*/
private void init() {
try {
// Properties p = new Properties();
String configs = System.getProperty("user.dir")
+ "\\conf\\db.properties";
configs = Thread.currentThread().getContextClassLoader()
.getResource("").toString();
configs = configs.replace("file:/", "") + "db.properties";
System.out.println("configs file local at " + configs);
FileInputStream is = new FileInputStream(configs);
Properties dbProps = new Properties();
try {
dbProps.load(is);
} catch (Exception e) {
System.err.println("不能读取属性文件. "
+ "请确保db.properties在CLASSPATH指定的路径中");
return;
}
String logFile = dbProps.getProperty("logfile",
"DBConnectionManager.log");
logFile = dbProps.getProperty("logfile");
try {
File f = new File(logFile);
f = f.getParentFile();
if(f.mkdirs()){
log = new PrintWriter(new FileWriter(logFile, true), true);
}
} catch (IOException e) {
System.err.println("无法打开日志文件: " + logFile);
log = new PrintWriter(System.err);
}
loadDrivers(dbProps);
createPools(dbProps);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 171 * 装载和注册所有JDBC驱动程序 172 * 173 *
*
* @param props
* 属性 174
*/
private void loadDrivers(Properties props) {
Enumeration propNames = props.propertyNames();
while (propNames.hasMoreElements()) {
String name = (String) propNames.nextElement();
if (name.endsWith(".driver")) {
String poolName = name.substring(0, name.lastIndexOf("."));
String driverClasses = props.getProperty(poolName + ".driver");
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);
System.out.println(driverClassName);
log("成功注册JDBC驱动程序" + driverClassName);
} catch (Exception e) {
log("无法注册JDBC驱动程序: " + driverClassName + ", 错误: " + e);
}
}
}
}
// 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);
// System.out.println(driverClassName);
// log("成功注册JDBC驱动程序" + driverClassName);
// } catch (Exception e) {
// log("无法注册JDBC驱动程序: " + driverClassName + ", 错误: " + e);
// }
// }
}
/**
* 根据指定属性创建连接池实例.
*
* @param props
* 连接池属性
*/
private void createPools(Properties props) {
Enumeration propNames = props.propertyNames();
while (propNames.hasMoreElements()) {
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("没有为连接池" + poolName + "指定URL");
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("错误的最大连接数限制: " + maxconn + " .连接池: " + poolName);
max = 0;
}
DBConnectionPool pool = new DBConnectionPool(poolName, url,
user, password, max);
pools.put(poolName, pool);
log("成功创建连接池" + poolName);
}
}
}
/**
* 将文本信息写入日志文件
*/
private void log(String msg) {
log.println(new Date() + ": " + msg);
}
/**
* 将文本信息与异常写入日志文件
*/
private void log(Throwable e, String msg) {
log.println(new Date() + ": " + msg);
e.printStackTrace(log);
}
/**
* 类DBConnectionPool的作用: 从连接池获取(或创建)可用连接。 把连接返回给连接池 在系统关闭时释放所有资源,关闭所有连接。
* 处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题)。 限制连接池中的连接总数不超过某个预定值。
*/
class DBConnectionPool {
// private int checkedOut;
private Vector freeConnections = new Vector();
private int maxConn;
private String name;
private String password;
private String URL;
private String user;
/**
* 创建新的连接池
*
* @param name
* 连接池名字
* @param URL
* 数据库的JDBC URL
* @param user
* 数据库帐号,或 null
* @param password
* 密码,或 null
* @param maxConn
* 此连接池允许建立的最大连接数,0表示没有限制
*/
public DBConnectionPool(String name, String URL, String user,
String password, int maxConn) {
this.name = name;
this.URL = URL;
this.user = user;
this.password = password;
this.maxConn = maxConn;
}
/**
* 将不再使用的连接返回给连接池
*
* @param con
* 客户程序释放的连接
*/
public synchronized void freeConnection(Connection con) {
// 将指定连接加入到向量末尾
try {
if (con.isClosed()) {
System.out.println("before freeConnection con is closed");
}
freeConnections.addElement(con);
Connection contest = (Connection) freeConnections.lastElement();
if (contest.isClosed()) {
System.out
.println("after freeConnection contest is closed");
}
notifyAll();
} catch (SQLException e) {
System.out.println(e);
}
}
/**
* 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,
* 然后递归调用自己以尝试新的可用连接.
*/
public synchronized Connection getConnection() {
Connection con = null;
if (freeConnections.size() > 0) {
// 获取向量中第一个可用连接
con = (Connection) freeConnections.firstElement();
freeConnections.removeElementAt(0);
try {
if (con.isClosed()) {
log("从连接池" + name + "删除一个无效连接");
System.out.println("从连接池" + name + "删除一个无效连接");
// 递归调用自己,尝试再次获取可用连接
con = getConnection();
}
} catch (SQLException e) {
log("从连接池" + name + "删除一个无效连接时错误");
System.out.println("从连接池" + name + "删除一个无效连接出错");
// 递归调用自己,尝试再次获取可用连接
con = getConnection();
}
if (freeConnections.size() > maxConn) {
System.out.println(" 删除一个溢出连接 ");
releaseOne();
}
}
else if ((maxConn == 0) || (freeConnections.size() < maxConn)) {
con = newConnection();
}
return con;
}
public synchronized Connection returnConnection() {
Connection con = null;
// 如果闲置小于最大连接,返回一个新连接
if (freeConnections.size() < maxConn) {
con = newConnection();
}
// 如果闲置大于最大连接,返回一个可用的旧连接
else if (freeConnections.size() >= maxConn) {
con = (Connection) freeConnections.firstElement();
System.out.println(" [a 连接池可用连接数 ] : " + "[ "
+ freeConnections.size() + " ]");
freeConnections.removeElementAt(0);
System.out.println(" [b 连接池可用连接数 ] : " + "[ "
+ freeConnections.size() + " ]");
try {
if (con.isClosed()) {
log("从连接池" + name + "删除一个无效连接");
System.out.println("从连接池" + name + "删除一个无效连接");
returnConnection();
}
} catch (SQLException e) {
log("从连接池" + name + "删除一个无效连接时错误");
System.out.println("从连接池" + name + "删除一个无效连接出错");
returnConnection();
}
}
return con;
}
/**
* 从连接池获取可用连接.可以指定客户程序能够等待的最长时间 参见前一个getConnection()方法.
*
* @param timeout
* 以毫秒计的等待时间限制
*/
public synchronized Connection getConnection(long timeout) {
long startTime = new Date().getTime();
Connection con;
while ((con = getConnection()) == null) {
try {
wait(timeout);
} catch (InterruptedException e) {
}
if ((new Date().getTime() - startTime) >= timeout) {
// wait()返回的原因是超时
return null;
}
}
return con;
}
/**
* 关闭所有连接
*/
public synchronized void release() {
Enumeration allConnections = freeConnections.elements();
while (allConnections.hasMoreElements()) {
Connection con = (Connection) allConnections.nextElement();
try {
con.close();
log("关闭连接池" + name + "中的一个连接");
} catch (SQLException e) {
log(e, "无法关闭连接池" + name + "中的连接");
}
}
freeConnections.removeAllElements();
}
/**
* 关闭一个连接
*/
public synchronized void releaseOne() {
if (freeConnections.firstElement() != null) {
Connection con = (Connection) freeConnections.firstElement();
try {
con.close();
System.out.println("关闭连接池" + name + "中的一个连接");
log("关闭连接池" + name + "中的一个连接");
} catch (SQLException e) {
System.out.println("无法关闭连接池" + name + "中的一个连接");
log(e, "无法关闭连接池" + name + "中的连接");
}
} else {
System.out
.println("releaseOne() bug.......................................................");
}
}
/**
* 创建新的连接
*/
private Connection newConnection() {
Connection con = null;
try {
if (user == null) {
con = DriverManager.getConnection(URL);
} else {
con = DriverManager.getConnection(URL, user, password);
}
log("连接池" + name + "创建一个新的连接");
} catch (SQLException e) {
log(e, "无法创建下列URL的连接: " + URL);
return null;
}
return con;
}
}
}
package com.db;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import org.apache.log4j.Logger;
/**
* 数据库操作管理类
*
* @author Harlyhood
*
*/
public class DBManager {
// --------------------------------------------------------- Instance
private static Logger logger = Logger.getLogger(DBManager.class);
// --------------------------------------------------------- Methods
// 数据库连接对象
private Connection con;
// SQL语句对象
private Statement stmt;
// 带参数的Sql语句对象
private PreparedStatement pstmt;
// 记录集对象
private ResultSet rs;
// 数据连接管理(连接池对象)
private DBConnectionManager dcm = null;
/** ***********************手动设置的连接参数********************************* */
@SuppressWarnings("unused")
private static String _DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
@SuppressWarnings("unused")
private static String _URL = "jdbc:sqlserver://localhost:1433;database=Hospital_AI_DB;characterEncoding=gb2312";
@SuppressWarnings("unused")
private static String _USER_NA = "sa";
@SuppressWarnings("unused")
private static String _PASSWORD = "";
/** ********************************************************************** */
// 默认构造
public DBManager() {
}
/** ****************************************************************************************** */
/**
* **************************************** 数据库连接初始化
* ***********************************
*/
/** ****************************************************************************************** */
/**
* 得到一个默认的数据库连接[从 com.hospital.dao.tools.db.properties文件初始化]
*
* @throws Exception
*/
private void getConnection() {
logger.info("###############open:::::从默认的配置文件得到一个数据库连接");
// 获取一个连接池管理类的实例
dcm = DBConnectionManager.getInstance();
// 得到一个数据库连接
con = dcm.getConnection("mysql");
try {
con.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 从指定参数得到一个连接对象
*
* @param driver
* @param url
* @param user_na
* @param password
* @throws Exception
*/
public void getConnection(String driver, String url, String user_na,
String password) throws Exception {
try {
logger.info("###############open:::::从指定配置中得到一个数据库连接");
Class.forName(driver);
con = DriverManager.getConnection(url, user_na, password);
} catch (ClassNotFoundException ex) {
logger
.info("###############Error[com.hospital.dao.tools.DBManager^^^Method:getConnection^^^Line:81]找不到类驱动类: "
+ driver);
throw ex;
} catch (SQLException ex) {
logger
.info("###############Error[com.hospital.dao.tools.DBManager^^^Method:getConnection^^^Line:81]加载类: "
+ driver + " 时出现 SQLException 异常");
throw ex;
}
}
/** ****************************************************************************************** */
/**
* **************************************** 数据库操作方法
* ***********************************
*/
/** ****************************************************************************************** */
/**
* 执行SQL语句操作(更新数据 无参数)
*
* @param strSql
* SQL语句
* @throws Exception
*/
public boolean executeUpdate(String strSql) throws SQLException {
getConnection();
// getConnection(_DRIVER,_URL,_USER_NA,_PASSWORD);
boolean flag = false;
stmt = con.createStatement();
logger.info("###############::执行SQL语句操作(更新数据 无参数):" + strSql);
try {
if (0 < stmt.executeUpdate(strSql)) {
close_DB_Object();
flag = true;
con.commit();
}
} catch (SQLException ex) {
logger
.info("###############Error DBManager Line126::执行SQL语句操作(更新数据 无参数):"
+ strSql + "失败!");
flag = false;
con.rollback();
throw ex;
}
return flag;
}
/**
* 执行SQL语句操作(更新数据 有参数)
*
* @param strSql
* sql指令
* @param prams
* 参数列表
* @return
* @throws SQLException
*/
public boolean executeUpdate(String strSql, HashMap<Integer, Object> prams)
throws SQLException, ClassNotFoundException {
getConnection();
// getConnection(_DRIVER,_URL,_USER_NA,_PASSWORD);
boolean flag = false;
try {
pstmt = con.prepareStatement(strSql);
setParamet(pstmt, prams);
logger.info("###############::执行SQL语句操作(更新数据 有参数):" + strSql);
if (0 < pstmt.executeUpdate()) {
close_DB_Object();
flag = true;
con.commit();
}
} catch (SQLException ex) {
logger
.info("###############Error DBManager Line121::执行SQL语句操作(更新数据 无参数):"
+ strSql + "失败!");
flag = false;
con.rollback();
throw ex;
} catch (ClassNotFoundException ex) {
logger
.info("###############Error DBManager Line152::执行SQL语句操作(更新数据 无参数):"
+ strSql + "失败! 参数设置类型错误!");
con.rollback();
throw ex;
}
return flag;
}
/**
* 执行SQL语句操作(查询数据 无参数)
*
* @param strSql
* SQL语句
* @return 数组对象列表
* @throws Exception
*/
public ArrayList<HashMap<Object, Object>> executeSql(String strSql)
throws Exception {
getConnection();
// getConnection(_DRIVER,_URL,_USER_NA,_PASSWORD);
stmt = con.createStatement();
logger.info("###############::执行SQL语句操作(查询数据):" + strSql);
rs = stmt.executeQuery(strSql);
con.commit();
if (null != rs) {
return convertResultSetToArrayList(rs);
}
close_DB_Object();
return null;
}
/**
* 执行SQL语句操作(查询数据 有参数)
*
* @param strSql
* SQL语句
* @param prams
* 参数列表
* @return 数组对象列表
* @throws Exception
*/
public ArrayList<HashMap<Object, Object>> executeSql(String strSql,
HashMap<Integer, Object> prams) throws Exception {
getConnection();
// getConnection(_DRIVER,_URL,_USER_NA,_PASSWORD);
pstmt = con.prepareStatement(strSql);
setParamet(pstmt, prams);
logger.info("###############::执行SQL语句操作(查询数据):" + strSql);
rs = pstmt.executeQuery();
con.commit();
if (null != rs) {
return convertResultSetToArrayList(rs);
}
return null;
}
/**
* 执行存储过程(查询数据 无参数)
*
* @param procName
* 存储过程名称
* @return 数组列表对象
* @throws Exception
*/
public ArrayList<HashMap<Object, Object>> executeProcedureQuery(
String procName) throws Exception {
getConnection();// 获取连接
String callStr = "{call " + procName + "}";// 构造执行存储过程的sql指令
CallableStatement cs = con.prepareCall(callStr);
logger.info("###############::执行存储过程(查询数据):" + procName);
rs = cs.executeQuery();
con.commit();
cs.close();
close_DB_Object();
return convertResultSetToArrayList(rs);
}
/**
* 执行存储过程(查询数据,带参数)返回结果集合
*
* @param procName
* 存储过程名称
* @param parameters
* 参数对象数组
* @param al
* 数组列表对象
* @return 数组列表对象
* @throws Exception
*/
public ArrayList<HashMap<Object, Object>> executeProcedureQuery(
String procName, Object[] parameters) throws Exception {
int parameterPoint = 0;
// 获取存储过程信息列表集合
ArrayList<HashMap<Object, Object>> procedureInfo = getProcedureInfo(procName);
// 获取存储过程的完全名称
String procedureCallName = getProcedureCallName(procName,parameters.length);
// 获取连接对象
getConnection();
// 初始化 存储过程 执行对象
CallableStatement cs = con.prepareCall(procedureCallName);
// 参数下标变量
int index = 0;
// 获取 存储过程信息列表集合的 迭代器 对象
Iterator<HashMap<Object, Object>> iter = procedureInfo.iterator();
// 遍历存储过程信息列表集合
while (iter.hasNext()) {
HashMap<Object, Object> hm = iter.next();
parameterPoint++;
// 如果参数是输入参数 way = 0
if (hm.get("WAY").equals("0")) {
// 设置参数到cs
cs.setObject(parameterPoint, parameters[index]);
// 参数下标+1
index++;
}
}
// 释放这个对象,做为第二次使用
procedureInfo = null;
logger.info("###############::执行存储过程(查询数据):::::" + procedureCallName);
rs = cs.executeQuery();
con.commit();
procedureInfo = convertResultSetToArrayList(rs);
cs.close();
close_DB_Object();
return procedureInfo;
}
/**
* 执行存储过程(更新,查询数据[简单查询、非纪录集],返回输出参数[非纪录集])
*
* @param procName
* 存储过程名称
* @param parameters
* 参数对象数组
* @param os
* 输出参数对象数组
* @return 输出参数对象数组
* @throws Exception
*/
public Object[] executeProcedureUpdate(String procName, Object[] parameters)
throws Exception {
logger.info("------------------------------------------------------------------------------------------------------");
logger.info(" Run --> executeProcedureUpdate ############## 正在执行 存储过程: " + procName +" ##############");
CallableStatement cs = null;
Object []returnVal = null;
try {
// 获取 存储过程 调用全名
String fullPCallName = getProcedureCallName(procName,parameters.length);
logger.info(" Run --> executeProcedureUpdate # 存储过程命令: " + fullPCallName +" #");
//获取存储过程参数信息
ArrayList<HashMap<Object, Object>> p_Call_Info_List = getProcedureInfo(procName);
//获取连接
getConnection();
//创建 存储过程 执行对象
cs = con.prepareCall(fullPCallName);
//数组下标
int index = 1;
//输出参数下标 纪录
ArrayList<Integer> outPutIndexList = new ArrayList<Integer>();
logger.info(" Run --> executeProcedureUpdate # 参数个数是: " + parameters.length +" #");
for(HashMap<Object,Object> tempHash:p_Call_Info_List)
{
if("0".equals(tempHash.get("WAY")))
{
//设置输入参数
cs.setObject(index, parameters[index-1]);
logger.info(" Run --> executeProcedureUpdate # 输入 Input: 编号:" + index +" 值: "+parameters[index-1]+" 类型: "+parameters[index-1].getClass()+" #");
}
else
{
//注册输出参数
cs.registerOutParameter(index, getDataType(tempHash.get("TYPENAME").toString()));
//纪录输出参数的下标
outPutIndexList.add(index);
logger.info(" Run --> executeProcedureUpdate # 输出 OutPut: 编号:" + index +" 值: "+parameters[index-1]+" 类型: "+parameters[index-1].getClass()+" #");
}
index++;
}
logger.info(" Run --> executeProcedureUpdate # 参数设置完毕,正在执行中 ... : #");
//-------------------- 执行 -----------------
if(!cs.execute())
{
returnVal = new Object[outPutIndexList.size()];
logger.info(" Run --> executeProcedureUpdate # 执行成功! : #");
//取输 出参数的 返回值
for(int i = 0 ;i<outPutIndexList.size();i++)
{
returnVal[i] = cs.getObject(outPutIndexList.get(i));
logger.info(" Run --> executeProcedureUpdate # 返回值 "+(i+1)+" "+returnVal[i]+" #");
}
con.commit();//提交
}
} catch (Exception e) {
logger.info(" Run --> executeProcedureUpdate # 执行失败!事务回滚中... : #");
con.rollback();
throw e;
}
logger.info("------------------------------------------------------------------------------------------------------");
return returnVal;
}
/** ****************************************************************************************** */
/**
* ********************************* 小工具
* ************************************************
*/
/** ****************************************************************************************** */
/**
* 关闭数据对象
*/
public void close_DB_Object() {
logger.info("###############close:::::关闭连接对象,语句对象,记录集对象");
if (null != rs) {
try {
rs.close();
} catch (SQLException ex) {
rs = null;
}
}
if (null != stmt) {
try {
stmt.close();
} catch (SQLException ex) {
stmt = null;
}
}
if (null != pstmt) {
try {
pstmt.close();
} catch (SQLException ex) {
pstmt = null;
}
}
if (con != null) {
dcm.freeConnection("mysql", con);
}
}
/**
* 设置Sql 指令参数
*
* @param p_stmt
* PreparedStatement
* @param pramets
* HashMap
*/
private PreparedStatement setParamet(PreparedStatement p_stmt,
HashMap<Integer, Object> pramets) throws ClassNotFoundException,
SQLException {
// 如果参数为空
if (null != pramets) {
// 如果参数个数为0
if (0 <= pramets.size()) {
for (int i = 1; i <= pramets.size(); i++) {
try {
// 字符类型 String
if (pramets.get(i).getClass() == Class
.forName("java.lang.String")) {
p_stmt.setString(i, pramets.get(i).toString());
}
// 日期类型 Date
if (pramets.get(i).getClass() == Class
.forName("java.sql.Date")) {
p_stmt.setDate(i, java.sql.Date.valueOf(pramets
.get(i).toString()));
}
// 布尔类型 Boolean
if (pramets.get(i).getClass() == Class
.forName("java.lang.Boolean")) {
p_stmt.setBoolean(i, (Boolean) (pramets.get(i)));
}
// 整型 int
if (pramets.get(i).getClass() == Class
.forName("java.lang.Integer")) {
p_stmt.setInt(i, (Integer) pramets.get(i));
}
// 浮点 float
if (pramets.get(i).getClass() == Class
.forName("java.lang.Float")) {
p_stmt.setFloat(i, (Float) pramets.get(i));
}
// 双精度型 double
if (pramets.get(i).getClass() == Class
.forName("java.lang.Double")) {
p_stmt.setDouble(i, (Double) pramets.get(i));
}
} catch (ClassNotFoundException ex) {
throw ex;
} catch (SQLException ex) {
throw ex;
}
}
}
}
return p_stmt;
}
/**
* 转换记录集对象为数组列表对象
*
* @param rs
* 纪录集合对象
* @return 数组列表对象
* @throws Exception
*/
private ArrayList<HashMap<Object, Object>> convertResultSetToArrayList(
ResultSet rs) throws Exception {
logger.info("###############::转换记录集对象为数组列表对象");
// 获取rs 集合信息对象
ResultSetMetaData rsmd = rs.getMetaData();
// 创建数组列表集合对象
ArrayList<HashMap<Object, Object>> tempList = new ArrayList<HashMap<Object, Object>>();
HashMap<Object, Object> tempHash = null;
// 填充数组列表集合
while (rs.next()) {
// 创建键值对集合对象
tempHash = new HashMap<Object, Object>();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
// 遍历每列数据,以键值形式存在对象tempHash中
tempHash.put(rsmd.getColumnName(i + 1).toUpperCase(), rs
.getString(rsmd.getColumnName(i + 1)));
}
// 第一个键值对,存储在tempList列表集合对象中
tempList.add(tempHash);
}
close_DB_Object();// 关闭相关链接
return tempList;// 返回填充完毕的数组列表集合对象
}
/**
* 从数据库得到存储过程信息
*
* @param procName
* 存储过程名称
* @return 数组列表对象
* @throws Exception
*/
private ArrayList<HashMap<Object, Object>> getProcedureInfo(String procName)
throws Exception {
return this.executeSql("select Syscolumns.isoutparam as Way,systypes.name as TypeName from sysobjects,syscolumns,systypes where systypes.xtype=syscolumns.xtype and syscolumns.id=sysobjects.id and sysobjects.name='"
+ procName + "' order by Syscolumns.isoutparam");
}
/**
* 从数据库得到存储过程参数个数
*
* @param procName
* 存储过程名称
* @return 数组列表对象
* @throws Exception
*/
@SuppressWarnings("unused")
private int getParametersCount(String procName) throws Exception {
int returnVal = 0;
for (HashMap<Object, Object> tempHas : this
.executeSql("select count(*) as RowsCount from sysobjects,syscolumns,systypes where systypes.xtype=syscolumns.xtype and syscolumns.id=sysobjects.id and sysobjects.name='"
+ procName + "'")) {
returnVal = Integer.parseInt(tempHas.get("ROWSCOUNT").toString());
}
return returnVal;
}
/**
* 得到调用存储过程的全名
*
* @param procName
* 存储过程名称
* @return 调用存储过程的全名
* @throws Exception
*/
private String getProcedureCallName(String procName, int prametCount)
throws Exception {
String procedureCallName = "{call " + procName;
for (int i = 0; i < prametCount; i++) {
if (0 == i) {
procedureCallName = procedureCallName + "(?";
}
if (0 != i) {
procedureCallName = procedureCallName + ",?";
}
}
procedureCallName = procedureCallName + ")}";
return procedureCallName;
}
/**
* 得到数据类型的整型值
*
* @param typeName
* 类型名称
* @return 数据类型的整型值
*/
private int getDataType(String typeName) {
if (typeName.equals("varchar"))
return Types.VARCHAR;
if (typeName.equals("int"))
return Types.INTEGER;
if (typeName.equals("bit"))
return Types.BIT;
if (typeName.equals("float"))
return Types.FLOAT;
return 0;
}
// 设置驱动路径
@SuppressWarnings("static-access")
public void set_DRIVER(String _DRIVER) {
this._DRIVER = _DRIVER;
}
// 设置数据库密码
@SuppressWarnings("static-access")
public void set_PASSWORD(String _PASSWORD) {
this._PASSWORD = _PASSWORD;
}
// 设置数据库连接字符串
@SuppressWarnings("static-access")
public void set_URL(String _URL) {
this._URL = _URL;
}
// 设置数据库用户名
@SuppressWarnings("static-access")
public void set_USER_NA(String _USER_NA) {
this._USER_NA = _USER_NA;
}
}
package com.db;
/**
* 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接池的访问。
* 客户程序可以调用getInstance()方法访问本类的唯一实例。
* 装载和注册JDBC驱动程序。
* 根据在属性文件中定义的属性创建连接池对象。
* 实现连接池名字与其实例之间的映射。
* 跟踪客户程序对连接池的引用,保证在最后一个客户程序结束时安全地关闭所有连接池。
*/
import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;
public class DBConnectionManager {
static public DBConnectionManager instance; // 唯一实例
static public int clients;
public Vector drivers = new Vector(); // 驱动
public PrintWriter log; // 日志
public Hashtable pools = new Hashtable(); // 连接
/**
* 返回唯一实例.如果是第一次调用此方法,则创建实例
*
* @return DBConnectionManager 唯一实例
*/
static synchronized public DBConnectionManager getInstance() {
if (instance == null) {
instance = new DBConnectionManager();
}
clients++;
return instance;
}
/**
* 建构函数私有以防止其它对象创建本类实例
*/
public DBConnectionManager() {
init();
}
/**
* 将连接对象返回给由名字指定的连接池
*
* @param name
* 在属性文件中定义的连接池名字
* @param con
* 连接对象
*/
public void freeConnection(String name, Connection con) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
pool.freeConnection(con);
} else {
System.out.println("pool ==null");
}
clients--;
}
/**
* 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数 限制,则创建并返回新连接
*
* @param name
* 在属性文件中定义的连接池名字
* @return Connection 可用连接或null
*/
public Connection getConnection(String name) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
// return pool.getConnection();
return pool.returnConnection();
}
return null;
}
/**
* 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制, 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.
*
* @param name
* 连接池名字
* @param time
* 以毫秒计的等待时间
* @return Connection 可用连接或null
*/
public Connection getConnection(String name, long time) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
return pool.getConnection(time);
}
return null;
}
/**
* 关闭所有连接,撤销驱动程序的注册
*/
public synchronized void release() {
// 等待直到最后一个客户程序调用
if (--clients != 0) {
return;
}
Enumeration allPools = pools.elements();
while (allPools.hasMoreElements()) {
DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();
pool.release();
}
Enumeration allDrivers = drivers.elements();
while (allDrivers.hasMoreElements()) {
Driver driver = (Driver) allDrivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
log("撤销JDBC驱动程序 " + driver.getClass().getName() + "的注册");
} catch (SQLException e) {
log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());
}
}
}
/**
* 根据指定属性创建连接池实例.
*
* @param props
* 连接池属性
*/
private void createPools(Properties props) {
Enumeration propNames = props.propertyNames();
while (propNames.hasMoreElements()) {
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("没有为连接池" + poolName + "指定URL");
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("错误的最大连接数限制: " + maxconn + " .连接池: " + poolName);
max = 0;
}
DBConnectionPool pool = new DBConnectionPool(poolName, url,
user, password, max);
pools.put(poolName, pool);
log("成功创建连接池" + poolName);
}
}
}
/**
* 读取属性完成初始化
*/
private void init() {
try {
// Properties p = new Properties();
String configs = System.getProperty("user.dir")
+ "\\conf\\db.properties";
System.out.println("configs file local at " + configs);
FileInputStream is = new FileInputStream(configs);
Properties dbProps = new Properties();
try {
dbProps.load(is);
} catch (Exception e) {
System.err.println("不能读取属性文件. "
+ "请确保db.properties在CLASSPATH指定的路径中");
return;
}
String logFile = dbProps.getProperty("logfile",
"DBConnectionManager.log");
try {
log = new PrintWriter(new FileWriter(logFile, true), true);
} catch (IOException e) {
System.err.println("无法打开日志文件: " + logFile);
log = new PrintWriter(System.err);
}
loadDrivers(dbProps);
createPools(dbProps);
} catch (Exception e) {
}
}
/**
* 171 * 装载和注册所有JDBC驱动程序 172 * 173 *
*
* @param props
* 属性 174
*/
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);
System.out.println(driverClassName);
log("成功注册JDBC驱动程序" + driverClassName);
} catch (Exception e) {
log("无法注册JDBC驱动程序: " + driverClassName + ", 错误: " + e);
}
}
}
/**
* 将文本信息写入日志文件
*/
private void log(String msg) {
log.println(new Date() + ": " + msg);
}
/**
* 将文本信息与异常写入日志文件
*/
private void log(Throwable e, String msg) {
log.println(new Date() + ": " + msg);
e.printStackTrace(log);
}
/**
* 类DBConnectionPool的作用: 从连接池获取(或创建)可用连接。 把连接返回给连接池 在系统关闭时释放所有资源,关闭所有连接。
* 处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题)。 限制连接池中的连接总数不超过某个预定值。
*/
class DBConnectionPool {
// private int checkedOut;
private Vector freeConnections = new Vector();
private int maxConn;
private String name;
private String password;
private String URL;
private String user;
/**
* 创建新的连接池
*
* @param name
* 连接池名字
* @param URL
* 数据库的JDBC URL
* @param user
* 数据库帐号,或 null
* @param password
* 密码,或 null
* @param maxConn
* 此连接池允许建立的最大连接数,0表示没有限制
*/
public DBConnectionPool(String name, String URL, String user,
String password, int maxConn) {
this.name = name;
this.URL = URL;
this.user = user;
this.password = password;
this.maxConn = maxConn;
}
/**
* 将不再使用的连接返回给连接池
*
* @param con
* 客户程序释放的连接
*/
public synchronized void freeConnection(Connection con) {
// 将指定连接加入到向量末尾
try {
if (con.isClosed()) {
System.out.println("before freeConnection con is closed");
}
freeConnections.addElement(con);
Connection contest = (Connection) freeConnections.lastElement();
if (contest.isClosed()) {
System.out.println("after freeConnection contest is closed");
}
notifyAll();
} catch (SQLException e) {
System.out.println(e);
}
}
/**
* 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,
* 然后递归调用自己以尝试新的可用连接.
*/
public synchronized Connection getConnection() {
Connection con = null;
if (freeConnections.size() > 0) {
// 获取向量中第一个可用连接
con = (Connection) freeConnections.firstElement();
freeConnections.removeElementAt(0);
try {
if (con.isClosed()) {
log("从连接池" + name + "删除一个无效连接");
System.out.println("从连接池" + name + "删除一个无效连接");
// 递归调用自己,尝试再次获取可用连接
con = getConnection();
}
} catch (SQLException e) {
log("从连接池" + name + "删除一个无效连接时错误");
System.out.println("从连接池" + name + "删除一个无效连接出错");
// 递归调用自己,尝试再次获取可用连接
con = getConnection();
}
if (freeConnections.size() > maxConn) {
System.out.println(" 删除一个溢出连接 ");
releaseOne();
}
}
else if ((maxConn == 0) || (freeConnections.size() < maxConn)) {
con = newConnection();
}
return con;
}
public synchronized Connection returnConnection() {
Connection con = null;
// 如果闲置小于最大连接,返回一个新连接
if (freeConnections.size() < maxConn) {
con = newConnection();
}
// 如果闲置大于最大连接,返回一个可用的旧连接
else if (freeConnections.size() >= maxConn) {
con = (Connection) freeConnections.firstElement();
System.out.println(" [a 连接池可用连接数 ] : " + "[ "
+ freeConnections.size() + " ]");
freeConnections.removeElementAt(0);
System.out.println(" [b 连接池可用连接数 ] : " + "[ "
+ freeConnections.size() + " ]");
try {
if (con.isClosed()) {
log("从连接池" + name + "删除一个无效连接");
System.out.println("从连接池" + name + "删除一个无效连接");
returnConnection();
}
} catch (SQLException e) {
log("从连接池" + name + "删除一个无效连接时错误");
System.out.println("从连接池" + name + "删除一个无效连接出错");
returnConnection();
}
}
return con;
}
/**
* 从连接池获取可用连接.可以指定客户程序能够等待的最长时间 参见前一个getConnection()方法.
*
* @param timeout
* 以毫秒计的等待时间限制
*/
public synchronized Connection getConnection(long timeout) {
long startTime = new Date().getTime();
Connection con;
while ((con = getConnection()) == null) {
try {
wait(timeout);
} catch (InterruptedException e) {
}
if ((new Date().getTime() - startTime) >= timeout) {
// wait()返回的原因是超时
return null;
}
}
return con;
}
/**
* 关闭所有连接
*/
public synchronized void release() {
Enumeration allConnections = freeConnections.elements();
while (allConnections.hasMoreElements()) {
Connection con = (Connection) allConnections.nextElement();
try {
con.close();
log("关闭连接池" + name + "中的一个连接");
} catch (SQLException e) {
log(e, "无法关闭连接池" + name + "中的连接");
}
}
freeConnections.removeAllElements();
}
/**
* 关闭一个连接
*/
public synchronized void releaseOne() {
if (freeConnections.firstElement() != null) {
Connection con = (Connection) freeConnections.firstElement();
try {
con.close();
System.out.println("关闭连接池" + name + "中的一个连接");
log("关闭连接池" + name + "中的一个连接");
} catch (SQLException e) {
System.out.println("无法关闭连接池" + name + "中的一个连接");
log(e, "无法关闭连接池" + name + "中的连接");
}
} else {
System.out
.println("releaseOne() bug.......................................................");
}
}
/**
* 创建新的连接
*/
private Connection newConnection() {
Connection con = null;
try {
if (user == null) {
con = DriverManager.getConnection(URL);
} else {
con = DriverManager.getConnection(URL, user, password);
}
log("连接池" + name + "创建一个新的连接");
} catch (SQLException e) {
log(e, "无法创建下列URL的连接: " + URL);
return null;
}
return con;
}
}
}