我正在尝试使用带有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
我确信我正在做的事情是愚蠢的,但我仍然没有足够的知识来认识它。
答案 0 :(得分:1)
当ResultSet
被调用时,TableModel#getValueAt
将关闭,因为Swing使用事件模型来从TableModel
中提取元素。这是异步发生的,即不在主UI线程上。不要让Statement
和ResultSet
等数据库资源保持打开状态。这些会在数据库本身产生开销。
根据JDBC查询更新TableModel
,然后关闭关联的数据库资源。不要使用ResultSet
方法填充模型。
看看Creating a Table Model。它显示了固定后备数据如何用于保存TableModel
的数据。或者,可以使用ArrayList
。
如果你刚开始,DefaultTableModel
很容易使用并且是可变的。稍后您可以继续管理模型的更新,例如来自@mKorbel的example
除此之外:使用PreparedStatement
而不是Statement
来防止SQL注入攻击