2015-04-28 1 views
1

Я новичок в Java, используя NetBeans, и я пытался создать нечто похожее на систему регистрации преподавателей. Я использую SQL Server 2005 для создания БД. Во время реализации я пытался создать функцию, чтобы ученики могли регистрировать своих подданных, поэтому функция в основном ищет предметы, которые студент закончил свои предпосылки. Поэтому я написал следующий код:SQLException: результирующий набор закрыт

package GUIs; 
import java.sql.*; 
import javax.swing.*; 


public class AddSubToStd extends javax.swing.JFrame { 

final void FillList1(){ 
    try{ 
    String url = "jdbc:sqlserver://localhost:1433;databaseName=BIS"; 
    String username = "sa"; 
    String password = "*****"; 
    Connection conn = DriverManager.getConnection(url,username,password); 
    Statement stmt = conn.createStatement(); 
    DefaultListModel DLM = new DefaultListModel(); 
    ResultSet res = stmt.executeQuery("SELECT * FROM Students"); 
    while(res.next()){ 
     DLM.addElement(res.getString("ID")); 
    } 
    List1.setModel(DLM); 
} 
    catch(SQLException e){ 
     JOptionPane.showMessageDialog(null, e.toString()); 
    } 
} 

final void FillList2(){ 
    try{ 
    String url = "jdbc:sqlserver://localhost:1433;databaseName=BIS"; 
    String username = "sa"; 
    String password = "*****"; 
    Connection conn = DriverManager.getConnection(url,username,password); 
    Statement stmt = conn.createStatement(); 
    DefaultListModel DLM = new DefaultListModel(); 
    String Query = "SELECT * FROM FinishedCourses WHERE ID = '"+List1.getSelectedValue()+"'"; 
    ResultSet res = stmt.executeQuery(Query); 

    ResultSet res1; 
    String S_Code; 
    String Query1; 

    while(res.next()){ 

     S_Code = res.getString("S_Code"); 
     Query1 = "SELECT * From Subjects WHERE Prerequisite = '"+S_Code+"'"; 
     res1 = stmt.executeQuery(Query1); 

     while(res1.next()){ 

      DLM.addElement(res.getString("S_Code")); 
     } 

    } 
    conn.close(); 
    stmt.close(); 
    List2.setModel(DLM); 
} 
    catch(SQLException e){ 
     JOptionPane.showMessageDialog(null, e.toString()); 
    } 
} 

public AddSubToStd() { 
    initComponents(); 
    FillList1(); 

} 

но я получаю SQLException что говорит набор результатов закрыт, когда я пытаюсь вызвать FillList2()

private void UpdateAllowedActionPerformed(java.awt.event.ActionEvent evt) {            
    try{ 
    String url = "jdbc:sqlserver://localhost:1433;databaseName=BIS"; 
    String username = "sa"; 
    String password = "*****"; 
    Connection conn = DriverManager.getConnection(url,username,password); 
    FillList2();  
    } 
    catch(SQLException e){ 
     JOptionPane.showMessageDialog(null, e.toString()); 
    } 

}         

кто-то пожалуйста, помогите.

+1

Добавьте 'e.printStackTrace()' к вашему 'catch' и добавьте трассировку стека к вашему вопросу, пожалуйста. – RealSkeptic

ответ

6

Вы повторно используете тот же объект Statement для выполнения двух запросов. Когда stmt используется для выполнения второго запроса, объект, возвращенный предыдущим оператором, закрыт. Создайте два объекта для каждого запроса.

Пример:

Statement stmt = conn.createStatement(); 
Statement stmt1 = conn.createStatement(); 
... 
ResultSet res = stmt.executeQuery(Query); 

... 

while(res.next()){ 

    S_Code = res.getString("S_Code"); 
    Query1 = "SELECT * From Subjects WHERE Prerequisite = '"+S_Code+"'"; 
    res1 = stmt1.executeQuery(Query1); // use a separate statement 

    while(res1.next()){ 

     DLM.addElement(res.getString("S_Code")); 
    } 

} 

Это объясняется в следующей цитате из Statement API docs:

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

Также настоятельно рекомендуется закрыть JDBC ресурсы в обратном порядке их выделения, МРО следует закрыть Statement сек затем закройте Connection, и вы должны сделать это в finally блоке:

catch(SQLException e){ 
    JOptionPane.showMessageDialog(null, e.toString()); 
} finally { 
    if(res != null) { 
     res.close(); 
    } 
    if(res1 != null) { 
     res1.close(); 
    } 
    if(stmt != null) { 
     stmt.close(); 
    } 
    if(stmt1 != null) { 
     stmt1.close(); 
    } 
    if(conn != null) { 
     conn.close(); 
    } 
} 

Если вы используете Java 7, вы можете использовать примерочных с-ресурсов заявление автоматически закрыть эти ресурсы (без явного вызова метода close()):

// try-with-resources statement declaring two resources 
try(Connection conn = DriverManager.getConnection(url,username,password); 
    Statement stmt = conn.createStatement()) { 
    ... 
} catch(SQLException e){ 
    JOptionPane.showMessageDialog(null, e.toString()); 
} 

Попробуй-ресурсы обязательно закроют объект Statement, затем Connection после того, как они будут использованы.

+1

Для последней части вашего ответа лучше использовать try-with-resource: он гарантирует закрытие в правильном порядке, даже если есть исключения (например, если исключение выбрано в вашем примере finally block, то соединение может не закрываться). –

+1

Также рекомендуется использовать 'PreparedStatement', чтобы OP не попадал в проблемы с кодами курсов, такими как' '; DROP TABLE Студенты; - ':) –

+0

Спасибо, миллион парней. try-with-resources отлично работали: D – Kenchi