Wie kann man eine Datenbank in eine JTable mit AbstractTableModel einlesen?

Nico2201

Mitglied
Hallo,

ich habe vor kurzem eine Datenbank mit Hilfe von mariadb erstellt, mit folgenden Werten:
  • ID
  • Vorname
  • Nachname
  • Alter
  • Wohnort
  • Eintragedatum
Als Vorlage für mich, habe ich eine Testverbindung zu dieser Datenbank mit Java erstellt, die auch funktioniert hat. Nun habe ich ein neues Projekt gestartet, wo ich die Daten aus der Datenbank in meine JTable mit einem AbstractTableModel einlesen möchte. In diesem Projekt habe ich 2 Frames und eine Klasse. Der 1. Frame beinhaltet nur die Verbindung zur Datenbank - ist die Verbindung erfolgreich, dann wird der 2. Frame geöffnet, der die JTable beinhaltet. Nun habe ich das Problem, dass ich nicht wirklich weiß, wie man die Datenbank in die JTable einlesen kann. Hier einmal die Methode "Verbinden":

Java:
public void Verbinden(ActionEvent e) {
        
        try {
            
            info.setText("Der Treiber wird geladen..");
            Class.forName(eingabeDriver.getText()).newInstance();
            info.setText("Der Treiber wurde geladen.");
        }
        
        catch(Exception ex) {
            
            info.setText("Der Treiber konnte nicht geladen werden!");
        }
        
        try {
            
            info.setText("Die Verbindung wird hergestellt..");
            conn = DriverManager.getConnection(eingabeURL.getText() + "://" + eingabeHost.getText() + ":" + eingabePort.getText() + "/" + eingabeDatenbankname.getText(), eingabeBenutzername.getText(), eingabePasswort.getText());
            info.setText("Die Verbindung wurde hergestellt.");
            conn.close();
        }
        
        catch(Exception ex) {
            
            info.setText("Die Verbindung konnte nicht hergestellt werden!");
        }

*Der 2. Frame mit der JTable wird automatisch geöffnet, sollte die Verbindung erfolgreich sein (was auch der Fall ist).*

Und hier mein AbstractTableModel:

Java:
public class MeinModel extends AbstractTableModel {

    private static final long serialVersionUID = 1488059323556292793L;
    private int row = 100;
    private int col = 6;
    private String[] colNamen = {"ID", "Vorname", "Nachname", "Alter", "Wohnort", "Eintragedatum"};

    public Object[][] data = new Object[row][col];

    public int getColumnCount() {

        return col;
    }
    
    public String getColumnName(int col) {
        
        return colNamen[col];
    }

    public int getRowCount() {

        return row;
    }

    public Object getValueAt(int row, int col) {

        return data[row][col];
    }
    
    public void setValueAt(Object value, int row, int col) {
        
        data[row][col] = value;
        fireTableCellUpdated(row, col);
    }
    
    public boolean isCellEditable(int row, int col) {
        
        return true;
    }

}

Vielen Dank für eure Bemühungen.

Freundliche Grüße
 
Wenn du im AbstractTableModel auch mit einem 2D-Object Array Arbeitest hast du eigentlich so ziemlich genau das gleiche wie mit dem DefaultTableModel erreicht. Nur kann dein Model weniger. Ich habe aber das Gefühl du verstehst es nun vom Ansatz :)

Für die DB brauchst du eine Query ausführen. Du erhälst ein ResultSet, welches du iterieren und in dein Model übertragen muss - entweder in dein 2D Object Array (aber dann besser DefaultTableModel) oder in ein DAO Object, dessen Liste im AbstractTableModel gehalten wird. Für die Verarbeitung con ResultSets gibt es wirklich genügend Beispiele im Netz.

So etwa könnte das AbstractTableModel mit einem DAO aussehen:
Java:
package javaforum.org.nico;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.table.AbstractTableModel;


public class PersonTableModel extends AbstractTableModel {
    private final static int ROWLIMIT = 100; 
    
    private List<Person> personen;
    private final String[] colNamen = {"ID", "Vorname", "Nachname", "Alter", "Wohnort", "Eintragedatum"};
    
    
    public PersonTableModel() {
        personen = new ArrayList<>();
    }
    
    
    public void addPerson(Person person) {
        if(personen.size() >= ROWLIMIT) return;
        
        personen.add(person);
        
        fireTableRowsInserted(personen.size() - 1, personen.size() - 1);
    }
    
    @Override
    public int getColumnCount() {
        return colNamen.length;
    }

    @Override
    public String getColumnName(int colIndex) {
        return colNamen[colIndex];
    }

    @Override
    public int getRowCount() {
        return ROWLIMIT;
    }

    @Override
    public Object getValueAt(int rowIndex, int colIndex) {
        try {
            Person person = personen.get(rowIndex);
            switch(colIndex) {
                case 0: return person.getId();
                case 1: return person.getVorname();
                case 2: return person.getNachname();
                case 3: return person.getAlter();
                case 4: return person.getWohnort();
                case 5: return person.getEintragedatum();
                default: return null;
            }
        } catch(IndexOutOfBoundsException e) {
            return null;
        }
    }

    @Override
    public void setValueAt(Object o, int rowIndex, int colIndex) {
        try {
            Person person = personen.get(rowIndex);

            switch(colIndex) {
                case 0: person.setId((Integer)o); break;
                case 1: person.setVorname((String)o); break;
                case 2: person.setNachname((String)o); break;
                case 3: person.setAlter((Integer)o); break;
                case 4: person.setWohnort((String)o); break;
                case 5: person.setEintragedatum((Date)o); break;
                default:
                    
                fireTableCellUpdated(rowIndex, colIndex);    
            }
        } catch(IndexOutOfBoundsException e) {}
    }

    @Override
    public boolean isCellEditable(int rowIndex, int colIndex) {
        return true;
    }

    @Override
    public Class<?> getColumnClass(int colIndex) {
        switch(colIndex) {
            case 0: case 3: return Integer.class;
            case 1: case 2: case 4: return String.class;
            case 5: return Date.class;
            default: return null;
        }
    }    
}
 
Wenn du im AbstractTableModel auch mit einem 2D-Object Array Arbeitest hast du eigentlich so ziemlich genau das gleiche wie mit dem DefaultTableModel erreicht. Nur kann dein Model weniger. Ich habe aber das Gefühl du verstehst es nun vom Ansatz :)

Für die DB brauchst du eine Query ausführen. Du erhälst ein ResultSet, welches du iterieren und in dein Model übertragen muss - entweder in dein 2D Object Array (aber dann besser DefaultTableModel) oder in ein DAO Object, dessen Liste im AbstractTableModel gehalten wird. Für die Verarbeitung con ResultSets gibt es wirklich genügend Beispiele im Netz.

So etwa könnte das AbstractTableModel mit einem DAO aussehen:
Java:
package javaforum.org.nico;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.table.AbstractTableModel;


public class PersonTableModel extends AbstractTableModel {
    private final static int ROWLIMIT = 100;
   
    private List<Person> personen;
    private final String[] colNamen = {"ID", "Vorname", "Nachname", "Alter", "Wohnort", "Eintragedatum"};
   
   
    public PersonTableModel() {
        personen = new ArrayList<>();
    }
   
   
    public void addPerson(Person person) {
        if(personen.size() >= ROWLIMIT) return;
       
        personen.add(person);
       
        fireTableRowsInserted(personen.size() - 1, personen.size() - 1);
    }
   
    @Override
    public int getColumnCount() {
        return colNamen.length;
    }

    @Override
    public String getColumnName(int colIndex) {
        return colNamen[colIndex];
    }

    @Override
    public int getRowCount() {
        return ROWLIMIT;
    }

    @Override
    public Object getValueAt(int rowIndex, int colIndex) {
        try {
            Person person = personen.get(rowIndex);
            switch(colIndex) {
                case 0: return person.getId();
                case 1: return person.getVorname();
                case 2: return person.getNachname();
                case 3: return person.getAlter();
                case 4: return person.getWohnort();
                case 5: return person.getEintragedatum();
                default: return null;
            }
        } catch(IndexOutOfBoundsException e) {
            return null;
        }
    }

    @Override
    public void setValueAt(Object o, int rowIndex, int colIndex) {
        try {
            Person person = personen.get(rowIndex);

            switch(colIndex) {
                case 0: person.setId((Integer)o); break;
                case 1: person.setVorname((String)o); break;
                case 2: person.setNachname((String)o); break;
                case 3: person.setAlter((Integer)o); break;
                case 4: person.setWohnort((String)o); break;
                case 5: person.setEintragedatum((Date)o); break;
                default:
                   
                fireTableCellUpdated(rowIndex, colIndex);   
            }
        } catch(IndexOutOfBoundsException e) {}
    }

    @Override
    public boolean isCellEditable(int rowIndex, int colIndex) {
        return true;
    }

    @Override
    public Class<?> getColumnClass(int colIndex) {
        switch(colIndex) {
            case 0: case 3: return Integer.class;
            case 1: case 2: case 4: return String.class;
            case 5: return Date.class;
            default: return null;
        }
    }   
}

Vielen Dank für deine Hilfe!

Das mit dem ResultSet weiß ich und habe es auch so weit möglich umgesetzt, aber irgendwie wird die Datenbank nicht in die JTable geschrieben. Das ist mein try-catch-Block bzgl. ResultSet:

Java:
try {
            
            Statement stmt = conn.createStatement();
            
            ResultSet rs = stmt.executeQuery("SELECT * FROM benutzer_tb");
            
            while(rs.next()) {
                
                rs.getInt(1);
                rs.getString(2);
                rs.getString(3);
                rs.getInt(4);
                rs.getString(5);
                rs.getDate(6);
            }
            
            rs.close();
        }
        
        catch(Exception ex) {
            
            ex.printStackTrace();
        }

Ich habe es auch mit table.setValueAt(aValue, row, column); versucht, aber das hat genauso wenig funktioniert wie das, was man oben im Code sieht.

Weißt du da vielleicht auch eine Lösung für? Mir fällt leider nichts ein. :mad:

P.S.: ex.printStackTrace(); liefert mir auch keine Fehlermeldung, sodass ich wenigstens sehen könnte, was ich falsch gemacht habe..
 
Nach ein paar Anläufen ist es mir letztendlich selber gelungen das Problem zu lösen. :) Um das ganze etwas zu vereinfachen, habe ich ein DefaultTableModel "erstellt" und damit funktioniert alles einwandfrei.

Vielen Dank für eure Hilfe!
 
Zurück