How to fill data in a JTable with database?

I would recommend taking the following approach:

  • Create a Row class to represent a row read from your ResultSet. This could be a simple wrapper around an Object[].
  • Create a List<Row> collection, and subclass AbstractTableModel to be backed by this collection.
  • Use a SwingWorker to populate your List<Row> by reading from the underlying ResultSet on a background thread (i.e. within the doInBackground() method). Call SwingWorker‘s publish method to publish Rows back to the Event Dispatch thread (e.g. every 100 rows).
  • When the SwingWorker‘s process method is called with the latest chunk of Rows read, add them to your List<Row> and fire appropriate TableEvents to cause the display to update.
  • Also, use the ResultSetMetaData to determine the Class of each column within the TableModel definition. This will cause them to be rendered correctly (which won’t be the case if you simply use a 2D Object[][] array).

The advantage of this approach is that the UI will not lock up when processing large ResultSets, and that the display will update incrementally as results are processed.

EDIT

Added example code below:

/**
 * Simple wrapper around Object[] representing a row from the ResultSet.
 */
private class Row {
  private final Object[] values;

  public Row(Object[] values) {
    this.values = values;
  }

  public int getSize() {
    return values.length;
  }

  public Object getValue(int i) {
    return values[i];
  }
}

// TableModel implementation that will be populated by SwingWorker.
public class ResultSetTableModel extends AbstractTableModel {
  private final ResultSetMetaData rsmd;
  private final List<Row> rows;

  public ResultSetTableModel(ResultSetMetaData rsmd) {
    this.rsmd = rsmd;
    this.rows = new ArrayList<Row>();
  }

  public int getRowCount() {
    return rows.size();
  }

  public int getColumnCount() {
    return rsmd.getColumnCount();
  }

  public Object getValue(int row, int column) {
    return rows.get(row).getValue(column);
  }

  public String getColumnName(int col) {
    return rsmd.getColumnName(col - 1); // ResultSetMetaData columns indexed from 1, not 0.
  }

  public Class<?> getColumnClass(int col) {
    // TODO: Convert SQL type (int) returned by ResultSetMetaData.getType(col) to Java Class.
  }
}

// SwingWorker implementation
new SwingWorker<Void, Row>() {
  public Void doInBackground() {
    // TODO: Process ResultSet and create Rows.  Call publish() for every N rows created.
  }

  protected void process(Row... chunks) {
    // TODO: Add to ResultSetTableModel List and fire TableEvent.
  }
}.execute();

Leave a Comment