2013-05-21 91 views
0

我試圖使用SQLServer的與MS驅動3.0一個結果填充一個JTable。SQLServerException:結果集被關閉

表將只要我不關閉ResultSet,陳述或連接生成。如果我關閉它們,然後我的表來回復與消息:

com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed. 

我試圖創建一個使用「如何使用表」教程我的TableModel。

這裏是我的表型號:

TableModel model = new AbstractTableModel() { 
       private String[] columnName = {"Employee ID", "Job Start", "Job ID",  "Oper. ID", "Indir. ID"}; 

      public int getColumnCount() { 
       return columns; 
      } 

      public int getRowCount() { 
       return rows; 
      } 

      public Object getValueAt(int row, int col) { 
       try { 
        rs.absolute(row+1); 
        return rs.getObject(col+1); 
       } catch (SQLException ex) { 
        System.err.println(ex); 
       } 
       return null; 

      } 
      public String getColumnName(int col) { 
       return columnName[col]; 
      } 
     }; 

我的連接與資源塊試試最初完成,但在試圖找到我把它變成一個問題的try-catch-終於與RS塊.close(),stmt.close()和connection.close()。正如我上面提到的,如果我沒有close語句,它會工作正常,但如果我有它們,那麼它表明結果集在我的表模型中到達getValueAt方法的時候已關閉。

我的整個代碼是在這裏:

package dashboard; 

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.ResultSet; 
import java.sql.ResultSetMetaData; 
import java.sql.SQLException; 
import java.sql.Statement; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.event.TableModelListener; 
import javax.swing.table.AbstractTableModel; 
import javax.swing.table.TableModel; 
import org.omg.CORBA.DATA_CONVERSION; 


public class Dashboard extends JFrame { 



     ResultSet rs; 
     Connection connection; 
    Statement stmt; 
    ResultSetMetaData md; 
    JScrollPane scrollpane; 
    int columns, rows; 
    JFrame frame; 
    String connectionUrl; 

    @SuppressWarnings("empty-statement") 
    public Dashboard() throws SQLException { 


     try { 
      connection = DriverManager.getConnection(connectionUrl); 
      stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); 
      rs = stmt.executeQuery(query); 

      ResultSetMetaData md = rs.getMetaData(); 

      //Count number of rows 
      rs.last(); 
      rows = rs.getRow(); 
      rs.first(); 

      //Get column Count 
      columns = md.getColumnCount(); 



      TableModel model = new AbstractTableModel() { 
       private String[] columnName = {"Employee ID", "Job Start", "Job ID", "Oper. ID", "Indir. ID"}; 

       public int getColumnCount() { 
        return columns; 
       } 

       public int getRowCount() { 
        return rows; 
       } 

       public Object getValueAt(int row, int col) { 
        try { 
         rs.absolute(row+1); 
         return rs.getObject(col+1); 
        } catch (SQLException ex) { 
         System.err.println(ex); 
        } 
        return null; 

       } 
       public String getColumnName(int col) { 
        return columnName[col]; 
       } 
      }; 


      JTable table = new JTable(model); 
      table.setAutoCreateRowSorter(true); 

      scrollpane = new JScrollPane(table); 
      getContentPane().add(scrollpane); 

      frame = new JFrame(); 
      frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
      frame.pack(); 
      frame.setTitle("Employee Dashboard"); 
      frame.setBounds(300, 300, 1300, 750); 
      frame.setResizable(false); 
      frame.add(scrollpane); 
      frame.setVisible(true); 
     } catch (SQLException ex) { 
      System.err.println(ex); 
     } finally { 
      rs.close(); 
      stmt.close(); 
      connection.close(); 
     } 

    } 

    public static void main(String[] args) throws InterruptedException, SQLException { 

     Dashboard me = new Dashboard(); 

    } 
} 

更新13年6月4日

最後我折騰出來的一切和所依據的@Reimeus說從頭開始。我不積極,但我認爲這是行得通的。當我輸出model.getRowCount()時,它告訴我它與我的查詢具有相同的行。代碼在這裏:

DefaultTableModel model = new DefaultTableModel(); 

     ResultSetMetaData meta = rs.getMetaData(); 
     int numberOfColumns = meta.getColumnCount(); 
     while (rs.next()) { 
      Object[] rowData = new Object[numberOfColumns]; 
      for (int i = 0; i < rowData.length; ++i) { 
       rowData[i] = rs.getObject(i + 1); 

      } 
      model.addRow(rowData); 
      System.out.println(model.getColumnName(1)); 

     } 

我現在遇到的問題是我無法使用表模型生成表。以下是我認爲會工作:

JTable table = new JTable(model); 
     table.setAutoCreateRowSorter(true); 

     scrollpane = new JScrollPane(table); 
     getContentPane().add(scrollpane); 

     frame = new JFrame(); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.add(scrollpane); 
     frame.setVisible(true); 

在我心中,我在想:

DB到RS RS表型號 以舊換新表 表到滾動窗格 的ScrollPane到JTable中

我確信這是一件愚蠢的事,但我仍然不夠認識它。

+3

這是預期行爲。什麼是問題? – Reimeus

+0

Jeez,我在這裏發帖非常緊張,實際上我忘了問任何問題。我的問題是,爲什麼我的結果集在我的getValueAt方法之前關閉?過去幾天我一直在看不同的例子,並一直試圖用這些例子來說明如何做我的。我使用矢量工作得很好,但後來我發現矢量已被棄用,現在我知道我的結果集包含數據,我只是想把它放到表中。在我看來這是有道理的,但我絕對是一個初學者,並且作爲最後的手段來到這裏。 – Prizz

回答

1

當調用TableModel#getValueAt時,ResultSet被關閉,因爲Swing使用事件模型從TableModel中檢索元素。這是異步發生的,即不在主UI線程上。不要保留數據庫資源,如StatementResultSet。這些會在數據庫本身上創建開銷。

更新TableModel基於JDBC查詢然後關閉相關的數據庫資源。不要使用ResultSet方法填充模型。

看一看Creating a Table Model。它顯示瞭如何使用固定後臺數據來保存TableModel的數據。或者可以使用ArrayList

如果你是新手,DefaultTableModel是易於使用,並且是可變的。之後你可以進步到從@mKorbel

管理模式的更新,如在此example旁白:使用PreparedStatement,而不是Statement,以防止SQL注入攻擊

+0

非常感謝您的回覆。 – Prizz

+0

我會研究PreparedStatements並確保我用它們來代替語句。 關於我的錯誤,你的解釋完全理解它爲什麼關閉。我現在明白了。謝謝。 您提到「基於JDBC查詢更新TableModel」。你偶然會對我在哪裏可以學到更多關於如何使用JDBC更新表模型的建議嗎?我想正確有效地做到這一點,很明顯,我目前使用的資源並沒有使我走上正確的道路。 – Prizz

+0

查看更新..... – Reimeus

相關問題