【问题标题】:How to fill data in a JTable with database?如何用数据库填充 JTable 中的数据?
【发布时间】:2011-01-12 15:51:44
【问题描述】:

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

到目前为止,我一直使用 JTable 来显示来自 Object [ ][ ] 的数据。

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

【问题讨论】:

    标签: java swing jtable


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      用 ResultSet 填充 jTable 的最佳方法

      先决条件

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

      【讨论】:

        【解决方案3】:

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

        1. 查询 ---> 数据库数据 ---> 行集
        2. RowSet TableModel 适配器 JTable

        George Reese 的这个book 为他的班级RowSetModel 提供the source code,以将RowSet 改编为TableModel。开箱即用地为我工作。我唯一的改变是为这个类取了一个更好的名字:RowSetTableModel

        RowSet 是 ResultSet 的子接口,在 Java 1.4 中添加。所以一个 RowSet 一个 ResultSet。

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

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

        RowSet tutorial

        【讨论】:

          【解决方案4】:

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

          【讨论】:

          • 我知道这个答案很旧,但什么是模型?
          • model 是 TableModel 的对象
          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

              我建议采用以下方法:

              • 创建一个Row 类来表示从ResultSet 读取的行。这可以是 Object[] 的简单包装器。
              • 创建一个List&lt;Row&gt; 集合,并将AbstractTableModel 子类化以由该集合支持。
              • 使用SwingWorker 来填充您的List&lt;Row&gt;,方法是从后台线程(即在doInBackground() 方法中)上的底层ResultSet 读取。调用SwingWorkerpublish 方法将Rows 发布回事件调度线程(例如每100 行)。
              • 当调用SwingWorkerprocess 方法并读取最新的行块时,将它们添加到您的List&lt;Row&gt; 并触发适当的TableEvents 以更新显示。
              • 另外,使用ResultSetMetaData 确定TableModel 定义中每一列的Class。这将导致它们被正确渲染(如果您仅使用 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();
              

              【讨论】:

              • 我已经得到了你的答案,但我仍然有些困惑。可以用小代码sn-p指定。
              • 我已经提到我的问题作为对我的新问题的评论。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-03-03
              • 2014-09-23
              相关资源
              最近更新 更多