SQLServerException:结果集已关闭

时间:2013-05-21 20:23:03

标签: java sql-server

我正在尝试使用带有MS Driver 3.0的SQLServer从resultSet填充jTable。

只要我不关闭结果集,语句或连接,就会生成表。如果我关闭它们,那么我的表会回复消息:

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];
            }
        };

我的连接最初是在资源块的尝试中完成的,但在尝试查找问题时,我将其放入带有rs.close(),stmt.close()和连接的try-catch-finally块中。关()。正如我上面提到的,如果我没有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();

    }
}

更新6-4-13

根据@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到表模型 TM到表 表到ScrollPane ScrollPane到Jtable

我确信我正在做的事情是愚蠢的,但我仍然没有足够的知识来认识它。

1 个答案:

答案 0 :(得分:1)

ResultSet被调用时,TableModel#getValueAt将关闭,因为Swing使用事件模型来从TableModel中提取元素。这是异步发生的,即不在主UI线程上。不要让StatementResultSet等数据库资源保持打开状态。这些会在数据库本身产生开销。

根据JDBC查询更新TableModel,然后关闭关联的数据库资源。不要使用ResultSet方法填充模型。

看看Creating a Table Model。它显示了固定后备数据如何用于保存TableModel的数据。或者,可以使用ArrayList

如果你刚开始,DefaultTableModel很容易使用并且是可变的。稍后您可以继续管理模型的更新,例如来自@mKorbel的example

除此之外:使用PreparedStatement而不是Statement来防止SQL注入攻击