程序如果有几十个并发数的时候,会出现“java.sql.SQLException: 关闭的 Resultset: next”的异常。
这个异常一般会是因为在rs.next()之前就关闭了Statement对象才会有的。
但是,程序如果在单线程的情况下就没有此问题,不知道大家有什么解决的办法来避免这个问题,部分代码如下:                        //conn为Connection对象。在整个的程序中,是一个静态变量
                        stmt = conn.createStatement();

rsRow = stmt.executeQuery(strSQL); // 获取记录
while (rsRow.next()) { //程序在此处报错
    stateList.add(rsRow.getString("execute_state"));
}
rsRow.close();
stmt.close();
rsRow = null;
stmt = null;
异常信息:java.sql.SQLException: 关闭的 Resultset: next
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.OracleResultSetImpl.next(OracleResultSetImpl.java:175)
at weblogic.jdbc.wrapper.ResultSet_oracle_jdbc_driver_OracleResultSetImpl.next()Z(Unknown Source)
at com.ngoss.framework.db.impl.WorkorderDAOImpl.selectWorkOrder(WorkorderDAOImpl.java:347)
at com.ngoss.framework.impl.RequestManagerImpl.selectWorkOrder(RequestManagerImpl.java:110)

解决方案 »

  1.   

    你为什么在遍历结果集之前关闭Statement? 这些最好都放在finally中处理。
      

  2.   

    并发的程序,你还敢搞个静态的Connection?连接池是最好的选择
      

  3.   


    我没有在遍历之前关闭呀。
    是在遍历之后关闭的。放在finally里是可以,但是和这个效果一样,还是会报一样的错误
      

  4.   

    严禁将 Connection、Statement、ResultSet 等数据库连接对象作为共享变量!后果不用说了,楼主已经尝到了。解决方案:将共享的数据库连接对象全部改为局部变量。
      

  5.   

    严禁将 Connection、Statement、ResultSet 等数据库连接对象作为共享变量!这句话,我在 CSDN Java 版说过不下十次了,但是没有人理会,哎!JDBC 规范并未规定那三个对象必须是线程安全的,因此所有的 JDBC 厂商也不会去弄成线程安全的,正因为如此,所以就会有并发问题。如果你对 JDBC、多线程编程没有达到非常熟练的程度,还是老老实实地使用经典的 JDBC 代码结构。
      

  6.   

    普通应用程序根本没必要把那三个对象弄成是成员变量,更不可弄成静态的成员变量。只有在数据库连接池的实现中,会将这些对象置于成员变量中,但是连接池的实现者已经进行必要的同步处理,而且还经过严格的性能及压力测试。但我想不通的是,为什么就有那么多人不遵照普遍的 JDBC 代码,而是喜欢自作聪明呢?普通的 JDBC 代码结构是这样的:Connection con = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
        con = ConnectionFactory.getConnection();
        String sql = "xxxx";
        ps = con.preparedSatement(sql);
        ps.setXxxxx(1, xxx);
        rs = ps.executeQuery();
        while(rs.next()) {
            Xxxx xxx = rs.getXxxx();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        if (rs != null) try { rs.close(); } catch (SQLException e) { e.printStackTrace(); }
        if (ps != null) try { ps.close(); } catch (SQLException e) { e.printStackTrace(); }
        if (con != null) try { con.close(); } catch (SQLException e) { e.printStackTrace(); }
    }千万别在 JDBC 上自作聪明,在并发很高的情况下,可能会带来灾难性的后果。
      

  7.   

    首先,很感谢你的回复。现在已经代码改回每一次请求从数据库里重新拿Connection,但是遇到了,在高并发的时候,连接池里面的连接数会快速增加的情况。并且我通过在数据库端用SQL语句查询的时候,也发现连接数保持在很高的位置。
    我在申请连接与释放连接的地方也都做了同步的操作,并且在这个位置也加了一个记数器来测试,可以肯定是在申请后的连接均释放了。
    这种情况在单线程跑的时候,不会出现,查询连接数,很快会回到原始数量。所以,请问一下,连接池里面的连接数怎么样才能让他马上回恢到原始数量,因为在高并发的时候,很容易发现在连接池的连接数会大量的增加之后,再过来的请求就一直在排除等待拿Connection直至事务超时。