2 ComboBox(en)

Ich habe 2 ComboBox(en) und in beide wird mit einer fill-Methode Labels, mit Strings, aus einer SQL Datenbank geladen. Genauer gesagt werden mit "SELECT *" alle Spalten ausgewählt, aber nur die LABEL(s) aus entsprechender Spalte als String Werte in die ComboBox(en) geladen.

Jetzt möchte ich folgendes errreichen: Wenn man in der ersten ComboBox ein Wert auswählt, der nicht dem ersten entspricht ("Bitte auswählen"), dann soll die andere ComboBox auf den ersten Wert ("Bitte auswählen") springen. Das Ganze hat den Hintergrund, dass man nicht in beiden ComboBox(en) einen Wert auswählen soll, da beide Boxen die selben Variablen mit Werten belegen. Im nicht Sehbaren ist das egal, da die Werte vom letzten Action Performed einfach überschrieben werden. Ich möchte jetzt das Ganze visuell unterstützen, so dass der Nutzer ganz klar sehen kann was die zu letzt gesetzte ComboBox war.

Also schematisch: Wähle ich in ComboBox 1 etwas aus, was nicht dem Index 0 entspricht, dann soll bei ComboBox 2 der Index auf 0 gesetzt werden und andersrum. Das führt dazu das man nur einen Wert in beiden ComboBox(en) gleichzeitig auswählen kann - und genau so will ich es.

Ohne SQL und Datenbank Anbindung geht das ganz leicht, mit kommen bei mir jedoch Fehler...

.setSelectedIndex(0); führt dazu, dass die Datenbank gelockt wird.
.setModel("Bitte auswählen"); führt zu dem Fehler: String cannot be converted to ComboBoxModel<String>

Wie kann man das möglichst elegant lösen? Bzw. habt ihr mich verstanden? :D
 
Wenn beim Auswahl eines Wertes aus einer ComboBox die DB gesperrt wird, ist etwas grundlegend falsch. Recht viel mehr kann man ohne Details nicht dazu sagen.
 
Danke für deine Antwort. Das ist leider nicht ganz korrekt. Wenn man einen Wert in der ComboBox auswählt entsteht kein Fehler. Nur bei den oben genannten zwei Beispielen. ;)
 
Gut, mal anders: warum und was passiert denn auf der DB, wenn Du in der ComboBox etwas auswählst?
 
In der Datenbank sollte eigentlich nix verändert werden, lediglich Werte aus der Datenbank in GUI geladen werden. Wenn man einen Wert in der ComboBox setzt, dann werden Attribute gesetzt (benutze sqlitejdbc sowie rs2xml):
Java:
    private void jComboBoxFilialenDeutschlandActionPerformed(java.awt.event.ActionEvent evt) {                                                             
        try{
            int row = jComboBoxFilialenDeutschland.getSelectedIndex();
            String sql = "SELECT * FROM Filialen_Deutschland WHERE id='" + row + "' ";
            pst = conn.prepareStatement(sql);
            rs = pst.executeQuery();
                strasze = rs.getString("STRASZE");
                plzort = rs.getString("PLZ_ORT");
                ort = rs.getString("ORT");
                telLaendercode = "" + rs.getInt("TEL_LAND");
                telStartInt = "" + rs.getInt("TEL_ANFANG_INT");
                telStartGer = rs.getString("TEL_ANFANG_TXT");
                telEndDefault = "" + rs.getInt("TEL_ENDE_DEFAULT");
                faxStart = rs.getString("FAX_ANFANG_TXT");
                faxEndDefault = rs.getString("FAX_ENDE_TXT");
                Preview();
                Testpreview();
                //jComboBoxFilialenAusland.setSelectedIndex(0);
                //jComboBoxFilialenAusland.setModel("Bitte auswählen");
        }catch(Exception e){
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, e);
        }finally{
            try{
                rs.close();
                pst.close();
            }catch(SQLException e){
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, e);
            }
        }
    }
 
Hier findet keine saubere Trennung zwischen DB und UI statt. Du solltest die DB separat behandeln (s. z. B. Repository-Pattern). Aktuell verschachtelst Du ggf. mehrere SQL-Abfragen, d. h. Du hast mehrere Cursor gleichzeitig offen. Das kann zu Problemen führen.

Als Quick & Dirty-Lösungsansatz kannst Du den DB-Part in eine separate Methode auslagern. Den folgende Code bitte als Pseudocode verstehen (ich habe das nur hier im Forum editiert, kann sein, dass er nicht übersetzt wird):
Java:
    private void jComboBoxFilialenDeutschlandActionPerformed(java.awt.event.ActionEvent evt) {                                                            
        int row = jComboBoxFilialenDeutschland.getSelectedIndex();
        try {
            loadGermanBranch(row);
            Preview();
            Testpreview();
            jComboBoxFilialenAusland.setSelectedIndex(0);
        }catch(SQLException e){
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, e);
            return false;
        }
    }
   
    private void loadGermanBranch(int row) throws SQLException {
        String sql = "SELECT * FROM Filialen_Deutschland WHERE id=?";
        try(pst = conn.prepareStatement(sql)) {
            pst.setInt(1, row);
            try(rs = pst.executeQuery()) {
                strasze = rs.getString("STRASZE");
                plzort = rs.getString("PLZ_ORT");
                ort = rs.getString("ORT");
                telLaendercode = "" + rs.getInt("TEL_LAND");
                telStartInt = "" + rs.getInt("TEL_ANFANG_INT");
                telStartGer = rs.getString("TEL_ANFANG_TXT");
                telEndDefault = "" + rs.getInt("TEL_ENDE_DEFAULT");
                faxStart = rs.getString("FAX_ANFANG_TXT");
                faxEndDefault = rs.getString("FAX_ENDE_TXT");
            }
        }
    }
Analog für die andere ComboBox. Noch ein paar grundsätzliche Anmerkungen:
1. Baue Parameter in SQL-Strings nie manuell ein. Verwende die setXXX-Methoden von PreparedStatement.
2. Verwende try-with-resources (die Ressourcen werden dann automatisch geschlossen)
3. Verlass Dich nicht darauf, dass Ergebnisse vorhanden sind (habe ich im Code jetzt nicht berücksichtigt). Die row könnte -1 sein und zwischen dem Laden der Werte der ComboBox und der Auswahl durch den Benutzer liegt genügend Zeit, dass jemand ausgerechnet die Filiale löscht, die der Benutzer dann auswählt.
 
Ok, das verstehe ich nicht ganz; muss man das so trennen? Ich habe einige SQL Methode, zum Befüllen, editieren, etc. muss man das immer trennen? Weil das würde enorm viel mehr Zeilen Code bedeuten :O
 
1. Baue Parameter in SQL-Strings nie manuell ein. Verwende die setXXX-Methoden von PreparedStatement.
2. Verwende try-with-resources (die Ressourcen werden dann automatisch geschlossen)
3. Verlass Dich nicht darauf, dass Ergebnisse vorhanden sind (habe ich im Code jetzt nicht berücksichtigt). Die row könnte -1 sein und zwischen dem Laden der Werte der ComboBox und der Auswahl durch den Benutzer liegt genügend Zeit, dass jemand ausgerechnet die Filiale löscht, die der Benutzer dann auswählt.
habe ich das mit finally -> rs.close() und pst.close() nicht schon sichergestellt? Also das es geschlossen wird meine ich. Der Code ist von mir zusammengesetzt; habe leider kaum Beispiele dazu im Internet gefunden wie man das perfekt machen kann. Auch meine anderen SQL Methode sehen ähnlich aus und wären dann vermutlich nicht optimal, hmm ...
 
habe ich das mit finally -> rs.close() und pst.close() nicht schon sichergestellt?
Jein. Man kann das mit finally machen, das war in Java 6 Standard (ging nicht anders). Der Code ist aber hässlich, weil Du überall finally-Blöcke brauchst, die allerdings etwas anders aussehen müssten als Deiner. Wenn bei Dir z. B. eine Exception in prepareStatement aufritt, ist Dein ResultSet (normalerweise, ich sehe bei Dir gar keine Deklaration) null, was im finally-Block bei rs.close() zu einer NullPointerException führt. Seinerzeit habe ich (wie vermutlich viele andere auch) dafür Utility-Methoden geschrieben, die in etwa so aussahen:
Java:
public static void close(ResultSet rs, Statement stmt) {
    if (rs != null) {
        try { rs.close(); } catch (SQLException ex) { /* hier ggf. Warnung loggen. */ }
    }
    if (stmt != null) {
        try { stmt.close(); } catch (SQLException ex) { /* hier ggf. Warnung loggen. */ }
    }
}
Die Methode wure dann im finally-Block verwendet close(rs, stmt);. Seit Java 7 braucht man den ganzen Käse Dank try-with-resources nicht mehr.

Ok, das verstehe ich nicht ganz; muss man das so trennen?
Müssen muss man gar nichts... Im konkreten Fall sorgt die Trennung dafür, dass das SQL-Gedöns abgeschlossen ist, bevor irgend etwas anderes passiert. Wenn Du Dir jetzt den actionListener ansiehst, fällt Dir viel schneller auf, dass Du Events hin und her feuerst, weil der row-Index nicht abgeprüft wird :) (Du musst am Anfang noch prüfen, ob der row-Index 0 ist).
 
Oh man :( hatte eigentlich gedachte das wäre leichter :O
habe gerade mal deine Anpassung ausprobiert und bei mir kommen folgende Fehler:
Code:
try(pst = conn.prepareStatement(sql)){ // hier kommt bei mir "variables in try-with-resources not supported in -source 1.8"
try(rs = pst.executeQuery()){ // hier kommt "the try-with-resources resource must either be a variable declaration or an expression
denoting a reference to a final or effectively final variable"
 
Oh man :( hatte eigentlich gedachte das wäre leichter :O
habe gerade mal deine Anpassung ausprobiert und bei mir kommen folgende Fehler:
Code:
try(pst = conn.prepareStatement(sql)){ // hier kommt bei mir "variables in try-with-resources not supported in -source 1.8"
try(rs = pst.executeQuery()){ // hier kommt "the try-with-resources resource must either be a variable declaration or an expression
denoting a reference to a final or effectively final variable"
Stell deine IDE auf Java 8 und deklarier die Variablen dort, wo du sie auch initialisierst ;)
 
Ja, da fehlen die Deklarationen:
Java:
        try(PreparedStatement pst = conn.prepareStatement(sql)) {
            pst.setInt(1, row);
            try(ResultSet rs = pst.executeQuery()) {
 
Oh man :( hatte eigentlich gedachte das wäre leichter :O
Software hat das Problem, inhärent komplex zu sein. Als wäre das nicht genug, soll sich Software im Gegensatz zu anderen Gütern möglichst einfach an neue bzw. veränderte Anforderungen anpassen lassen. Um das in den Griff zu bekommen, haben sich über die Zeit verschiedene Herangehensweisen, Paradigmen, Pattern etc. herausgebildet. Und nach wie vor muss man feststellen, dass es kein Patentrezept gibt. Kurz: schnell, gut, kostengünstig - such Dir zwei aus.
 
Ja das ist leider richtig und es kann sehr frustrierend sein das anderen Menschen verständlich zu machen, die nur die Oberfläche sehen und sich denken das wäre so leicht :D

Also mit deinen Code habe ich es geschafft die Methode auf zwei zu trennen. Jedoch habe ich jetzt gerade ein anderes Problem:

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()){
            String label = rs.getString("LABEL");
            boolean infront = rs.getBoolean("VORNE");
            if(infront = false){
                titelvorn = label;
                titelhinten = "";
            }else{
                titelhinten = label;
                titelvorn = "";
            }
            }
        }
        }
  private void jComboBoxTitelblaActionPerformed(java.awt.event.ActionEvent evt) {
        int row = jComboBoxTitelbla.getSelectedIndex();
        try{
            loadTitel(row);
            Testpreview();
        }catch(SQLException e){
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, e);
            //return false; // wozu return false???
        }
}
wie man glaub unschwer erkennen kann soll die Variable titelvorn gesetzt werden wenn infront true ist und wenn es false ist soll titelhinten gesetzt werden. Leider zeigt er bei der if-Verzweigung alle Titel vorn an wenn ich if(infront = true)... schreibe und alle hinten wenn ich if(infront = false)... schreibe ... ist stehe etwas auf den Schlauch gerade, HÄÄÄ :'(
 
Oh man, ja das war dumm :D
hmm geht aber leider immer noch nicht; es zeigt nur eine Richung an, er belegt nur titelvorn (egal bei welchen Wert). Eigentlich müsste titelvorn zu mindest mal irgendwann leer sein.

Danke übrigens nochmal für eure Hilfe! :)
 
Hab noch ein Fehler entdeckt: Wenn ich auf das erste Item der ComboBox klicke kommt "java.sql.Exception: REsultSet closed"
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben