1

我正在尝试使用带有 MS Driver 3.0 的 SQLServer 从结果集中填充 jTable。

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

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

我尝试使用“如何使用表格”教程创建我的表格模型。

这是我的表模型:

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 with resources 块中完成的,但在尝试找到问题时,我将其放入带有 rs.close()、stmt.close() 和 connection.close() 的 try-catch-finally 块中. 正如我上面提到的,如果我没有关闭语句,它会正常工作,但如果我有它们,那么它表明结果集在它到达我的表模型中的 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();

    }
}

2013 年 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 to RS RS to Table Model TM to Table Table to ScrollPane ScrollPane to Jtable

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

4

1 回答 1

3

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

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

看看创建表模型。它显示了如何使用固定的支持数据来保存TableModel. 或者,ArrayList可以使用一个。

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

旁白:使用PreparedStatement而不是Statement防止 SQL 注入攻击

于 2013-05-21T20:55:02.930 回答