手动创建JDBC及连接池封装等

Posted 嗨小叔的程序猿之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手动创建JDBC及连接池封装等相关的知识,希望对你有一定的参考价值。

一、适用场景

    有些时候在改造别人代码的时候,无法嵌入通用的一些ORM框架,跟现有框架容易冲突,但是又不想使用现有框架的写法,那么这时候就需要手写JDBC。

    国庆前小叔在深圳一家500强企业做MES项目开发时候,应该算是三开了,公司首期花了大价钱使用了SAP ME的产品,可惜维护不力加上人员更迭,后面人就不懂了,然后找了一家公司二开,但是二开完,那家公司貌似做不下去了,后面尾款都没收就跑了,然后就有了三开;

   系统存在三个独立的分布式的数据库(正式库、中转库(包涵ME的标准表)、历史库),底层连接使用了druid连接池,但是事务管理使用了JTA,底层采用了NamedParameterJdbcTemplate的封装,导致想要改写这些东西,又会影响到二期的功能,所以就另外封装了一套JDBC,并且封装了一些通用的增删改差之类的方法。


二、整体介绍

    1、JDBC连接管理工具类:主要为连接的建立、关闭

    2、JDBC连接工具类:包含从连接池获取连接、通用的连接方法

    3、JDBC连接池工具类:获取框架DruidXADataSource连接池对象

    4、结果解析工具类:主要为将查询返回结果转化为想要的对象格式

   5、其他:静态文件,获取框架的配置信息(JDBC连接、账号、密码等);枚举类,用于指定对应数据库源(正式库、中转库、测试库);框架的基础配置等


三、代码介绍

  1、db.properties

2、db.xml大致如下:

    需要引入上面的db.properties

    Druid数据源大致配置如下:

     

手动创建JDBC及连接池封装等

3、静态文件,获取以上的xml配置值

    Global.Java   

import java.io.File;import java.io.IOException;import java.nio.charset.Charset;import java.util.Map;import java.util.concurrent.BlockingQueue;import java.util.concurrent.LinkedBlockingQueue;
import org.apache.commons.lang3.StringUtils;import org.springframework.core.io.DefaultResourceLoader;
import com.google.common.collect.Maps;public class Global { /** * 当前对象实例 */    private static Global global = new Global(); /** * 保存全局属性值 */    private static Map<StringString> map = Maps.newHashMap(); /** * 属性文件加载对象 */    private static PropertiesLoader loader = new PropertiesLoader("db.properties");  /** * 获取当前对象实例 */ public static Global getInstance() { return global;    } /** * 获取配置 */ public static String getConfig(String key) { String value = map.get(key); if (value == null) { value = loader.getProperty(key); map.put(key, value != null ? value : StringUtils.EMPTY); } return value; }    // 数据源及相关参数设置 public static final String DB_URL =getConfig("productionJdbc.url"); public static final String DB_USERNAME =getConfig("productionJdbc.username"); public static final String DB_PASSWORD =getConfig("productionJdbc.password"); public static final String DB_DRIVER =getConfig("productionJdbc.driver"); public static final String DB_INITIALSIZE =getConfig("ds.initialSize"); public static final String DB_MAXACTIVE =getConfig("ds.maxActive"); public static final String DB_MINIDLE =getConfig("ds.minIdle"); public static final String DB_MAXWAIT =getConfig("ds.maxWait"); public static final String DB_TIMEBETWEENEVICTIONRUNSMILLIS =getConfig("ds.timeBetweenEvictionRunsMillis"); public static final String DB_MINEVICTABLEIDLETIMEMILLIS =getConfig("ds.minEvictableIdleTimeMillis");
public static final String TRANSFERJDBC_DB_URL =getConfig("transferJdbc.url"); public static final String TRANSFERJDBC_DB_USERNAME =getConfig("transferJdbc.username");    public static final String  TRANSFERJDBC_DB_PASSWORD =getConfig("transferJdbc.password"); }

DbEnum.java

public enum DbEnum { PROD("1") //生产库 ,TRANSF("2"); //中转库   ,HISTORY("3"); //历史库  private String value;  private DbEnum(String value){ this.value = value; }
public String getValue() { return value; }
@Override public String toString() { return this.value; } }

4、JDBC连接池建立工具

JdbcPoolTool.java

import java.sql.Connection;import java.sql.SQLException;
import com.alibaba.druid.pool.xa.DruidXADataSource;import com.byd.mes.base.utils.Global;import com.byd.mes.base.utils.JdbcUtil;import com.byd.mes.base.utils.SpringBeanUtill;import com.byd.mes3.exception.BizException;
public class JdbcPoolTool {
private static DruidXADataSource dataSourcePro = null; private static DruidXADataSource dataSourceTrans = null; /** * 获取数据库连接 * @param dbEnum * @return */ public static Connection getConnection(DbEnum dbEnum){ Connection conn = getConectionOfPool(dbEnum); return conn; } /** * 根据不同的数据库从框架中获取Druid连接池 * @param dbEnum * @return */ private static Connection getConectionOfPool(DbEnum dbEnum){ DruidXADataSource ds = null; Connection poolConn = null; switch(dbEnum.getValue()){ case "1": ds = (DruidXADataSource) SpringBeanUtill.getBean("productionJdbcXADataSource"); break; case "2": ds = (DruidXADataSource) SpringBeanUtill.getBean("transferJdbcXADataSource"); break; default: ds = (DruidXADataSource) SpringBeanUtill.getBean("productionJdbcXADataSource"); break; } if(ds.isClosed() || ds == null){ ds = setDruidXADataSource(dbEnum); } try { poolConn = ds.getConnection(); } catch (SQLException e) { e.printStackTrace(); throw new BizException("获取数据库连接出错!"); } if(poolConn == null ){ // 如果实在不行,手动建立JDBC连接 switch(dbEnum.getValue()){ case "1": poolConn = JdbcUtil.getConnection(Global.DB_URL,Global.DB_USERNAME,Global.DB_PASSWORD); break; case "2": poolConn = JdbcUtil.getConnection(Global.TRANSFERJDBC_DB_URL,Global.TRANSFERJDBC_DB_USERNAME,Global.TRANSFERJDBC_DB_PASSWORD); break; default: poolConn = JdbcUtil.getConnection(Global.DB_URL,Global.DB_USERNAME,Global.DB_PASSWORD); break; } } return poolConn; }
/** * 获取配置文件,并赋值 * @param dbEnum * @param poolConn * @return */ private static DruidXADataSource setDruidXADataSource(DbEnum dbEnum) { switch(dbEnum.getValue()){ case "1": if(dataSourcePro != null){ return dataSourcePro; } dataSourcePro = getDataSourcePro(); return dataSourcePro; case "2": if(dataSourceTrans != null){ return dataSourceTrans; } dataSourceTrans = getDataSourceTrans(); return dataSourceTrans; default: dataSourcePro = getDataSourcePro(); return dataSourcePro; } } /** * 获取生产库连接池对象 * @return */ private static DruidXADataSource getDataSourcePro() { DruidXADataSource ds = new DruidXADataSource(); setCommJdbc(ds); ds.setUrl(Global.DB_URL); ds.setUsername(Global.DB_USERNAME); ds.setPassword(Global.DB_PASSWORD); return ds; } /** * 获取中转库连接池对象 * @return */ private static DruidXADataSource getDataSourceTrans() { DruidXADataSource ds = new DruidXADataSource(); setCommJdbc(ds); ds.setUrl(Global.TRANSFERJDBC_DB_URL); ds.setUsername(Global.TRANSFERJDBC_DB_USERNAME); ds.setPassword(Global.TRANSFERJDBC_DB_PASSWORD); return ds; }
/** * 设置JDBC通用属性(请参考 applicationContext-db.xml 和 application.properties文件的配置) * @param dbEnum * @return */ private static void setCommJdbc(DruidXADataSource ds){ //配置初始化大小、最小、最大 ds.setInitialSize(Integer.parseInt(Global.DB_INITIALSIZE)); ds.setMaxActive(Integer.parseInt(Global.DB_MAXACTIVE)); ds.setMinIdle(Integer.parseInt(Global.DB_MINIDLE)); //配置获取连接等待超时的时间 ds.setMaxWait(Integer.parseInt(Global.DB_MAXWAIT)); //配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 ds.setTimeBetweenEvictionRunsMillis(Long.parseLong(Global.DB_TIMEBETWEENEVICTIONRUNSMILLIS)); //配置一个连接在池中最小生存的时间,单位是毫秒 ds.setMinEvictableIdleTimeMillis(Long.parseLong(Global.DB_MINEVICTABLEIDLETIMEMILLIS)); //配置连接驱动 ds.setDriverClassName(Global.DB_DRIVER); //设置驱动 //连接泄漏监测 超过removeAbandonedTimeout时间后,是否进行没用连接(废弃)的回收 ds.setRemoveAbandoned(false); ds.setRemoveAbandonedTimeout(60); //防止过期 ds.setValidationQuery("SELECT * FROM DUAL"); ds.setTestWhileIdle(true); ds.setTestOnBorrow(false); ds.setTestOnReturn(false); //关闭abanded连接时输出错误日志,将会在回收事件后,在log中打印出回收Connection的错误信息,包括在哪个地方用了Connection却忘记关闭了,方便调试 ds.setLogAbandoned(true); //打开PSCache,并且指定每个连接上PSCache的大小 ds.setPoolPreparedStatements(true); ds.setMaxPoolPreparedStatementPerConnectionSize(20); } }

5、JdbcUtil工具类(用于关闭连接)

import java.sql.CallableStatement;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;
public class JdbcUtil { /** * * 释放资源方法 */ public static void close(PreparedStatement ps , Connection conn){ if (ps != null){ try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } /** * * 释放资源方法 */ public static void close(CallableStatement ps , Connection conn){ if (ps != null){ try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } /** * 释放资源方法 */ public static void close(ResultSet rs, Statement stmt, Connection conn) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } /** * 释放资源方法 */ public static void close(ResultSet rs, CallableStatement stmt, Connection conn) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } }
/** * 释放资源方法 */ public static void close(Statement stmt, Connection conn) { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } }}

6、数据库连接使用工具(后台增删改查通过这个工具类)

JdbcTool.JAVA

import java.math.BigDecimal;import java.sql.Array;import java.sql.Blob;import java.sql.CallableStatement;import java.sql.Clob;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Types;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;
public class JdbcTool {
public static Connection getConnectionByDb(Connection conn ,DbEnum dbEnum){ switch(dbEnum.getValue()){ case "1": conn = JdbcPoolTool.getConnection(DbEnum.PROD); break; case "2": conn = JdbcPoolTool.getConnection(DbEnum.TRANSF); break; default: conn = JdbcPoolTool.getConnection(DbEnum.PROD); break; } return conn; } public static List<Map<String,Object>> queryForMap(DbEnum dbEnum,String sql){ Connection conn = null; PreparedStatement psmt = null; ResultSet rs = null; List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); try { conn = getConnectionByDb(conn,dbEnum); psmt = conn.prepareStatement(sql); rs = psmt.executeQuery(); list = ResultSetTool.resultSetToListMap(rs); } catch (Exception e) { JdbcUtil.close(rs, psmt, conn); throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(rs, psmt, conn); } return list; } public static Map<String,Object> queryForMapSingle(DbEnum dbEnum,String sql){ List<Map<String,Object>> list = queryForMap(dbEnum,sql); Map<String,Object> map = new HashMap<String,Object>(); if(list != null && list.size() >0){ map = list.get(0); } return map; } public static List<Map<String,Object>> queryForMap(DbEnum dbEnum,String sql,List<Object> paramsList){ Connection conn = null; PreparedStatement psmt = null; ResultSet rs = null; List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); if(paramsList != null && paramsList.size() >0){ if(countInterrogation(sql) != paramsList.size()){ throw new BizException("传入的参数个数不符合!执行语句"+sql+"传入的参数个数为"+paramsList.size()); } } try { conn = getConnectionByDb(conn,dbEnum); psmt = conn.prepareStatement(sql); psmt = ResultSetTool.listObjectSetToPs(paramsList, psmt); rs = psmt.executeQuery(); list = ResultSetTool.resultSetToListMap(rs); } catch (Exception e) { JdbcUtil.close(rs, psmt, conn); throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(rs, psmt, conn); } return list; } public static Map<String,Object> queryForMapSingle(DbEnum dbEnum,String sql,List<Object> paramsList){ List<Map<String,Object>> list = queryForMap(dbEnum,sql,paramsList); Map<String,Object> map = new HashMap<String,Object>(); if(list != null && list.size() >0){ map = list.get(0); } return map; } public static <T> List<T> queryForList(DbEnum dbEnum,String sql,Class<T> clazz){ Connection conn = null; PreparedStatement psmt = null; ResultSet rs = null; List<T> list = new ArrayList<>(); try { conn = getConnectionByDb(conn,dbEnum); psmt = conn.prepareStatement(sql); rs = psmt.executeQuery(); list =ResultSetTool.resultSetToListBean(rs, clazz); } catch (Exception e) { JdbcUtil.close(rs, psmt, conn); throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(rs, psmt, conn); } return list; } public static <T> T queryForBean(DbEnum dbEnum,String sql,Class<T> clazz){ List<T> list = queryForList(dbEnum,sql, clazz); if(list != null && list.size() >0){ return list.get(0); } return null; } public static <T> List<T> queryForList(DbEnum dbEnum,String sql,List<Object> paramsList,Class<T> clazz){ Connection conn = null; PreparedStatement psmt = null; ResultSet rs = null; List<T> list = new ArrayList<>(); if(paramsList != null && paramsList.size() >0){ if(countInterrogation(sql) != paramsList.size()){ throw new BizException("传入的参数个数不符合!执行语句"+sql+"传入的参数个数为"+paramsList.size()); } } try { conn = getConnectionByDb(conn,dbEnum); psmt = conn.prepareStatement(sql); psmt = ResultSetTool.listObjectSetToPs(paramsList, psmt); rs = psmt.executeQuery(); list =ResultSetTool.resultSetToListBean(rs, clazz); } catch (Exception e) { JdbcUtil.close(rs, psmt, conn); throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(rs, psmt, conn); } return list; }  /**   * 更新   **/ public static void update(DbEnum dbEnum,String sql){ Connection conn = null; PreparedStatement psmt = null; ResultSet rs = null; try { conn = getConnectionByDb(conn,dbEnum); //设置事务属性 conn.setAutoCommit(false); psmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); psmt.executeUpdate(); //提交,设置事务初始值 conn.commit(); conn.setAutoCommit(true); } catch (Exception e) { try{ //提交失败,执行回滚操作 conn.rollback(); }catch (SQLException sqlE) { sqlE.printStackTrace(); throw new BizException("执行出错,错误原因:"+e.getMessage()+",回滚执行失败!!!"); } JdbcUtil.close(rs, psmt, conn); throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(rs, psmt, conn); } } public static void update(DbEnum dbEnum,String sql,List<Object> paramsList){ Connection conn = null; PreparedStatement psmt = null; ResultSet rs = null; try { conn = getConnectionByDb(conn,dbEnum); //设置事务属性 conn.setAutoCommit(false); psmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); psmt = ResultSetTool.listObjectSetToPs(paramsList, psmt); psmt.executeUpdate(); //提交,设置事务初始值 conn.commit(); conn.setAutoCommit(true); } catch (Exception e) { try{ //提交失败,执行回滚操作 conn.rollback(); }catch (SQLException sqlE) { sqlE.printStackTrace(); throw new BizException("执行出错,错误原因:"+e.getMessage()+",回滚执行失败!!!"); } JdbcUtil.close(rs, psmt, conn); throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(rs, psmt, conn); } } public static void batchUpdate(DbEnum dbEnum,String sql,List<List<Object>> paramsList){ Connection conn = null; PreparedStatement psmt = null; ResultSet rs = null; //sql包含问号个数 int count = countInterrogation(sql); for(List<Object> list:paramsList){ if(list.size() != count){ throw new BizException("传入的参数个数不符合!执行语句"+sql+"传入的参数个数为"+ list.size()); } } try { conn = getConnectionByDb(conn,dbEnum); //设置事务属性 conn.setAutoCommit(false); psmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); for(int i=0; i<paramsList.size(); i++){ psmt = ResultSetTool.listObjectSetToPs(paramsList.get(i), psmt); psmt.addBatch(); } psmt.executeBatch(); //提交,设置事务初始值 conn.commit(); conn.setAutoCommit(true); } catch (Exception e) { try{ //提交失败,执行回滚操作 conn.rollback(); }catch (SQLException sqlE) { sqlE.printStackTrace(); throw new BizException("执行出错,错误原因:"+e.getMessage()+",回滚执行失败!!!"); } JdbcUtil.close(rs, psmt, conn); throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(rs, psmt, conn); } } /** * 调用无参无返回值存储过程 * @param dbEnum * @param procedureName */ public static void callProcedureNon(DbEnum dbEnum,String procedureName){ Connection conn = null; CallableStatement cstmt = null; try { conn = getConnectionByDb(conn,dbEnum); StringBuilder strSb = new StringBuilder(); strSb.append(" {call "); strSb.append(procedureName); strSb.append("()}"); cstmt = conn.prepareCall(strSb.toString()); cstmt.execute(); } catch (Exception e) { throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(cstmt, conn); } } /** * 调用无参有返回值的存储过程 * @param dbEnum * @param procedureName * @return */ public static List<Object> callProcedure(DbEnum dbEnum,String procedureName){ Connection conn = null; CallableStatement cstmt = null; ResultSet rs = null; List<Object> list = new ArrayList<Object>(); try { conn = getConnectionByDb(conn,dbEnum); StringBuilder strSb = new StringBuilder(); strSb.append(" {call "); strSb.append(procedureName); strSb.append("()}"); cstmt = conn.prepareCall(strSb.toString()); rs = cstmt.executeQuery(); while(rs.next()){ int rowNum = rs.getRow(); for(int i=0;i<rowNum;i++){ list.add(rs.getObject(i)); } } } catch (Exception e) { throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(rs, cstmt, conn); } return list; } /** * 调用有参无返回值的存储过程 * @param dbEnum * @param procedureName * @param ins */ public static void callProcedure(DbEnum dbEnum,String procedureName,List<Object> ins){ Connection conn = null; CallableStatement cstmt = null; try { conn = getConnectionByDb(conn,dbEnum); StringBuilder strSb = new StringBuilder(); strSb.append(" {call "); strSb.append(procedureName); strSb.append("("); if(ins != null && ins.size() > 0){ for(int i=0;i<ins.size(); i++){ strSb.append("?,"); } strSb.setLength(strSb.length()-1); } strSb.append(")}"); cstmt = conn.prepareCall(strSb.toString()); cstmt = listOject2CallableStatement(cstmt,ins); cstmt.execute(); } catch (Exception e) { throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(cstmt, conn); } } /** * 调用有出入参的存储过程 * @param dbEnum * @param procedureName * @param ins */ public static List<Object> callProcedure(DbEnum dbEnum,String procedureName,List<Object> ins,List<ProcedureOutParameter> outs){ Connection conn = null; CallableStatement cstmt = null; List<Object> result = new ArrayList<Object>(); try { conn = getConnectionByDb(conn,dbEnum); StringBuilder strSb = new StringBuilder(); strSb.append(" {call "); strSb.append(procedureName); strSb.append("("); if(ins != null && ins.size() > 0){ for(int i=0; i<ins.size(); i++){ strSb.append("?,"); } if(outs != null && outs.size() >0){ for(int j=0; j<outs.size(); j++){ strSb.append("?,"); } } strSb.setLength(strSb.length()-1); } strSb.append(")}"); cstmt = conn.prepareCall(strSb.toString()); cstmt = listOject2CallableStatement(cstmt,ins); if(outs != null && outs.size() >0){ for(int j=0; j<outs.size(); j++){ cstmt.registerOutParameter(outs.get(j).getLeft(), outs.get(j).getRight()); } } cstmt.execute(); if(outs != null && outs.size() >0){ for(int j=0; j<outs.size(); j++){ int type = outs.get(j).getRight(); int left = outs.get(j).getLeft(); switch(type){ case Types.CHAR: result.add(cstmt.getString(left)); break; case Types.DATE: result.add(cstmt.getDate(left)); break; case Types.INTEGER: result.add(cstmt.getBigDecimal(left)); break; case Types.FLOAT: result.add(cstmt.getBigDecimal(left)); break; case Types.DOUBLE: result.add(cstmt.getBigDecimal(left)); break; case Types.BOOLEAN: result.add(cstmt.getBoolean(left)); break; case Types.BLOB: result.add(cstmt.getBlob(left)); break; case Types.CLOB: result.add(cstmt.getClob(left)); break; case Types.NVARCHAR: result.add(cstmt.getString(left)); break; case Types.VARCHAR: result.add(cstmt.getString(left)); break; case Types.TIME: result.add(cstmt.getTime(left)); break; case Types.TIMESTAMP: result.add(cstmt.getTimestamp(left)); break; default: result.add(cstmt.getObject(left)); break; } } } } catch (Exception e) { throw new BizException(e.getMessage()); }finally{ JdbcUtil.close(cstmt, conn); } return result; } public static CallableStatement listOject2CallableStatement(CallableStatement cstmt,List<Object> params){ if(cstmt != null && params != null && params.size() >0){ try{ for(int i=0; i<params.size(); i++){ Object p = params.get(i); if(p instanceof Integer){ cstmt.setInt(i+1, (Integer)p); }else if(p instanceof String){ cstmt.setString(i+1, (String)p); }else if(p instanceof Boolean){ cstmt.setBoolean(i+1, (Boolean)p); }else if(p instanceof Date){ // psmt.setDate(i+1, getDate((Date)p)); cstmt.setTimestamp(i+1, ResultSetTool.getTimestamp((Date)p)); }else if(p instanceof Double){ cstmt.setDouble(i+1, (Double)p); }else if(p instanceof Float){ cstmt.setFloat(i+1, (Float)p); }else if(p instanceof Long){ cstmt.setLong(i+1, (Long)p); }else if(p instanceof Blob){ cstmt.setBlob(i+1, (Blob)p); }else if(p instanceof Array){ cstmt.setArray(i+1, (Array)p); }else if(p instanceof BigDecimal){ cstmt.setBigDecimal(i+1, (BigDecimal)p); }else if(p instanceof Byte){ cstmt.setByte(i+1, (Byte)p); }else if(p instanceof Clob){ cstmt.setClob(i+1, (Clob)p); }else{ cstmt.setString(i+1, (String)p); } } }catch(Exception e){ throw new BizException("调用存储过程入参转换错误:"+e.getMessage()); } } return cstmt; } /** * 计算字符串包含的问号数量 * @param str * @return */ private static int countInterrogation(String str){ int count = 0; for(int i=0;i<str.length();i++){ if(str.charAt(i) == '?'){ count++; } } return count; } }

7、JDBC的ResultSet工具类

ResultSetTool.java

import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.math.BigDecimal;import java.sql.Array;import java.sql.Blob;import java.sql.Clob;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;import java.sql.Timestamp;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;
import net.sf.json.JSONArray;import net.sf.json.JSONException;import net.sf.json.JSONObject;
/** * JDBC的ResultSet工具类 * @author jianbin.lei * @date 2019-09-03 */public class ResultSetTool {
/** * 转换数据 JDBC结果集转实体 * * @param resultSet 结果集 * @param clazz 实体字节码文件对象 * @param <T> 实体类型 * @throws Exception sql异常 NoClass异常等等 */ public static <T> List<T> resultSetToListBean(ResultSet resultSet, Class<T> clazz) throws Exception { //获取全部类方法 包括父类的 Method[] declaredMethods = clazz.getMethods(); List<T> list = new ArrayList<>(); ResultSetMetaData metaData = resultSet.getMetaData(); while (resultSet.next()) { //反射实例化对象 T obj = clazz.newInstance(); //遍历类调用方法 for (Method method : declaredMethods) { //获取方法名 String name = method.getName(); if (!name.startsWith("set")){ //只要setter continue; } //获取数据库名 驼峰命名法转数据库字段命名法 String dbName = getDbName(name); //遍历数据库所有列 for (int i = 1; i <= metaData.getColumnCount(); i++) { //抓取指定列赋值 if (metaData.getColumnName(i).equalsIgnoreCase(dbName)) { if (resultSet.getObject(i) != null) { //赋值 setValue(obj,method,resultSet,i); } break; } } } list.add(obj); } return list; } /** * 将resultSet转换为List<Map<String,Object>> * @param rs * @return * @throws Exception */ public static List<Map<String,Object>> resultSetToListMap(ResultSet rs) throws Exception { //获取全部类方法 包括父类的 List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); // 遍历ResultSet中的每条数据 while (rs.next()) { Map<String,Object> map = new HashMap<String,Object>(); // 遍历每一列 for (int i = 1; i <= columnCount; i++) { String columnName =metaData.getColumnLabel(i); String value = rs.getString(columnName); map.put(columnName, value); } list.add(map); } return list; } /** * 将resultSet转化为JSON数组 * @param rs * @return * @throws SQLException * @throws JSONException */ public static JSONArray resultSetToJsonArry(ResultSet rs) throws SQLException,JSONException { // json数组 JSONArray array = new JSONArray(); // 获取列数 ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); // 遍历ResultSet中的每条数据 while (rs.next()) { JSONObject jsonObj = new JSONObject(); // 遍历每一列 for (int i = 1; i <= columnCount; i++) { String columnName =metaData.getColumnLabel(i); String value = rs.getString(columnName); jsonObj.put(columnName, value); } array.add(jsonObj); } return array; }
/** * 将resultSet转化为JSONObject * @param rs * @return * @throws SQLException * @throws JSONException */ public static JSONObject resultSetToJsonObject(ResultSet rs) throws SQLException,JSONException { // json对象 JSONObject jsonObj = new JSONObject();
// 获取列数 ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); // 遍历ResultSet中的每条数据 if (rs.next()) { // 遍历每一列 for (int i = 1; i <= columnCount; i++) { String columnName = metaData.getColumnLabel(i); String value = rs.getString(columnName); jsonObj.put(columnName, value); } } return jsonObj; }
/** * 将list参数设置到PreparedStatement中 * @param list * @param psmt * @return * @throws SQLException */ public static PreparedStatement listObjectSetToPs(List<Object> params,PreparedStatement psmt) throws SQLException{ if(params != null && params.size() >0){ for(int i=0;i<params.size();i++){ Object p = params.get(i); if(p instanceof Integer){ psmt.setInt(i+1, (Integer)p); }else if(p instanceof String){ psmt.setString(i+1, (String)p); }else if(p instanceof Boolean){ psmt.setBoolean(i+1, (Boolean)p); }else if(p instanceof Date){// psmt.setDate(i+1, getDate((Date)p)); psmt.setTimestamp(i+1, getTimestamp((Date)p)); }else if(p instanceof Double){ psmt.setDouble(i+1, (Double)p); }else if(p instanceof Float){ psmt.setFloat(i+1, (Float)p); }else if(p instanceof Long){ psmt.setLong(i+1, (Long)p); }else if(p instanceof Blob){ psmt.setBlob(i+1, (Blob)p); }else if(p instanceof Array){ psmt.setArray(i+1, (Array)p); }else if(p instanceof BigDecimal){ psmt.setBigDecimal(i+1, (BigDecimal)p); }else if(p instanceof Byte){ psmt.setByte(i+1, (Byte)p); }else if(p instanceof Clob){ psmt.setClob(i+1, (Clob)p); }else{ psmt.setString(i+1, (String)p); } } } return psmt; } public static Timestamp getTimestamp(Date date){ return new Timestamp(date.getTime()); } public static java.sql.Date getDate(long time){ return new java.sql.Date(time); }
public static java.sql.Date getDate(Date date){ return new java.sql.Date(date.getTime()); }
/** * 赋值操作, * 主要是处理数据类型 * 此处只简单处理下基本数据类型和Date类型 * @param obj 泛型对象 * @param method 方法 * @param resultSet 结果集 * @param i 脚标 * @param <T> 泛型 */ private static <T> void setValue(T obj, Method method, ResultSet resultSet, int i) throws SQLException, InvocationTargetException, IllegalAccessException { //Setter方法只有一个参数,获取参数类型名称 String name = method.getParameterTypes()[0].getName().toLowerCase(); if (name.contains("string")){ method.invoke(obj, resultSet.getString(i)); }else if (name.contains("short")){ method.invoke(obj,resultSet.getShort(i)); }else if (name.contains("int") || name.contains("integer")){ method.invoke(obj,resultSet.getInt(i)); }else if (name.contains("bigdecimal")){ method.invoke(obj,resultSet.getBigDecimal(i)); }else if(name.contains("long")){ method.invoke(obj,resultSet.getLong(i)); }else if (name.contains("float")){ method.invoke(obj,resultSet.getFloat(i)); }else if (name.contains("double")){ method.invoke(obj,resultSet.getDouble(i)); }else if (name.contains("boolean")){ method.invoke(obj,resultSet.getBoolean(i)); }else if (name.contains("date")){ method.invoke(obj,resultSet.getDate(i)); }else { method.invoke(obj, resultSet.getObject(i)); } }
/** * 实体setter名称转对应数据库列的列名 * 需要遵守命名规范,java(驼峰命名法),数据库(全小写,单词间用'_'隔开) * @param name setter名称 * @return 数据库列名 */ private static String getDbName(String name) { //根据setter命名规则获取对应的属性名 name = name.substring(3,4).toLowerCase()+name.substring(4); //获取数据库对应列名 StringBuffer buffer = new StringBuffer(); char[] nameChars = name.toCharArray(); for (char nameChar : nameChars) { if (nameChar >= 'A' && nameChar <= 'Z') { //将大写字母转换为下划线和对应的小写字母组合 buffer.append("_").append(String.valueOf(nameChar).toLowerCase()); } else { buffer.append(String.valueOf(nameChar)); } } return buffer.toString(); }}


四、使用

1、更新

 StringBuilder sql = new StringBuilder(); sql.append(" UPDATE MES3_BASKET SET BASKET_NO =?,BASKET_NAME=?"); sql.append(" ,BASKET_DESC =?,BASKET_QTY=?,MODIFY_USER=? "); sql.append(" ,MODIFY_DATE=sysdate,BASKET_KZLS=?,BASKET_TYPE=?"); sql.append(" WHERE PID= ?");  List<Object> paramsList = new ArrayList<>(); paramsList.add(map.get("BASKET_NO")); paramsList.add(map.get("BASKET_NAME")); paramsList.add(map.get("BASKET_DESC")); paramsList.add(map.get("BASKET_QTY")); paramsList.add(map.get("MODIFY_USER")); paramsList.add(map.get("BASKET_KZLS")); paramsList.add(map.get("BASKET_TYPE")); paramsList.add(map.get("PID")); JdbcTool.update(DbEnum.PROD, sql.toString(), paramsList);

2、查询返回单条数据的Map

String sfc = "1000020001";StringBuilder sqlSb = new StringBuilder();sqlSb.append(" SELECT DATA03 FROM Z_FORMES_SFC WHERE SFC ='").append(sfc).append("'");Map<String,Object> sfcMap = JdbcTool.queryForMapSingle(DbEnum.PROD, sqlSb.toString());

3、查询返回实体类对象

StringBuilder sqlSb = new StringBuilder();sqlSb.append("SELECT * FROM STUDENT WHERE NAME='张三'");return JdbcTool.queryForBean(DbEnum.PROD, sqlSb.toString(), Student.class);
StringBuilder sql = new StringBuilder(""); sql.append(" select PID, SEQ, NAME, OPERATION_ID, RESOURCE_ID, STATUS, STEP_MAIN_ID, SIMPLE");    sql.append(" from STEP_DETAIL "); sql.append(" where RESOURCE_ID = ? and OPERATION_ID = ? order by SEQ ");List<Object> paramsList = new ArrayList<>();paramsList.add("123123");paramsList.add("2222"); List<StepDetail> param =JdbcTool.queryForList(DbEnum.PROD, sql.toString(), paramsList,StepDetail.class);

4、查询返回List Map

StringBuilder sqlSb = new StringBuilder();sqlSb.append("SELECT * FROM STUDENT");List<Map<String,Object>> cellList = JdbcTool.queryForMap(DbEnum.PROD, sqlSb.toString());
StringBuilder sql = new StringBuilder(); sql.append("SELECT a.RESRCE AS resourceNo,b.OPERATION AS opeationNo,a.HANDLE AS R_HANDLE,b.HANDLE AS O_HANDLE"); sql.append(" FROM RESRCE a"); sql.append(" INNER JOIN OPERATION b ON SUBSTR (a.OPERATION_BO, 0,INSTR (a.OPERATION_BO, ',', -2, 1)-1) = SUBSTR (b.HANDLE, 0,INSTR (b.HANDLE, ',', -2, 1)-1) "); sql.append(" WHERE 1=1 ");    sql.append(" AND a.RESRCE = ? ");//问号为占位符 sql.append(" AND a.OPERATION_BO IS NOT NULL "); sql.append(" ORDER BY RESRCE "); List<Object> paramsList = new ArrayList<>(); paramsList.add(resourceNo);//根据顺序,查询时候替换占位符 List<Map<String, Object>> param =JdbcTool.queryForMap(DbEnum.TRANSF, sql.toString(), paramsList);

5、批量更新

 List<List<Object>> paramsList = new ArrayList<>(); List<Object> params = new ArrayList<>();  params.add("112312");  params.add(112312);  params.add("3213212");  paramsList.add(params);  String sql = " DELETE FROM STEP_MAIN WHERE PID=? AND MM=? AND CC=?";  JdbcTool.batchUpdate(DbEnum.PROD, sql, paramsList);

6、存储过程调用

List<Object> ins = new ArrayList<>(); ins.add(mResource.get("OPEATIONNO"));    ins.add(map.get("SCAN_VALUE"));List<ProcedureOutParameter> outs = new ArrayList<>(); ProcedureOutParameter p = new ProcedureOutParameter(); p.setLeft(3); p.setRight(1); outs.add(p);List<Object> list = JdbcTool.callProcedure(DbEnum.PROD, "P_POD_GETFZREWORK", ins, outs);



以上是关于手动创建JDBC及连接池封装等的主要内容,如果未能解决你的问题,请参考以下文章

jdbc操作数据库(使用连接池技术)查询封装结果

关于jdbc和数据库连接池的关系(不是封装的关系)

JDBC连接池原理及分析

自定义简易JDBC连接池及测试

Tomcat-JDBC源码解析及优化

Tomcat-JDBC源码解析及优化