web-dev-qa-db-fra.com

Comment remplir des données dans une table JTable avec une base de données?

Je veux afficher un JTable qui affiche les données d'une table DataBase en l'état.

Jusqu'à présent, j'ai utilisé JTable qui affiche les données de Object [] [].

Je sais qu’une façon d’afficher les données consiste à convertir d’abord la table de la base de données en Object [] [], mais existe-t-il une autre solution facile mais plus puissante et flexible? 

19
Yatendra Goel

Je recommanderais d'adopter l'approche suivante:

  • Créez une classe Row pour représenter une ligne lue dans votre ResultSet. Cela pourrait être un simple wrapper autour d'un Object[].
  • Créez une collection List<Row> et la sous-classe AbstractTableModel à sauvegarder par cette collection.
  • Utilisez un SwingWorker pour remplir votre List<Row> en lisant à partir du ResultSet sous-jacent sur un thread background (c'est-à-dire dans la méthode doInBackground()). Appelez la méthode SwingWorker de publish pour publier les Rows dans le thread Event Dispatch (toutes les 100 lignes, par exemple).
  • Lorsque la méthode SwingWorker de process est appelée avec le dernier bloc lu de lignes, ajoutez-les à votre List<Row> et lancez les TableEvents appropriés pour mettre à jour l'affichage.
  • Utilisez également ResultSetMetaData pour déterminer Class de chaque colonne de la définition TableModel. Cela entraînera leur rendu correct (ce qui ne sera pas le cas si vous utilisez simplement un tableau 2D Object[][]).

L’avantage de cette approche est que l’interface utilisateur ne se verrouille pas lors du traitement de ResultSets volumineux et que l’affichage est mis à jour de manière incrémentielle au fur et à mesure du traitement des résultats.

MODIFIER

Exemple de code ajouté ci-dessous:

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

Un autre moyen puissant et flexible pour afficher les données de base de données dans une table JTable consiste à charger les données résultantes de votre requête dans un CachedRowSet , puis à la connecter à JTable with TableModel adapter.

  1. Requête ---> Données de base de données ---> RowSet
  2. RowSet <-> Adaptateur de modèle de table <-> JTable

This book de George Reese donne le code source de sa classe RowSetModel pour adapter un RowSet en tant que TableModel. Travaillé pour moi hors de la boîte. Mon seul changement était un meilleur nom pour la classe: RowSetTableModel.

Un RowSet est une sous-interface de ResultSet, ajoutée à Java 1.4. Donc, un RowSet est un ResultSet.

Une implémentation CachedRowSet fait le travail pour vous, au lieu de créer une classe Row, une liste d'objets Row et ResultSetMetaData, comme indiqué dans les autres réponses de cette page.

Sun/Oracle fournit une implémentation référence de CachedRowSet. D'autres fournisseurs ou pilotes JDBC peuvent également fournir des implémentations.

Tutoriel RowSet

7
Basil Bourque

En fonction de ce que vous avez déjà fait et de ce que vous êtes prêt à faire, j'utilise Netbeans avec le support Beans Binding pour une application basée sur une base de données avec beaucoup de succès. Vous liez votre JTable à une base de données et celui-ci construit automatiquement les requêtes JPA.

4
Jon

Meilleure façon de remplir jTable avec ResultSet

Conditions préalables

1) Le jeu de résultats "rs" est rempli avec les données dont vous avez besoin ... 2

La mise en oeuvre

        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

Vous devez créer un TableModel personnalisé, où vous pouvez spécifier où et comment les données proviennent. 

Vous devez vraiment comprendre d’abord comment JTable + TableModel fonctionne, puis suivre l’une des réponses précédemment affichées. 

3
OscarRyz

Je sais que la question est ancienne, mais pour quiconque suit la solution d’Adamski, il faut faire attention en partageant les fils ResultSet et ResultSetMetadata entre les fils gui et SwingWorker. J'ai eu une exception d'état interne incohérente lors de l'utilisation de cette approche avec SQLite. La solution consiste à charger toutes les métadonnées dans des champs privés avant d'exécuter la SwingWorker et de laisser les fonctions getter (getColumnName, etc.) pour renvoyer les champs à la place.

1
j_kar

Je donne une petite méthode pour afficher des données de table de base de données dans JTable. Vous devez uniquement transmettre l'ensemble de résultats de la table de base de données en tant que paramètre .


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