[JTable] DB-Einträge aktualisieren

The_Answer1985

Erfahrenes Mitglied
Hallo alle miteinander,

ich habe eine JTable, die mit Daten aus einer DB gefüllt wird. Das hab ich nach langer Suche mit Hilfe folgendes Threads geschafft.

http://www.tutorials.de/forum/java/222502-datenbank-auslesen-und-werte-jtable-ueberfuehren.html

Meine Tabelle nutzt das DefaultTableModel.
Wenn ich Änderungen an den Daten der Tabelle vornehme, sollen diese natürlich auch in
die DB übernommen werden.

Nur, wie mache ich das?
Muss ich dazu dann doch ein eigenes TableModel implementieren?
Oder ließe es sich in meinen Code integrieren?

Diese Klasse ist für den DB-Zugriff zuständig und erstellt zudem die Tabelle
Code:
    final Vector<String> bezeichnung = new Vector<String>() {

        {
             add("Device Nr");
             add("Modul/Bundle");
             add("Benutzername");
             add("Passwort");
             add("Betriebssystem");
             add("Installationsdatum");
         }
     };
    
    javax.swing.JTable meineTabelle;
    DefaultTableModel meinModel;  
    
    public DBZugriffCADDetails() throws SQLException{
        
        meinModel = new DefaultTableModel(1, 6);
        meinModel.setColumnIdentifiers(bezeichnung);
        
        try {
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
            connection = DriverManager.getConnection("jdbc:odbc:odbc2access");
        } 
        catch (InstantiationException ex1) {
            System.out.println("Es ist ein Fehler aufgetreten: " + ex1.getMessage());
        } 
        catch (IllegalAccessException ex2) {
            System.out.println("Es ist ein Fehler aufgetreten: " + ex2.getMessage());
        } 
        catch (ClassNotFoundException ex3) {
            System.out.println("Es ist ein Fehler aufgetreten: " + ex3.getMessage());
        } 
        catch (SQLException ex4) {
            ex4.printStackTrace();
        }
    }

    public javax.swing.JTable tabelleFuellen(){
        meineTabelle = new javax.swing.JTable(meinModel);
        meineTabelle.setModel(meinModel);
        return meineTabelle;    
    }
        
    public void aktualisieren(String kdnr){
        
        meinModel.setDataVector(detailLesen("SELECT Kundennummer,Module,DongleNr,Benutzername,Passwort,BSLokal,Installationsdatum FROM MarbaCADDetailsVersuch WHERE Kundennummer = " + kdnr + ";"), bezeichnung);
        meinModel.fireTableDataChanged();
        
    }
    
    public Vector<Vector<String>> detailLesen(String befehl){
        
        statement = null;
        result = null;
        
        try 
        {
                statement = connection.createStatement();
                result = statement.executeQuery(befehl);
        
                if(result != null){
             
                    Vector<Vector<String>> results = new Vector<Vector<String>>();
             
                    while(result.next()){    

                        Vector<String> detail = new Vector<String>();
                
                        detail.add(result.getString(3));
                        detail.add(result.getString(2));
                        detail.add(result.getString(4));
                        detail.add(result.getString(5));
                        detail.add(result.getString(6));
                        detail.add(result.getString(7));
                       
                        results.add(detail);
                       
                        meinModel.setDataVector(results, bezeichnung);
                    }
                    return results;
                }
                
        }
        catch (SQLException ex1) 
        {
                System.out.println("Es ist ein Fehler aufgetreten: " + ex1.getMessage());
        }
        return null;

In einem Dialog wird diese Tabelle dann eingebunden und soll demnach editierbar sein.

Danke für jeden Post.

Liebe Grüße
 
Moin!
Falls du jede Änderung sofort in die Datenbank sichern möchtest, könntest du folgendermaßen vorgehen:
Füge deinem TableModel einen TableModelListener hinzu. Dieser empfängt dann jedesmal, wenn dein TableModel geändert wurde ein TableModelEvent. Durch dieses Event erfährst du dann, welche Änderung genau passiert ist.

Aus dem TableModel kannst du dann den Datenvektor mit den geänderten Daten holen und diese dann wie gewohnt speichern..
Klar soweit? ;)

*grüssle*
MeinerEiner
 
Hm eine ander Möglichkeit wäre einfach die setValueAt-methode des DefaultTableModels zu überschreiben. Das wäre vielleicht sogar einfacher als nen Listener zu implementieren.
Ist nur so ein Gedanke

Gruß

Gora
 
Hallo,

@gora
So hast du aber Funktion in ein Model reingebracht. Das ist nicht so ganz der Sinn eines Models. Angenommen es soll nachher nicht mehr in eine DB geschrieben werden, dann muss er sein Model umschreiben. Anders entfernt er nur die Zeile, in der der Listener hinzugefügt wird. Oder es soll wo anders gespeichert werden.
Also ich glaube auch, dass die Variante mit dem Listener die bessere Variante ist.

MFG

zEriX
 
So hast du aber Funktion in ein Model reingebracht. Das ist nicht so ganz der Sinn eines Models. Angenommen es soll nachher nicht mehr in eine DB geschrieben werden, dann muss er sein Model umschreiben. Anders entfernt er nur die Zeile, in der der Listener hinzugefügt wird. Oder es soll wo anders gespeichert werden.

@ zerix: Du nimmst mir die Worte aus dem Mund. So wars gedacht...

*grüssle*
MeinerEiner
 
Ich lasse mich immer gerne belehren danke..
So betrachtet macht es schon Sinn. habe ich nicht drüber nachgedacht ...
Ja das Tablemodel soll ja nur Adapter sein ...
Grüße Gora
 
Also...

Danke für die Antworten :)

Die blanke Theorie habe ich verstanden, nur an der Umsetzung hakt es ein wenig.

Ich habe meiner Tabellle jetzt einen Listener hinzugefügt (siehe Code). Dieser Listener funktioniert auch wunderbar, wenn ich eine (oder mehrere) Zellen eines Datensatzes ändere.

Nur macht mir die Umsetzung zum Hinzufügen bzw. Löschen eines Datensatzes noch Probleme. Ich scheitere daran, eine Zeile in der Tabelle hinzuzufügen.

Mit meinem Quellcode kann die Tabelle bisher nur eines:
Werte aus den Zellen einer Zeile entnehmen und diese in die DB übertragen, und das jedesmal, wenn die Zelle mit "Enter" verlassen wird.

Der Code dazu schaut folgendermaßen aus:
Code:
    public javax.swing.JTable tabelleErzeugen(){
        
        meineTabelle = new javax.swing.JTable(meinModel);
        meineTabelle.setModel(meinModel);
        
        meinModel.addTableModelListener(new TableModelListener() {

            public void tableChanged(TableModelEvent e) {
                
                int zeilenNr = meineTabelle.getSelectedRow();
                
                detailAendern(String.valueOf(meineTabelle.getValueAt(zeilenNr, 0)), 
                              String.valueOf(meineTabelle.getValueAt(zeilenNr, 2)), 
                              String.valueOf(meineTabelle.getValueAt(zeilenNr, 1)), 
                              String.valueOf(meineTabelle.getValueAt(zeilenNr, 3)),
                              String.valueOf(meineTabelle.getValueAt(zeilenNr, 4)),
                              String.valueOf(meineTabelle.getValueAt(zeilenNr, 5)));
                
                meinModel.fireTableDataChanged();
            }
            
        });

        
        return meineTabelle;    
    }

    public Vector<Vector<String>> detailLesen(String befehl){
        
        statement = null;
        result = null;
        
        try 
        {
                statement = connection.createStatement();
                result = statement.executeQuery(befehl);
        
                if(result != null){
             
                    Vector<Vector<String>> results = new Vector<Vector<String>>();
             
                    while(result.next()){    

                        Vector<String> detail = new Vector<String>();
                        
                        detail.add(result.getString(1));
                        detail.add(result.getString(4));
                        detail.add(result.getString(3));
                        detail.add(result.getString(5));
                        detail.add(result.getString(6));
                        detail.add(result.getString(7));
                       
                        results.add(detail);
                       
                        meinModel.setDataVector(results, bezeichnung);
                    }
                    return results;
                }
                
        }
        catch (SQLException ex1) 
        {
                System.out.println("Es ist ein Fehler aufgetreten: " + ex1.getMessage());
        }
        return null;
    }

Danke für eure Posts.

Liebe Grüße

EDIT:
eine neue Zeile hinzufügen funktioniert, allerdings nur, wenn ich den Listener weglasse.
Mit dem Listener erhalte ich eine "java.lang.ArrayIndexOutOfBoundsException: -1" an der Stelle, an der ich die Methode
zum Ändern der Daten in der DB aufrufe.

Wie hängt das zusammen, woran liegt das

Liebe Grüße
 
Zuletzt bearbeitet:
Moin!

Schau dir bitte mal das TableModelEvent im Detail an. Dies liefert alle Informationen die du benötigst. Als was (Zeile oder Zelle) wie (Insert, Update, Delete) geändert wurde.

Daher solltest du nicht die gerade selektierte Zeile deiner Tabelle abfragen. Schließlich kann sich die Selektion ändern, nach dem die das Editieren abgeschloßen hast (daher auch die Exception).

Ausserdem ist der Aufruf "meinModel.fireTableDataChanged()" unnötig. Das macht das Model schon automatisch, wenn es geändert wurde.

*grüssle*
MeinerEiner
 
Zuletzt bearbeitet von einem Moderator:
Danke für dein Post, ich wusste nicht inwieweit ich die Events voneinander unterscheiden kann :)

Allerdings eines ist mir immer noch net klar, wieso soll ich keine selektierte Spalte angeben beim Methodenaufruf?

Die Sache is nämlich, dass eine Spalte die ID des Datensatzes anzeigt, die brauch ich natürlich im SQL Stmt wieder, damit ich den Datensatz identifizieren kann. An diese ID komm ich ja nur, wenn ich von der Zeile, die selektiert wurde, die ID entnehme.

Und um den Wert aus einer Zelle zu holen muss ich in der getValueAt( ) Methode die Zelle angeben, wie kann ich das anders machen?

Zu der Exception:

Ich habe das Löschen eines Datensatzes implementiert. Ich erhalte die Exception mittlerweile nur noch hier.
Konkret:
Ich habe einen Datensatz angelegt und wollte diesen umgehend löschen: Exception.
Dann habe ich einen weiteren Datensatz angelegt, wollte diesen löschen und es funktionierte.

Code:
public void tableChanged(TableModelEvent e) {

                if(e.getType() == TableModelEvent.INSERT){
                    System.out.println("Neue Zeile eingefügt");
                }
                else if(e.getType() == TableModelEvent.UPDATE){
                    System.out.println("Datensatz wird geändert");
                    
                    if(neueZeile){
                        detailSchreiben(String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 2)), 
                                  String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 1)), 
                                  String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 3)),
                                  String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 4)),
                                  String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 5)));
                    }
                    else{
                        detailAendern(String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 0)), 
                                  String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 2)), 
                                  String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 1)), 
                                  String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 3)),
                                  String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 4)),
                                  String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 5)));
                    }
                    
                }
                else if(e.getType() == TableModelEvent.DELETE){
                    detailLoeschen(String.valueOf(meineTabelle.getValueAt(meineTabelle.getSelectedRow(), 0)));
                }
            }
 
Moin!
Wenn du eine Zeile löscht, kann sie danach ja wohl nicht mehr selektiert sein, oder?
Auch nach sonstigen Editieren muss die selektierte Zeile nicht der editierten Zeile entsprechen.
Aus diesem Grund, und das habe ich dir bereits gesagt, sollst du aus dem TableModelEvent extrahieren, welche Zeile/Zelle editiert wurde.

Aber wie ich sehe stehst du jetzt natürlich vor dem Problem, dass wenn du eine Zeile löscht, du auch nicht mehr erfahren kannst, welche ID diese Zeile hatte (wurde ja schließlich aus dem Model gelöscht).

Dazu hätte ich jetzt auch mal ne Frage.. wie löscht du eine Zeile eigentlich bzw. wie fügst du eine ein? Ich glaube nämlich, bezüglich des Lösches, wäre es fast besser das abzufangen. D.h. erst aus der Datenbank löschen (damit du die ID bekommst) und dann erst aus der Tabelle entfernen..

*grüssle*
MeinerEiner
 
Zurück