开发者

How to fill data in a JTable with database?

I want to display a JTable that display the data from a DataBase table as it is.

Up till now, I have used JTable that displays data from Object [ ][ ].

I know one way to display the data is to first convert the database table into Object [ ][ ] but Is there any other which is easy yet more powerful and fl开发者_开发知识库exible.


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();


Another powerful and flexible way to display database data in a JTable is to load your query's resulting data into a CachedRowSet, then connect it to the JTable with TableModel adapter.

  1. Query ---> Database data ---> RowSet
  2. RowSet <--> TableModel adapter <--> JTable

This book by George Reese gives the source code for his class RowSetModel to adapt a RowSet as a TableModel. Worked for me out-of-the-box. My only change was a better name for the class: RowSetTableModel.

A RowSet is a subinterface of ResultSet, added in Java 1.4. So a RowSet is a ResultSet.

A CachedRowSet implementation does the work for you, instead of you creating a Row class, a List of Row objects, and ResultSetMetaData as discussed in other answers on this page.

Sun/Oracle provides a reference implementation of CachedRowSet. Other vendors or JDBC drivers may provide implementations as well.

RowSet tutorial


Depending on what you've done already and what you're willing to do, I've been using Netbeans with its Beans Binding support for a database-driven app very successfully. You bind your JTable to a database and it automatically builds the JPA queries.


Best way to fill jTable with ResultSet

Prerequisites

1) Result Set "rs" is populated with data you need. 2) JTable "jTable1" is created before hand 3) Table Header is implemented before hand

Implementation

        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);
        }


You have to create a custom TableModel There you can specify where and how the data is coming from.

You really have to fully understand first how JTable + TableModel works and then follow one of the previously posted answers.


I know the question is old but for anyone following Adamski's solution, care should be taken while sharing the ResultSet and ResultSetMetadata between gui and SwingWorker threads. I got an inconsistent internal state exception while using this approach with SQLite. The solution is to load any metadata to private fields before executing the SwingWorker and have the getter functions (getColumnName etc.) to return the fields instead.


I am giving a small method for display database table data in JTable. You need to pass only the resultset of the database table as parameter.


    // 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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜