因为数据库访问本质上是异步的,所以您肯定希望在后台检索行以避免阻塞事件派发线程 ; SwingWorker
使这相对容易.取在执行行doInBackground()
,publish()
中期业绩,并在你的实现添加到表模型process()
.此处显示了一个完整的示例,概述了随之而来的好处.该示例循环遍历文件,但您可以替换您的ResultSet
操作.
while (rs.next()) { //collect row data publish(rowData); }
请tableData.add()
按照您的实施process()
.
以下完整示例着重于自定义TableModel
及其包含的交互SwingWorker
,创建一个包含行的测试数据库,并显示该表的查询结果.特别是,N
JTable
JDBCModel
延伸AbstractTableModel
.为简单起见,模型data
存储在a中List
,并ResultSetMetaData
用于列名.作为一个更抽象的替代方案,请参阅Apache Commons DbUtils
,它使用类文字作为运行时类型标记并ResultSetMetaData
安全地创建行数据的实例.
JDBCModel
将行检索委托给私人JDBCWorker
; 它publish()
在从中检索的每一行上调用ResultSet
; 因为process()
在EDT上运行,工作人员可以优化代表父模型使用的表模型事件的数量fireTableRowsInserted()
.
同样,你的实现delete()
应该驻留在JDBCModel
GUI 中,而不是GUI; 它应该fireTableRowsDeleted()
在从数据库成功删除行并从中删除之后data
.
添加Thread.sleep()
到worker的后台循环以查看人为增加延迟的效果.
使用setProgress()
和PropertyChangeListener
所示,在这里,以显示进度; 一个JOptionPane
时done()
可能是多余的.
覆盖getPreferredScrollableViewportSize()
以自定义表格封闭的大小JScrollPane
.
避免使用例如TableModel
与常见API名称冲突的类名.
此处检查在视图中实现实时过滤的变体.
import java.awt.Dimension; import java.awt.EventQueue; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingWorker; import javax.swing.table.AbstractTableModel; /** * @see /sf/ask/17360801/ * @see /sf/ask/17360801/ */ public class WorkerTest { private static final int N = 1_000; private static final String URL = "jdbc:h2:mem:test"; private static final Random r = new Random(); private void display() { JFrame f = new JFrame("WorkerTest"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); createTestDatabase(N); JDBCModel model = new JDBCModel(getConnection(), "select * from city"); f.add(new JScrollPane(new JTable(model) { @Override public Dimension getPreferredScrollableViewportSize() { return new Dimension(320, 240); } })); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } private static class Row { int ID; String name; } private static class JDBCModel extends AbstractTableModel { private final Listdata = new ArrayList<>(); private ResultSet rs = null; private ResultSetMetaData meta; public JDBCModel(Connection conn, String query) { try { Statement s = conn.createStatement(); rs = s.executeQuery(query); meta = rs.getMetaData(); JDBCWorker worker = new JDBCWorker(); worker.execute(); } catch (SQLException e) { e.printStackTrace(System.err); } } @Override public int getRowCount() { return data.size(); } @Override public int getColumnCount() { try { return meta.getColumnCount(); } catch (SQLException e) { e.printStackTrace(System.err); } return 0; } @Override public Object getValueAt(int rowIndex, int colIndex) { Row row = data.get(rowIndex); switch (colIndex) { case 0: return row.ID; case 1: return row.name; } return null; } @Override public String getColumnName(int colIndex) { try { return meta.getColumnName(colIndex + 1); } catch (SQLException e) { e.printStackTrace(System.err); } return null; } private class JDBCWorker extends SwingWorker
, Row> { @Override protected List
doInBackground() { try { while (rs.next()) { Row r = new Row(); r.ID = rs.getInt(1); r.name = rs.getString(2); publish(r); } } catch (SQLException e) { e.printStackTrace(System.err); } return data; } @Override protected void process(List
chunks) { int n = getRowCount(); for (Row row : chunks) { data.add(row); } fireTableRowsInserted(n, n + chunks.size()); } } } private static void createTestDatabase(int n) { Connection conn = getConnection(); try { Statement st = conn.createStatement(); st.execute("create table city(id integer, name varchar2)"); PreparedStatement ps = conn.prepareStatement( "insert into city values (?, ?)"); for (int i = 0; i < n; i++) { ps.setInt(1, i); ps.setString(2, (char) ('A' + r.nextInt(26)) + String.valueOf(r.nextInt(1_000_000))); ps.execute(); } } catch (SQLException ex) { ex.printStackTrace(System.err); } } private static Connection getConnection() { try { return DriverManager.getConnection(URL, "", ""); } catch (SQLException e) { e.printStackTrace(System.err); } return null; } public static void main(String[] args) { EventQueue.invokeLater(new WorkerTest()::display); } }