Java - 连接关闭后无法使用ResultSet

mlo*_*kal 8 java sql jdbc

关闭与MySQL的连接时遇到问题.

我收到错误:

java.sql.SQLException:ResultSet关闭后不允许操作

我的代码:

public static ResultSet sqlquery (String query)
{
 ResultSet rs=null;
 Connection connection=null;
 Statement st=null;
 try{   
     Class.forName("com.mysql.jdbc.Driver");
     connection = DriverManager.getConnection("databaseadress","username","password");
     st = connection.createStatement();  
     rs = st.executeQuery(query);

    }catch(SQLException e){System.out.println("SQL error: " + e);}
      catch(Exception e){System.out.println("Error: " + e);}
       finally {
       try{
          if(rs != null) rs.close();
          if(st!= null) st.close();
          if(connection != null)  connection.close();
  }catch(SQLException e){System.out.println("SQL error : " + e);}

    }
     return rs;
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*hes 11

JDBC不会在ResultSet中带回查询的所有结果,因为可能有太多的查询会急切地获取它们.相反,它会为您提供可用于检索结果的内容,但在连接关闭时会消失.因此,在关闭数据库连接后从方法中将其传回时,没有其他任何东西可以使用它.

您可以做的是让此方法使用resultSet填充对象或对象集合,并将该填充的对象传回.

如果您更改代码以传入rowMapper(它接受一个resultSet并传回一个填充了结果集中当前行的对象),并使用它来填充您传回的容器对象,那么您将拥有一些内容可以重复使用你所写的内容,但实际上是可行的,因为它不依赖于在调用完成后保持连接打开.

这是你的示例代码重写使用rowmapper,摆脱一些不必要的异常捕获,并修复一个错误,以防止连接在某些情况下被关闭:

public static List<T> sqlquery (String query, RowMapper<T> rowMapper) throws SQLException
{
    Connection connection=null;
    Statement st=null;
    ResultSet rs=null;
    // don't need Class.forName anymore with type4 driver     
    connection = DriverManager.getConnection("databaseadress","username","password");
    st = connection.createStatement();  
    rs = st.executeQuery(query);
    List<T> list = new ArrayList<T>();
    while (rs.next()) {
        list.add(rowMapper.mapRow(rs));
    }
    // don't let exception thrown on close of
    // statement or resultset prevent the
    // connection from getting closed
    if(rs != null) 
        try {rs.close()} catch (SQLException e){log.info(e);}
    if(st!= null) 
        try {st.close()} catch (SQLException e){log.info(e);}
    if(connection != null)  
        try {connection.close()} catch (SQLException e){log.info(e);}
    return list;
}
Run Code Online (Sandbox Code Playgroud)

如果没有单独关闭抛出的每个异常,如上所示,如果语句或resultSet在关闭时抛出异常,则可能无法关闭连接.

这类似于spring-jdbc所做的,它将RowMapper定义为:

public interface RowMapper<T> {
    T mapRow(ResultSet, int rowNum) throws SQLException;
}
Run Code Online (Sandbox Code Playgroud)

下一步是参数化您的查询,这样您就不必在引号中包围参数值或担心sql注入.有关spring-jdbc如何处理此问题的示例,请参阅此答案.这里的长期答案是,最好采用spring-jdbc或类似的东西,而不是零碎地重新发明它.


Jim*_*son 10

这是JDBC的工作方式.在你的代码关闭了ResultSetConnection,之后ResultSet不再可用.如果你想让它可用,你必须让它(和Connection)打开.

但是,如果你返回ResultSet,你应该重构你的代码,以便调用方法提供Connection.