我的程序是个socketserver,在程序启动时建立个oracle的数据库连接池,与oracle各持长连接,但有时因为网络原因,与oracle的连接会被阻断,在程序写了重新连接的代码,但在执行时却不能重新连接,报错:
java.sql.SQLException: Io 异常: Broken pipe
 at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
 at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179)
 at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:334)
 at oracle.jdbc.driver.OracleConnection.commit(OracleConnection.java:13811)
下面是我的连接池类
package jserver;import java.sql.*;
import java.util.*;
import jserver.tools.ErrorLog;public class ConnectionMgr {//连接池管理
    public ConnectionMgr() {
        try {
            jbInit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }    String driver;
  String url;
  String user;
  String pwd;
  int initCon; //连接池中初始创建连接数
  int maxCon; //连接池中允许创建的最大的连接数
  int incCon; //请求连接数大于活动连接数时,允许请求用户创建的连接数(必须大于0)
  int currCon; //当前活动连接数,包括已经从连接池中分配出去的连接和连接池中的可分配连接
  PreparedStatement pstmt;
  Hashtable connectionPool;
  Hashtable releaseconnectionPool;
  int overtime = 60;  public ConnectionMgr(String driver, String url, String user, String pwd,
                       int initCon, int maxCon, int incCon) {
    connectionPool = new Hashtable();
    releaseconnectionPool = new Hashtable();
    this.driver = driver;
    this.url = url;
    this.user=user;
    this.pwd = pwd;
    this.initCon = initCon;
    this.maxCon = maxCon;
    this.incCon = incCon;
    init();
  }  public void init() {
    try {
      System.out.println(this.url);
      System.out.println(this.user);
      System.out.println(this.pwd);
      Class.forName(driver);
      System.out.println(driver);
      for (int i = 0; i < initCon; i++) {
        try {
          Connection con = DriverManager.getConnection(this.url, this.user,
              this.pwd);
          connectionPool.put(con, new Integer(0));
        }
        catch (Exception e) {
          e.printStackTrace();
          System.err.println("ConnectionMgr.init():faild to create connection " +
                             i);
        }
        if (i == 10) {
          break;
        }
      }
    }
    catch (Exception e) {
        ErrorLog.writeLog(e);
      System.err.println("connectionMgr.init():faild to load jdbc driver:" +
                         driver);
    }
    currCon = connectionPool.size();
  }  public synchronized Connection requestCon() throws Exception {
    Connection con = null;
    Enumeration eConnections;
    con = null;
    eConnections = connectionPool.keys();
    int member = 0;
    if (eConnections.hasMoreElements()) {
      con = (Connection) eConnections.nextElement();
      if (con.isClosed()) {
        connectionPool.remove(con);
        currCon--;
        //递归调用自己,尝试再次获取可用连接
        con = requestCon();
      }
      else if (con == null) {
        con = requestCon();
      }
      else {
        //成功请求连接
        connectionPool.remove(con);
        releaseconnectionPool.put(con, new java.util.Date());
        System.out.println("requestCon:" + con);
      }
    }
    else {
      if (currCon >= maxCon) {
        boolean overtimecon = false;
        eConnections = releaseconnectionPool.keys();
        for (; eConnections.hasMoreElements(); ) {
          con = (Connection) eConnections.nextElement();
          java.util.Date date = (java.util.Date) releaseconnectionPool.get(con);
          java.util.Date crrdate = new java.util.Date();
          long time = (crrdate.getTime() - date.getTime()) / 1000;
          if (time > overtime && con != null) {
            releaseconnectionPool.remove(con);
            connectionPool.put(con, new Integer(0));
            overtimecon = true;
          }
        }
        con = null;
        if (overtimecon) {
          con = requestCon();
        }
        else {
          System.err.println("No connection available!");
          Exception e = new Exception("No connection available!");
          throw e;
        }
      }
      else {
        int iTotal = currCon + incCon;
        iTotal = iTotal <= maxCon ? iTotal : maxCon;
        try {
          for (int i = currCon; i < iTotal; i++) {
            con = DriverManager.getConnection(url, user, pwd);
            connectionPool.put(con, new Integer(0));
            currCon++;
            System.out.println("Create connection " + i + " :" + con);
            member++;
            if (member == 10) {
              break;
            }          }
          //递归调用自己,尝试再次获取可用连接
        }
        catch (Exception e) {
            ErrorLog.writeLog(e);
          System.err.println(
              "connectionMgr.requestCon():failed to create connection " +
              (currCon + 1));
        }
        finally {
          //con = requestCon();        }
      }
    }
    return con;
  }/////
  public synchronized void releaseCon(Connection con) {
    try {
      if (con != null) {
        if (con.isClosed()) {
          currCon--;
          releaseconnectionPool.remove(con);
        }
        else {
          releaseconnectionPool.remove(con);
          connectionPool.put(con, new Integer(0));
        }
      }
    }
    catch (Exception e) {ErrorLog.writeLog(e);}
    finally {
      System.out.println("releaseCon:" + con);
    }
  }  public void closeConnections() throws Exception {
    System.out.println("closing connection......");
    Enumeration[] Connections = {
        connectionPool.keys(), releaseconnectionPool.keys()};
    for (int i = 0; i < Connections.length; i++) {
      while (Connections[i].hasMoreElements()) {
        Connection con = (Connection) Connections[i].nextElement();
        con.close();
      }
    }
    currCon = 0;
    connectionPool.clear();
    releaseconnectionPool.clear();
  }    private void jbInit() throws Exception {
    }
}package jserver;import java.sql.*;
//import java.io.*;
//import oracle.sql.*;
//import oracle.jdbc.driver.*;
import jserver.tools.*;public class DBConnection {//连接调用
  final String DbServer = "192.192.192.162"; //数据库服务器IP地址
  final String SPort = "1521"; //数据库服务器端口
  final String SID = "test"; //数据库服务器server ID
  final String UserId = "shp"; //数据库用户名
  final String Password = "shp"; //用户密码
  final String Password =FileConf.DBPass;
  final String sDBDriver = "oracle.jdbc.driver.OracleDriver";
  String sConnStr = "jdbc:oracle:thin:@" + DbServer + ":"+SPort+":" + SID;
  public static ConnectionMgr dbconnectionMgr = null;
  Connection conn = null;
  Statement stmt = null;
  CallableStatement stmtproc=null;
  ResultSet rs = null;
  int initCon = 6; //the connection number ,init when application start
  int maxCon = 40; //the max connection number
  int incCon = 6; //the connection incteasing number
  boolean autoCommit = true;
  public DBConnection() {
    if (dbconnectionMgr == null) {
      dbconnectionMgr = new ConnectionMgr(sDBDriver, sConnStr, UserId, Password,
                                          initCon, maxCon, incCon);
    }
  }  public void setAutoCommit(boolean autoCommit) throws Exception {
    if (conn == null) {
      conn = dbconnectionMgr.requestCon();
    }
    conn.setAutoCommit(autoCommit);
    this.autoCommit = autoCommit;
  }  public void commit() throws Exception {
    if (conn != null) {
      conn.commit();
    }
  }  public void rollback() throws Exception {
    if (conn != null) {
      conn.rollback();
    }
  }
  public CallableStatement excuteProcedures(String proc) throws Exception{
      stmtproc=null;
      int intP=0;
      try{
          if(stmt!=null){
              stmt.close();
              stmt=null;
          }
          if(conn==null){
              if(!this.autoCommit){
                  Exception ep=new Exception("Connection Error!");
                  throw ep;
              }else{
                  conn=dbconnectionMgr.requestCon();
              }
          }
          stmtproc=conn.prepareCall(proc);
      }catch(Exception e){ErrorLog.writeLog(e);
          e.printStackTrace();
      }
      return stmtproc;
}    public Connection getConnection() throws Exception {
    if (conn == null) {
      conn = dbconnectionMgr.requestCon();
    }
    if (!this.autoCommit) {
      conn.setAutoCommit(autoCommit);
    }
    return conn;
  }  public void close() throws Exception {
    try {
      if (rs != null) {
          rs.close();
          rs = null;
        }
       if (stmt != null) {
        stmt.close();
        stmt = null;
      }
      if (conn != null) {
        if (!this.autoCommit) {
          conn.setAutoCommit(autoCommit);
          this.autoCommit = true;
        }
        dbconnectionMgr.releaseCon(conn);
        conn = null;
      }
    }
    catch (SQLException e) {ErrorLog.writeLog(e);
      //System.err.println("DBConnection.close():" + e.getMessage());
      throw e;
    }
  }
}

解决方案 »

  1.   

    import java.sql.*;
        1.参数化
            String driverName = "com.mysql.jdbc.Driver";
            String url = "jdbc:mysql://localhost:3306/test"; //协议;库或服务器名称;服务器IP,端口
            String username = "root";
            String password="";
                /* Oracle的连接
                String driverName = "oracle.jdbc.driver.OracleDriver";
                String url = "jdbc:oracle:thin:@192.168.0.23:1521:ora10g"; 
                String username = "openlab";
                String password="open123";*/            /* SQL Server的连接
                String driverName = "com.microsoft.jdbc.SQL Server.SQL ServerDriver";
                String url = "jdbc:microsoft:SQL Server://localhost:1433:DatabaseName=test"; 
                String username = "openlab";
                String password="open123";*/
            //以下这些都需要写在有异常的代码块里,所以需要提取出来。
            Connection conn = null;
            Statement stmt = null;
            ResultSet rs = null;//建议用PreparedStatement
        2.加载和注册数据库驱动
            Class.forName(driverName);//自动注册;需要把驱动的jar包导进来;需处理异常
                /*方法二:实例化具体的Driver驱动,这写法一般不用(不能参数化驱动名,不够灵活)
                Driver driver = new com.mysql.jdbc.Driver();
                DriverManager.registerDriver(driver); //将驱动交于DriverManager托管*/
                /*方法三:Dos运行时,java -Djdbc.drives = oracle.jdbc.driver.OracleDriver; --可多个 */
        3.连接数据库
            conn = DriverManager.getConnection(url, username, password);//需处理异常
            //Connection返回数据库连接,如:“com.mysql.jdbc.Connection@1ffb8dc”;连接不成功则返回 null
        4.创建Statement对象 //为了类型安全和批量更新的效率,改用PreparedStatement
            stmt = conn.createStatement();//需处理异常
            //返回其生成结果的对象"oracle.jdbc.driver.OracleStatement@198dfaf"
        5.操作数据库,执行SQL语句
            String sql = "select * from tableName";//SQL语句里不需要写分号
            rs = stmt.executeQuery(sql); //executeQuery(sqlString) 查询 返回查询结果集
                /* String sql = "insert into tableName values(?,?)"; // ?占位符
                int number = stmt.executeUpdate(sql);//更新,再返回int(更新、修改影响的条数) */
        6.处理数据(游标) 
            StringBuffer sb = new StringBuffer(); //缓存;用它可提高读取速度。当然,不用也可以。
            ResultSetMetaData md = rs.getMetaData(); //ResultSetMetaData可获取列的类型和属性信息
            int col = md.getColumnCount(); //获取列的数目
            while(rs.next()){ //rs.next()使游标下移一位,返回boolean,没有下一个结果则返回false
                for(int i=1; i<=col;i++){ // index(JDBC 的下标从1开始)  
                    sb.append(md.getColumnName(i)+"="+rs.getString(i)+"  ");
                } sb.append("\n");
            }System.out.println(sb);
                //1.游标的初始位置在第一条记录的前面,使第一次调用next()后,刚好拿到第一个结果。
                //2.游标的最终位置在最后一条记录的后面(结果集的前面和后面留空,真正存在) 
        7.释放资源,断开与数据库的连接
            //先判断是否有引用资源,再释放(释放空资源会抛异常);注意顺序
            if(rs!=null)try{rs.close();}catch(Exception e){e.printStackTrace();}
            if(stmt!=null)try{stmt.close();}catch(Exception e){e.printStackTrace();}
            if(conn!=null)try{conn.close();}catch(Exception e){e.printStackTrace();}
            //这些异常没法处理,处理只为方便调试。所以这些异常处理也只是打印。
            /*要按先ResultSet结果集,后Statement,最后Connection的顺序关闭资源,
            因为ResultSet需要Statement和Connection连接时才可以用的;Statement也需要Connection才可用;
            结束Statement之后有可能其它的Statement还需要连接,因此不能先关闭Connection。ResultSet同理。*/    步骤 2、3、7 每次都一样,可以重构。
           因为加载驱动是个一次性工作,所以可以采用静态初始化块来加载驱动;
           连接数据库的方法应该自己负责,获取数据库连接信息和驱动的信息,并处理相关异常;
           释放数据库资源的方法要考虑到ResultSet、Statement、Connection的不同情况,并处理相关异常。
    -------------------------------------
    上班中,没时间帮LZ分析,自己看看代码,别搞错就行
    同事分享下我以前做的一个例子。。
      

  2.   

    connectionPool.put(con, new Integer(0)); 
    这句应该反0改为i以在循环中不改为0将只创建最后一个Connection.
    还有connectionPool.remove(con); 当向连接池取时直接remove掉。但在关闭时没有还回来。
      

  3.   

    个人认为最好用现成的连接池库,比如OraclePooledConnection
    OracleConnectionPoolDataSource ocpds = new OracleConnectionPoolDataSource();ocpds.setDriverType("oci");
    ocpds.setServerName("dlsun999");
    ocpds.setNetworkProtocol("tcp");
    ocpds.setDatabaseName("816");
    ocpds.setPortNumber(1521);
    ocpds.setUser("scott"); 
    ocpds.setPassword("tiger");PooledConnection pc = ocpds.getPooledConnection();Connection conn = pc.getConnection();
      

  4.   

    网络中断了,oracle重新启动下。
      

  5.   

    二楼说的对,是这种情况,我现在没再研究这个代码,想试用下三楼说的那个jdbc的