2013-06-28 2 views
2

У меня возникла эта странная ошибка в первый раз в моей жизни, и я не знаю, что это значит. У меня есть класс, который получает информацию из таблицы в базе данных PostgreSQL, сделать некоторые операции и возвращают ArrayList с разобранным элементом:PSQLException: этот ResultSet закрыт

ResultSet rs = ProduttoreDCS.getProduttori(); 
     System.out.println("Recuperato result set produttori"); 
     ArrayList<String[]> res = new ArrayList<String[]>(); 


     while (rs.next()) { 
      String[] current = new String[6]; 

      current[0] = Integer.toString(rs.getInt("partita_iva")); 
      current[1] = rs.getString("nome"); 
      current[2] = rs.getString("cognome"); 
      current[3] = rs.getString("via_sede"); 
      current[4] = rs.getString("citta_sede"); 
      current[5] = rs.getString("provincia_sede"); 

      res.add(current); 
      current = null; 
     } 

     return res; 

ошибка на «а» линии.

public static ResultSet getProduttori() throws ClassNotFoundException, SQLException { 
    /* 
    * retrieve all record from produttori table 
    */ 
    Connection conn = null; 
    ResultSet res = null; 
    Statement stmt = null; 
    String query = "SELECT * FROM produttore"; 

    conn = ConnectionManager.getConnection(); 
    System.out.println("Connection obtained by ProduttoreDCS class"); 
    stmt = conn.createStatement(); 
    res = stmt.executeQuery(query); 

    stmt.close(); 
    conn.close(); 


    return res; 
} 
+0

показать нам getProduttori() method – PermGenError

+0

Что делает 'getProduttori', точно? Если он пытается повторно использовать один и тот же объект ResultSet несколько раз, это может быть легко проблемой. (Нет причин устанавливать 'current' на' null'.) –

+0

@ jon skeet я знаю, просто удалите его! EDITED main post – giozh

ответ

3

при закрытии объекта соединения в методе getProduttori, ваш результирующий набор будет автоматически закрыт. когда вы пытаетесь его использовать, он будет равен нулю.

ResultSet rs = ProduttoreDCS.getProduttori(); 
      = null, as you have closed the connection in getProduttori 
       method, which will automatically close the resultset 
       thus, it returns null. 

От Connection#close

Релизы базы данных и JDBC этого объекта Connection в ресурсы сразу, а не ждать их, чтобы быть автоматически.

применяется при закрытии заявления также. Для того, чтобы ваш код работал, не закрывайте Statement и Connection, пока вы не получите строки.

@Baadshah уже показал вам стандартный способ. Если вы используете java 7+, вы можете использовать блок try-with-resource, который упростит вашу жизнь.

try(Connection conn = gettheconn){ 
    get the statement here 
    get the result set 
     perform your ops 
} 
catch(SQLException ex){ 
    ex.printstacktrace(); 
    } 

Если вы заметили, нет никакого окончательно блокировать ваш объект соединение будет закрыто после выхода из блока TRY automatically.you не должны в явной форме вызова Подключение # закрытия()

+0

, поэтому мне просто нужно перенести первую часть кода внутри метода getProduttori и вернуть ArrayList методу вызывающего? – giozh

+0

yepp, это действительно стандартный способ сделать это – PermGenError

+1

+1 для блока try-with-resource :) вы разбудили меня –

3

As per Docs

объект ResultSet автоматически закрывается, когда себе объект, который генерируется его закрыто, повторно выполняется, или используется для получения следующего результата из последовательности нескольких результатов.

Вы закрываете соединение, а затем выполняете итерацию, где оно равно null. Пожалуйста, прочитайте данные, а затем закройте соединение.

Хорошая практика здесь

Connection conn = null; 
PreparedStatement stmt = null; 
ResultSet rs = null; 
try { 
    conn = 
    stmt = conn.prepareStatement("sql"); 
    rs = stmt.executeQuery(); 
    //DO SOME THING HERE 
} catch { 
    // Error Handling 
} finally { 
    try { if (rs != null) rs.close(); } catch (Exception e) {}; 
    try { if (stmt != null) stmt.close(); } catch (Exception e) {}; 
    try { if (conn != null) conn.close(); } catch (Exception e) {}; 
} 
+1

i сердце 'попробуйте с ресурсом' из java 7 :) – PermGenError

+1

@PermGenError да да .. это существующий код :) Haaav .. переместить java 7: P –

1

Закрытие соединения делает Resultset уйти.

ResultSet - это не контейнер, в котором вы можете использовать данные для передачи данных, это всего лишь обертка вокруг курсора. Вы должны запустить содержимое resultSet и скопировать их в структуру данных, а затем вернуть структуру данных. Вы уже это делаете, но вам нужно сделать это, прежде чем закрывать оператор и соединение.

Изменить код:

public static List<String[]> getProduttori() throws ClassNotFoundException, SQLException { 

    ArrayList<String[]> res = new ArrayList<String[]>(); 
    /* 
    * retrieve all record from produttori table 
    */ 
    Connection conn = null; 
    ResultSet rs = null; 
    Statement stmt = null; 
    String query = "SELECT * FROM produttore"; 

    conn = ConnectionManager.getConnection(); 
    try { 
     System.out.println("Connection obtained by ProduttoreDCS class"); 
     stmt = conn.createStatement(); 
     try { 
      rs = stmt.executeQuery(query); 
      while (rs.next()) { 
       String[] current = new String[6]; 
       current[0] = Integer.toString(rs.getInt("partita_iva")); 
       current[1] = rs.getString("nome"); 
       current[2] = rs.getString("cognome"); 
       current[3] = rs.getString("via_sede"); 
       current[4] = rs.getString("citta_sede"); 
       current[5] = rs.getString("provincia_sede"); 
       res.add(current); 
      }   
      return res; 
     } finally { 
      try { 
       stmt.close(); 
      } catch (SQLException e) { 
       log.error(e); 
      } 
     } 
    } finally { 
     try { 
     conn.close(); 
     } catch (SQLException e) { 
      log.error(e); 
     } 
    }   
} 
+0

Проблема в том, что если вы хотите отвлечься база данных вызывает отдельный класс, с этим методом становится сложно, потому что здесь вы смешиваете данные класса с методами подключения к базе данных. – JohnMerlino

+0

@John: Согласен, я бы предпочел использовать пружину здесь с spring-jdbc, поддерживая соединение-приобретать полностью отдельно. мне просто не казалось, что это часть вопроса. –

3

Это проблема:

stmt.close(); 
conn.close(); 

Вы закрыть соединение с базой данных. Вы не можете этого сделать, пока не прочитаете данные - иначе как будет выглядеть сообщение ResultSet? Возможно, он будет читать некоторые данные для начала, но это не значит, что это отключенный объект.

В частности, из docuemntation для ResultSet.close:

Примечания: Объект ResultSet автоматически закрываются Statement объект, который генерируется, когда что заявление объект закрыт, повторно выполняется, или используется для извлечения следующий результат из последовательности нескольких результатов.