2 ComboBox(en)

Diskutiere 2 ComboBox(en) im Datenbankprogrammierung Bereich.
M

maGG

OK, habe den Fehler behoben; der Logikfehler bei der Verzweigung bleibt jedoch. Also die Attribute titelvorn und titelhinten werden nicht richtig gesetzt bzw. es wird nur titelhinten mit Werten belegt.
Java:
        private void loadTitel(int row) throws SQLException{
            String sql = "SELECT * FROM Titel WHERE id=?";
            try(PreparedStatement pst = conn.prepareStatement(sql)){
                pst.setInt(1, row);
                try(ResultSet rs = pst.executeQuery()){
                    if(row != 0){
                        String label = rs.getString("LABEL");
                        boolean infront = rs.getBoolean("VORNE");
                        if(infront == true){
                            titelvorn = label;
                            titelhinten = "";
                        }else{
                            titelvorn = "";
                            titelhinten = label;
                        }
                    }
                }
            }
        }
SQL:
CREATE TABLE Titel (
    id    INTEGER PRIMARY KEY AUTOINCREMENT,
    LABEL TEXT,
    VORNE BOOLEAN
);
So kompliziert kann das Ganze doch nicht sein ... o_O aber es funktioniert leider noch nicht, seht ihr direkt etwas falsches?
 
Zuletzt bearbeitet:
mrBrown

mrBrown

Prüft, ob im ResultSet eine weitere Zeile verfügbar ist, und "springt" zu dieser.
Nach Ausführen der Query zeigt das ResultSet noch auf kein Ergebnis (es könnte ja auch leer sein), mit next zeigt es dann auf die erste Zeile (und mit weiteren Aufrufen dann auf die danach.)
 
mihe7

mihe7

So kompliziert kann das Ganze doch nicht sein ... o_O aber es funktioniert leider noch nicht, seht ihr direkt etwas falsches?
LOL, ne kompliziert ist das alles nicht. Die Prüfung auf row == 0 sollte ganz am Anfang stehen (s. Kommentar #11, ggf. besser noch in der Methode, die loadTitel aufruft) und nach dem Ausführen der Abfrage sollte man prüfen, ob die Abfrage überhaupt ein Ergebnis liefert (s. Kommentar #6, Nummer 3):
Java:
        private void loadTitel(int row) throws SQLException{
            if (row == 0) {
                return;
            }
            String sql = "SELECT * FROM Titel WHERE id=?";
            try(PreparedStatement pst = conn.prepareStatement(sql)){
                pst.setInt(1, row);
                try(ResultSet rs = pst.executeQuery()){
                    if(rs.next()){
                        String label = rs.getString("LABEL");
                        boolean infront = rs.getBoolean("VORNE");
                        if(infront){
                            titelvorn = label;
                            titelhinten = "";
                        }else{
                            titelvorn = "";
                            titelhinten = label;
                        }
                    }
                }
            }
        }
 
M

maGG

Vielen lieben Dank @mihe7 und euch anderen für die Hilfe. Es sieht bei mir jetzt so aus:

Java:
    private void jComboBoxTitelblaActionPerformed(java.awt.event.ActionEvent evt) {                                                 
        int row = jComboBoxTitelbla.getSelectedIndex();
        if (row == 0) {           
            titelvorn = "";
            titelhinten = "";
            Testpreview();
            return;
        }           
        try{
            loadTitel(row);
            Testpreview();
        }catch(SQLException e){
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, e);
            //return false;
        }

        private void loadTitel(int row) throws SQLException{           
            String sql = "SELECT * FROM Titel WHERE id=?";
            try(PreparedStatement pst = conn.prepareStatement(sql)){
                pst.setInt(1, row);
                try(ResultSet rs = pst.executeQuery()){
                    if(rs.next()){
                        String label = rs.getString("LABEL");
                        boolean infront = rs.getBoolean("VORNE");
                        if(infront){
                            titelvorn = label + " ";
                            titelhinten = "";
                        }else{
                            titelvorn = "";
                            titelhinten = ", " + label;
                        }
                    }
                }
            }
        }
Ist es jetzt richtig so?
Ich verstehe ehrlich gesat nicht so ganz was das "return;" und "return false" genau macht o_O
Also return ist ja eine Rückgabe, aber da ist jetzt gar keine Variable mit drin?
 
mihe7

mihe7

Das sieht mal nicht verkehrt aus. Das return sorgt dafür, dass an der Stelle der Methodenaufruf (die Methode muss ja von irgendwo aus aufgerufen worden sein) beendet wird. Einen Rückgabewert gibt es hier nicht, weil die Methode mit dem Rückgabetyp "void", also "nichts", deklariert wurde. Ein "return false" wäre dem entsprechend falsch, da die Methode nicht mit dem Rückgabetyp "boolean" deklariert wurde.

Konkret: der Listener prüft ab, ob row == 0 gilt, falls ja, werden testvorn und testhinten gesetzt und die die Methode Testpreview() wird aufgerufen. Dann wird die Ausführung der Listener-Methode per return beendet. Ist row != 0, dann werden loadTitel(row) und Testpreview() aufgerufen. Tritt dabei eine SQLException auf, wird der betreffende catch-Block ausgeführt (Stacktrace geschrieben, JOptionPane angezeigt).
 
M

maGG

Ok, cool Dankschön @mihe7!

Ich hab leider noch ein paar weitere Methoden, die ich wohl optimieren sollte, z.B. diese hier:

Java:
        private void fillComboBoxFilialenDeutschland(){
            try{
                String sql = "SELECT * FROM Filialen_Deutschland";
                pst = conn.prepareStatement(sql);
                rs = pst.executeQuery();
                //jComboBoxSchablonen.addItem(sql);
                while(rs.next()){
                    String label = rs.getString("LABEL");
                    jComboBoxFilialenDeutschland.addItem(label);
                }
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                try{
                    rs.close();
                    pst.close();
                    //conn.close();
                }catch(SQLException e){
                    e.printStackTrace();
                    JOptionPane.showMessageDialog(null, e);
                }
        }
        }
Ich habe das mal versucht, mit euren Vorschlägen anzupassen:
Java:
        private void fillComboBoxGermanBranches() throws SQLException{
            String sql = "SELECT * FROM Filialen_Deutschland";
            try(PreparedStatement pst = conn.prepareStatement(sql)){
                try(ResultSet rs = pst.executeQuery()){
                    while(rs.next()){
                        String label = rs.getString("LABEL");
                        jComboBoxFilialenDeutschland.addItem(label);
                    }
                }
            }
        }
Könnte das so in etwa funktionieren? Ich hätte gerne eine Fehlerausgabe mit JOptionPane, wo würde ich das reinschreiben?

Update: Kommen folgende Fehler:
Code:
C:\...\GUI.java:130: error: unreported exception SQLException; must be caught or declared to be thrown
        fillComboBoxGermanBranches();
1 error
C:\...\nbproject\build-impl.xml:953: The following error occurred while executing this line:
C:\...\nbproject\build-impl.xml:270: Compile failed; see the compiler error output for details.
BUILD FAILED (total time: 11 seconds)
 
Zuletzt bearbeitet:
M

maGG

s. Kommentar #6 :)

EDIT: damit ich Dich nicht auf die falsche Spur führe, sollte ich noch klarstellen, dass es nur um das try-catch im ActionListener geht.
Danke für deine Antwort!

Ok habe es jetzt um das Aufruf-Statement geschrieben:
Java:
        try {
            fillComboBoxGermanBranches();
        } catch (SQLException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, e);
        }
Das heißt natürlich, dass ich jetzt jedes mal ein Try-Catch-Block brauche, wenn ich die Methode aufrufe. Ich rufe die Methode u.a. beim Start im Standardkonstruktor auf. Ist das das die eleganteste Lösung oder kann ich das auch in der Methode selbst einbetten, oder macht man das nicht? :)
 
mihe7

mihe7

In diese Methode bettet man das nicht ein, wenn man sauber trennen will (in dem Fall ruft man dort auch keine Methoden der JComboBox auf...) Und eigentlich sollte die Methode in eine eigene Klasse.

Die Methode fillComboBoxGermanBranches müsste eigentlich loadGermanBranches heißen und eine Liste zurückgeben, z. B.

Java:
        private List<String> loadGermanBranches() throws SQLException{
            String sql = "SELECT * FROM Filialen_Deutschland";
            try(PreparedStatement pst = conn.prepareStatement(sql)){
                try(ResultSet rs = pst.executeQuery()){
                    List<String> result = new ArrayList<>();
                    while(rs.next()){
                        result.add(rs.getString("LABEL"));
                    }
                    return result;
                }
            }
        }
Wie gesagt, eigentlich lagert man diesen Code in separate Klassen aus. Die fillComboBoxGermanBranches-Methode könnte dann so aussehen:
Java:
    private void fillComboBoxGermanBranches() {
        try {
            for (String label : loadGermanBranches()) {
                jComboBoxFilialenDeutschland.addItem(label);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, e);
        }
    }
Du kannst auch hergehen und in der load-Methode die SQLException abfangen und durch eine unchecked Exception ersetzen, dann fallen die try-catch-Blöcke ganz weg. Dann müsstest Du aber beim Thread einen Exception-Handler für nicht abgefangene Exceptions registrieren.
 
M

maGG

Ah ok, man lernt nie aus :) bin kein richtiger Informatiker, also hab interdisziplinär Grundlagen der Ingenieurinformatik (Java) gehört und Datenbanken für Ingenieuranwendungen (CAD, Revit, C# mit Visual Basic und SQL mit Java), aber nach zwei Module und eine Hand voll von Hausübungen befähigt einen das längst noch nicht sowas mal locker von der Hand runterzuschreiben ;'D
Für mein Aushilfsjob hier wird eh nix erwartet, mache das alles freiwillig.

Hmm deiner Variante wäre wohl besser, evtl. mache ich das noch am Ende, wenn die Hauptfunktionen des Programms alle da sind.
 
M

maGG

Hmm neues Problem :D

Der Code bei #26 hat einen Nachteil: Wenn ich die Methode fillComboBoxGermanBranches() mehrmals aufrufe werden die Einträge der ComboBox immer größer und ich habe Dubletten. Wie kann ich das elegant vermeiden?
Habe es mit .removeAllItems() probiert, aber das funktioniert leider nicht richtig. Ich will ja nicht alle Einträge löschen, z.B. der erste "Bitte auswählen" soll bleiben. Habt ihr eine Idee? :)
 
mrBrown

mrBrown

Hmm neues Problem :D

Der Code bei #26 hat einen Nachteil: Wenn ich die Methode fillComboBoxGermanBranches() mehrmals aufrufe werden die Einträge der ComboBox immer größer und ich habe Dubletten. Wie kann ich das elegant vermeiden?
Habe es mit .removeAllItems() probiert, aber das funktioniert leider nicht richtig. Ich will ja nicht alle Einträge löschen, z.B. der erste "Bitte auswählen" soll bleiben. Habt ihr eine Idee? :)
Die Methode nicht mehrmals aufrufen? :p

Warum willst du die Methode denn mehrmals aufrufen? (Falls das schon irgendwo steht hab ich's überlesen...)
 
M

maGG

Warum willst du die Methode denn mehrmals aufrufen? (Falls das schon irgendwo steht hab ich's überlesen...)
Also wenn man das Programm startet sollen die ComboBoxen alle gefüllt werden. Dann gibt es aber ein zweites Fenster, welches man öffnen kann und wo man die Datenbank im Programm selbst in Tabellen-form editeren kann - hat man das getan und z.B. einen neuen Eintrag hinzugefügt, dann kehrt man auf das Hauptfenster zurück. Beim Zurückkehren soll das Zweitfenster geschlossen werden und alle Comboboxen neu befüllt werden, denn schließlich könnte man an der Datenbank etwas geändert haben. Natürlich könnte ich auch einfach das Programm neustarten, aber ich denke man kann das auch so irgendwie lösen.

Hmm macht das für dich Sinn? :D
 
mrBrown

mrBrown

Entweder alle entfernen, und dann alle inklusive des ersten Eintrags neu hinzufügen, oder ein eigenes ComboBoxModel nutzen, welches das Updaten der Einträge unterstützt und dabei den ersten immer erhält.
 
M

maGG

Heyho, habe ein neues Problem :D
(Habe das versucht aufzuteilen, aber irgendetwas funktioniert noch nicht, also die Vorschau Funktion geht, aber das Updaten der Datenbank leider noch nicht)

Seht ihr einen Fehler? Vielen Dank! :)

Java:
    private void jButtonUpdateA1ActionPerformed(java.awt.event.ActionEvent evt) {                                               
        int row = Integer.parseInt(jTextFieldF1.getText());
        String label = jTextFieldF2.getText();
        String strasze = jTextFieldF3.getText();
        String plzort = jTextFieldF4.getText();
        String ort = jTextFieldF5.getText();
        int telland = Integer.parseInt(jTextFieldF6.getText());
        long telanfangint = Long.parseLong(jTextFieldF7.getText());
        String telanfangtxt = jTextFieldF8.getText();
        String telendedefault = jTextFieldF9.getText();
        String faxanfangtxt = jTextFieldF10.getText();
        String faxendetxt = jTextFieldF11.getText();
        if  (jTextFieldF1.getText().equals("") || label.equals("") || strasze.equals("")
            || plzort.equals("") || ort.equals("") || jTextFieldF6.getText().equals("")
            || jTextFieldF7.getText().equals("") || telanfangtxt.equals("") || telendedefault.equals("")
            || faxanfangtxt.equals("") || faxendetxt.equals("")){
            JOptionPane.showMessageDialog(null, "Fehler: Bitte notwendige Parameter setzen");
        }else {           
            try{
                updateTableGermanBranches(row, label, strasze, plzort, ort, telland, telanfangint, telanfangtxt, telendedefault, faxanfangtxt, faxendetxt);
                viewTableGermanBranches();
                JOptionPane.showMessageDialog(null, "Filiale aktualisiert");
            }catch(SQLException e){
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, e);
            }
        }
    }
Java:
    public void updateTableGermanBranches(int row, String label, String strasze, String plzort, String ort, int telland, long telanfangint, String telanfangtxt, String telendedefault, String faxanfangtxt, String faxendetxt) throws SQLException{
        String sql = "UPDATE Filialen_Deutschland SET id=?, LABEL=?, STRASZE=?, PLZ_ORT=?, ORT=?,TEL_LAND=?, TEL_ANFANG_INT=?,"
                        + " TEL_ANFANG_TXT=?, TEL_ENDE_DEFAULT=?, FAX_ANFANG_TXT=?, FAX_ENDE_TXT=? WHERE id=?";
        try (PreparedStatement pst = conn.prepareStatement(sql)) {
            try (ResultSet rs = pst.executeQuery()) {
                if (rs.next()) {
                    pst.setInt(1, row); // id
                    pst.setString(2, label); //LABEL
                    pst.setString(3, strasze); //STRASZE
                    pst.setString(4, plzort); //PLZ_ORT
                    pst.setString(5, ort); //ORT
                    pst.setInt(6, telland); //TEL_LAND
                    pst.setLong(7, telanfangint); //TEL_ANFANG_INT
                    pst.setString(8, telanfangtxt); //TEL_ANFANG_TXT
                    if (telendedefault.equals("")) {
                        pst.setObject(9, null);
                    } else {
                        pst.setInt(9, Integer.parseInt(telendedefault)); //TEL_ENDE_DEFAULT
                    }
                    pst.setString(10, faxanfangtxt); //FAX_ANFANG_TXT
                    if (faxendetxt.equals("")) {
                        pst.setObject(11, null);
                    } else {
                        pst.setString(11, faxendetxt); //FAX_ENDE_TXT
                    }
                    pst.setInt(12, row); // id (doppelt)
                    pst.executeUpdate();                               
                }
            }
        }   
    }
Java:
    public void viewTableGermanBranches() throws SQLException{
         String sql = "SELECT * FROM Filialen_Deutschland";
        try (PreparedStatement pst = conn.prepareStatement(sql)) {
            try (ResultSet rs = pst.executeQuery()) {
                if (rs.next()) {
                    jTableFilialen_Deutschland.setModel(DbUtils.resultSetToTableModel(rs));
                }
            }
        }   
    }
Code:
java.sql.SQLException: Query does not return results
    at org.sqlite.jdbc3.JDBC3PreparedStatement.executeQuery(JDBC3PreparedStatement.java:68)
    at signatur.GUI.updateTableGermanBranches(GUI.java:792)
    at signatur.GUI.jButtonUpdateA1ActionPerformed(GUI.java:5154)
    at signatur.GUI.access$1000(GUI.java:60)
    at signatur.GUI$11.actionPerformed(GUI.java:1493)
 
mrBrown

mrBrown

WTF.
bzw: WTF?!?!

Java:
    public void updateTableGermanBranches(int row, String label, String strasze, String plzort, String ort, int telland, long telanfangint, String telanfangtxt, String telendedefault, String faxanfangtxt, String faxendetxt) throws SQLException{
        String sql = "UPDATE Filialen_Deutschland SET id=?, LABEL=?, STRASZE=?, PLZ_ORT=?, ORT=?,TEL_LAND=?, TEL_ANFANG_INT=?,"
                        + " TEL_ANFANG_TXT=?, TEL_ENDE_DEFAULT=?, FAX_ANFANG_TXT=?, FAX_ENDE_TXT=? WHERE id=?";
        try (PreparedStatement pst = conn.prepareStatement(sql)) {
            try (ResultSet rs = pst.executeQuery()) {
                if (rs.next()) {
                    pst.setInt(1, row); // id
                    pst.setString(2, label); //LABEL
                    pst.setString(3, strasze); //STRASZE
                    pst.setString(4, plzort); //PLZ_ORT
                    pst.setString(5, ort); //ORT
                    pst.setInt(6, telland); //TEL_LAND
                    pst.setLong(7, telanfangint); //TEL_ANFANG_INT
                    pst.setString(8, telanfangtxt); //TEL_ANFANG_TXT
                    if (telendedefault.equals("")) {
                        pst.setObject(9, null);
                    } else {
                        pst.setInt(9, Integer.parseInt(telendedefault)); //TEL_ENDE_DEFAULT
                    }
                    pst.setString(10, faxanfangtxt); //FAX_ANFANG_TXT
                    if (faxendetxt.equals("")) {
                        pst.setObject(11, null);
                    } else {
                        pst.setString(11, faxendetxt); //FAX_ENDE_TXT
                    }
                    pst.setInt(12, row); // id (doppelt)
                    pst.executeUpdate();                             
                }
            }
        } 
    }
Du solltest das PreparedStatement erst befüllen, und dann die Query ausführen.

etwa:
Java:
try (PreparedStatement pst = conn.prepareStatement(sql)) {
    pst.setInt(1, row); // id
    pst.setString(2, label); //LABEL
    ....
    pst.executeUpdate()
}
ResultSet ist dabei überflüssig, du willst ja ein Update und kein Select ausführen.
 
M

maGG

haha naja Methoden ausgelagert habe ich noch nicht soviele und es ist viel noch auskommentiert, da wird einiges an Zeilen wieder von verschwinden.
Hat mit deinen Tipps auf jeden Fall geklappt jetzt, hab noch ein paar Datentypen Fehler, aber die krieg ich morgen bestimmt noch weg, Dankeschön! :)
 
mihe7

mihe7

naja Methoden ausgelagert habe ich noch nicht soviele
Ich hatte im letzten Quartal Fremdcode vor mir, da hatte eine einzige Methode mehr Zeilen - die dafür fast alle sehr ähnlich waren... Da brauchst Du Karte und Kompass, dass Du noch weißt, ob Du an der richtigen Stelle editierst.
 
Thema: 

2 ComboBox(en)

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben