Java 如何使用数据库在JTable中填充数据?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2192764/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 04:36:16  来源:igfitidea点击:

How to fill data in a JTable with database?

javaswingjtable

提问by Yatendra Goel

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

我想显示一个 JTable,它按原样显示来自 DataBase 表的数据。

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

到目前为止,我一直使用 JTable 来显示来自 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 flexible.

我知道显示数据的一种方法是首先将数据库表转换为 Object [ ][ ] 但是有没有其他更简单但更强大和灵活的方法。

采纳答案by Adamski

I would recommend taking the following approach:

我建议采用以下方法:

  • Create a Rowclass to represent a row read from your ResultSet. This could be a simple wrapper around an Object[].
  • Create a List<Row>collection, and subclass AbstractTableModelto be backed by this collection.
  • Use a SwingWorkerto populate your List<Row>by reading from the underlying ResultSeton a background thread(i.e. within the doInBackground()method). Call SwingWorker's publishmethod to publish Rows back to the Event Dispatch thread (e.g. every 100 rows).
  • When the SwingWorker's processmethod 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 ResultSetMetaDatato determine the Classof each column within the TableModeldefinition. This will cause them to be rendered correctly (which won't be the case if you simply use a 2D Object[][]array).
  • 创建一个Row类来表示从您的ResultSet. 这可能是一个围绕Object[].
  • 创建一个List<Row>集合,以及AbstractTableModel由该集合支持的子类。
  • 使用 a通过从后台线程上的底层读取(即在方法内)SwingWorker来填充您List<Row>的。调用的方法将s发布回 Event Dispatch 线程(例如每 100 行)。ResultSetdoInBackground()SwingWorkerpublishRow
  • 当使用最新的 Rows 块调用SwingWorker'sprocess方法时,将它们添加到您的List<Row>并触发适当的TableEvents 以更新显示。
  • 此外,使用ResultSetMetaData来确定定义Class中每一列的TableModel。这将导致它们被正确渲染(如果您只是使用 2DObject[][]数组,则不会出现这种情况)。

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.

这种方法的优点是 UI 在处理大ResultSets时不会锁定,并且显示会随着结果的处理而增量更新。

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

回答by Jon

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.

根据您已经完成的工作以及您愿意做的事情,我一直在非常成功地使用 Netbeans 及其对数据库驱动应用程序的 Beans Binding 支持。您将 JTable 绑定到数据库,它会自动构建 JPA 查询。

回答by OscarRyz

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

您必须创建一个自定义TableModel在那里您可以指定数据的来源和方式。

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

您确实必须首先完全了解JTable+ TableModel 的工作原理,然后按照之前发布的答案之一进行操作。

回答by Ram

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.

我给出了一个在 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); } }

回答by Basil Bourque

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 JTablewith TableModeladapter.

在 JTable 中显示数据库数据的另一种强大而灵活的方法是将查询的结果数据加载到CachedRowSet 中,然后使用TableModel适配器将其连接到JTable

  1. Query ---> Database data ---> RowSet
  2. RowSet <--> TableModel adapter <--> JTable
  1. 查询 ---> 数据库数据 ---> RowSet
  2. RowSet <--> TableModel 适配器 <--> JTable

This bookby George Reese gives the source codefor his class RowSetModelto adapt a RowSetas a TableModel. Worked for me out-of-the-box. My only change was a better name for the class: RowSetTableModel.

George Reese 的这本书给出他的类RowSetModel的源代码,用于将RowSet改编为 TableModel。为我开箱即用。我唯一的改变是为这个类了一个更好的名字:RowSetTableModel

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

RowSet 是 ResultSet 的子接口,是在 Java 1.4 中添加的。所以 RowSet一个 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.

CachedRowSet 实现会为您完成这项工作,而不是像本页上的其他答案中所讨论的那样,您创建一个 Row 类、一个 Row 对象列表和 ResultSetMetaData。

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

Sun/Oracle 提供了CachedRowSet的参考实现。其他供应商或 JDBC 驱动程序也可能提供实现。

RowSet tutorial

行集教程

回答by Yogesh

Best way to fill jTable with ResultSet

用 ResultSet 填充 jTable 的最佳方法

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

1) 结果集“rs”填充了您需要的数据。2) JTable "jTable1" 是事先创建的 3) Table Header 是事先实现的

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

回答by Yogesh

I know the question is old but for anyone following Adamski's solution, care should be taken while sharing the ResultSetand ResultSetMetadatabetween gui and SwingWorkerthreads. 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 SwingWorkerand have the getter functions (getColumnName etc.) to return the fields instead.

我知道这个问题很老,但是对于任何遵循 Adamski 解决方案的人来说,在 gui 和线程之间共享ResultSet和 时应该小心。在 SQLite 中使用这种方法时,我遇到了不一致的内部状态异常。解决方案是在执行之前将任何元数据加载到私有字段,并使用 getter 函数(getColumnName 等)来返回字段。ResultSetMetadataSwingWorkerSwingWorker