web-dev-qa-db-ja.com

JTableのデータをデータベースで埋める方法は?

データベーステーブルのデータをそのまま表示するJTableを表示したい。

これまで、オブジェクト[] []からのデータを表示するJTableを使用してきました。

データを表示する1つの方法は、最初にデータベーステーブルをオブジェクト[] []に変換することですが、簡単でありながらより強力で柔軟な他の方法はありますか。

19
Yatendra Goel

私は次のアプローチを取ることをお勧めします:

  • Rowから読み取った行を表すResultSetクラスを作成します。これは、Object[]の単純なラッパーである可能性があります。
  • List<Row>コレクションを作成し、このコレクションを基にするAbstractTableModelをサブクラス化します。
  • SwingWorkerを使用して、バックグラウンドスレッド(つまり、doInBackground()メソッド内)で基になるResultSetから読み取ることにより、List<Row>を入力します。 SwingWorkerpublishメソッドを呼び出して、Rowsを発行し、イベントディスパッチスレッドに戻します(100行ごとなど)。
  • 読み取られた行の最新のチャンクでSwingWorkerprocessメソッドが呼び出されたら、それらをList<Row>に追加し、適切なTableEventsを起動して表示を更新します。
  • また、ResultSetMetaDataを使用して、Class定義内の各列のTableModelを判別します。これにより、それらが正しくレンダリングされます(2D Object[][]配列を使用するだけの場合は当てはまりません)。

このアプローチの利点は、大きなResultSetsを処理するときにUIがロックしないこと、および結果が処理されるときに表示が段階的に更新されることです。

[〜#〜]編集[〜#〜]

以下のサンプルコードを追加しました:

/**
 * 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();
24
Adamski

データベースデータをJTableに表示するもう1つの強力で柔軟な方法は、クエリの結果データを CachedRowSet にロードし、 JTableTableModel アダプタを使用して接続することです。 。

  1. クエリ--->データベースデータ---> RowSet
  2. RowSet <-> TableModelアダプタ<-> JTable

ジョージリースによるこの は、彼のクラスRowSetModelRowSet をTableModelとして適合させるために ソースコード を提供します。 the-box。私の唯一の変更は、クラスのより良い名前でした:RowSetTableModel

RowSetはResultSetのサブインターフェースであり、Java 1.4で追加されました。したがって、RowSet ResultSetです。

このページの他の回答で説明されているように、Rowクラス、Rowオブジェクトのリスト、およびResultSetMetaDataを作成する代わりに、CachedRowSet実装が機能します。

Sun/OracleはCachedRowSetの リファレンス実装 を提供しています。他のベンダーまたはJDBCドライバーも実装を提供している場合があります。

RowSetチュートリアル

7
Basil Bourque

すでに何をしていて、何をするつもりかにもよりますが、私はデータベース駆動型アプリのBeans Bindingサポートを備えたNetbeansを非常にうまく利用しています。 JTableをデータベースにバインドすると、自動的にJPAクエリが作成されます。

4
Jon

JTableをResultSetで埋める最良の方法

前提条件

1)結果セット「rs」には、必要なデータが入力されています。 2)JTable "jTable1"が事前に作成されている3)テーブルヘッダーが事前に実装されている

実装

        Java.sql.ResultSet rs = datacn.executeSelectQuery(query);
        //Filling JTable with Result set

        // Removing Previous Data
        while (jTable1.getRowCount() > 0) {
            ((DefaultTableModel) jTable1.getModel()).removeRow(0);
        }

        //Creating Object []rowData for jTable's Table Model        
        int columns = rs.getMetaData().getColumnCount();
        while (rs.next())
        {  
            Object[] row = new Object[columns];
            for (int i = 1; i <= columns; i++)
            {  
                row[i - 1] = rs.getObject(i); // 1
            }
            ((DefaultTableModel) jTable1.getModel()).insertRow(rs.getRow() - 1,row);
        }
4
Yogesh

カスタムを作成する必要があります TableModel ここで、データの取得元と方法を指定できます。

最初に JTable + TableModel がどのように機能するかを完全に理解してから、以前に投稿された回答の1つに従う必要があります。

3
OscarRyz

私は質問が古いことを知っていますが、Adamskiの解決策に従う誰にとっても、ResultSetResultSetMetadataをguiスレッドとSwingWorkerスレッドで共有する際には注意が必要です。 SQLiteでこのアプローチを使用しているときに、一貫性のない内部状態例外が発生しました。解決策は、SwingWorkerを実行する前にプライベートフィールドにメタデータをロードし、代わりにフィールドを返すゲッター関数(getColumnNameなど)を用意することです。

1
j_kar

JTableでデータベーステーブルデータを表示するための小さなメソッドを提供しています。データベーステーブルの結果セットのみをパラメーターとして渡す必要があります。


    // rs is the ResultSet of the Database table
    public void displayData(ResultSet rs)
    {
        //jt Represents JTable
        //jf represents JFrame
        int i;
        int count;
        String a[];
        String header[] = {"1","2","3","4","5"};   //Table Header Values, change, as your wish
        count = header.length;

//First set the Table header for(i = 0; i < count; i++) { model.addColumn(header[i]); } jt.setModel(model); //Represents table Model jf.add(jt.getTableHeader(),BorderLayout.NORTH); a = new String[count]; // Adding Database table Data in the JTable try { while (rs.next()) { for(i = 0; i < count; i++) { a[i] = rs.getString(i+1); } model.addRow(a); //Adding the row in table model jt.setModel(model); // set the model in jtable } } catch (Exception e) { JOptionPane.showMessageDialog(null, "Exception : "+e, "Error", JOptionPane.ERROR_MESSAGE); } }
0
Ram