`
shaobo
  • 浏览: 51386 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Java 通用数据库连接类[支持存储过程 参数自动识别]

    博客分类:
  • J2SE
阅读更多

package com.hospital.dao.tools;

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;
 }

}

分享到:
评论

相关推荐

    java开源包4

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    JAVA上百实例源码以及开源项目源代码

     用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。 Java日期选择控件完整源代码 14个目标文件 内容索引:JAVA源码,系统相关,日历,...

    java开源包11

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    java开源包6

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    java开源包9

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    JAVA上百实例源码以及开源项目

     用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。 Java日期选择控件完整源代码 14个目标文件 内容索引:JAVA源码,系统相关,日历,...

    java开源包101

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    java开源包5

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    java开源包8

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    java开源包10

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    java开源包1

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    java开源包3

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    java开源包2

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    java开源包7

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    Java资源包01

    BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加...

    db-utils:数据库实用程序

    用于连接管理的单例BaseDAO:用于在数据库中存储和检索可识别对象的通用抽象类待办事项DBQueryBuilder仅支持CREATE和SELECT子句,并不意味着它是完整的。用法DBQueryBuilder SQLClause createClause = ...

    Java开发技术大全 电子版

    Java开发技术大全 电子版 第1篇Java基础知识入门. 第1章Java的开发运行环境2 1.1Java的运行环境与虚拟机2 1.2Java的开发环境4 1.2.1JDK的安装4 1.2.2如何设置系统环境变量6 1.2.3编译命令的使用8 1.2.4解释...

    基于JAVA的模拟ATM系统的设计与实现【文献综述】.pdf

    文献综述 计算机科学与技术 基于 JAVA 的模拟 ATM 系统的设计与实现 ATM 是 Automatic Teller Machine 的缩写,即自动柜员机。它是有计算机控制的持 卡人自我服务型的金融专用设备。 ATM 机可以向持卡人提供提款、...

Global site tag (gtag.js) - Google Analytics