2015-04-28 56 views
1

我是使用NetBeans的Java初學者,我試圖創建類似於教員註冊系統的東西。我使用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(); 

} 

,但我得到的是說,當我嘗試調用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()); 
    } 

}         

有人請幫助的結果集被關閉SQLException

+1

將'e.printStackTrace()'添加到您的'catch'並將堆棧跟蹤添加到您的問題中。 – RealSkeptic

回答

6

您正在重新使用相同的Statement對象來執行兩個查詢。當使用stmt執行第二個查詢時,前一個語句返回的ResultSet對象關閉。爲每個查詢創建兩個對象。

實施例:

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解釋:

默認情況下,每Statement只有一個ResultSet對象的對象可以是在同一時間打開。因此,如果一個ResultSet對象的讀數與另一個對象的讀數交錯,則每個對象必須由不同的Statement對象生成。 Statement接口中的所有執行方法隱式關閉一個陳述的當前對象(如果存在一個開放對象的話)ResultSet

還強烈建議以關閉JDBC資源,其分配相反的順序,IEG應關閉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,您可以使用try-與資源語句自動關閉這些資源(而無需顯式調用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塊中引發異常,則連接可能會未關閉)。 –

+1

建議使用'PreparedStatement',這樣OP就不會遇到像''這樣的課程代碼; DROP TABLE學生; --' :) –

+0

感謝一百萬人。嘗試與資源完美地工作:D – Kenchi