2013-05-21 139 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

相关问题