2015-04-28 54 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