2017-07-02 16 views
2

Ich erstelle Paketmaschine Programm. Jedes Paket hat eine eindeutige Paket-ID, die in eine MySQL-Datenbank exportiert wird. Das Problem ist, dass jedes Mal, wenn ich das Programm starte, das Programm FlurID von 0 zählt. Ich suche nach einer Lösung, die es mir erlaubt, die letzte FlurstückID in der Datenbank zu überprüfen und Zeile nach der letzten zu erstellen.INSERT INTO eindeutiges Feld

Jetzt sieht es so aus: 1. Ich erstelle eine neue Zeile in db (erfolgreich) von Java-Programm. 2. Ich schließe das Programm nach einiger Zeit. 3. Ich führe das Programm erneut aus und kann keine weitere neue Zeile hinzufügen, weil der Fehler "Eintrag '1' für den Schlüssel 'PRIMARY'" doppelt vorhanden ist.

public static void post() throws Exception{ 

    int parcelID = Parcel.generateID(); 
    int clientMPNumber = Parcel.typeClientNumber(); 
    int orderPassword = Parcel.generatePass(); 

    try{ 
     Connection con = getConnection(); 
     PreparedStatement posted = con.prepareStatement("INSERT INTO Parcels.Orders (parcelID, clientMPNumber, orderPassword) VALUES ('"+parcelID+"', '"+clientMPNumber+"', '"+orderPassword+"')"); 

     posted.executeUpdate(); 
    } 
    catch(Exception e){ 
     System.out.println(e); 
    } 
    finally{ 
     System.out.println("Insert completed"); 
    } 
} 

und die Methode ist:

public static int generateID(){ 
    parcelID = parcelID + 1; 
    return parcelID; 
} 
+3

Btw .: Verwenden Sie 'prepareStatement()' und string concat nicht die Werte in Ihrer Abfrage trotzdem. Verwenden Sie 'prepareStatement()', um die "vorbereitete Anweisung" zu erstellen (das ist eine Abfrage mit "?" Als Platzhalter für Ihre Werte) und verwenden Sie 'setInt' und' setString', um diese Platzhalter zu füllen. – Progman

Antwort

1

ich lasse die Datenbank für Sie die schwere Arbeit tun - gerade definieren die parcelID Spalte als serial anstatt zu versuchen, seinen Wert selbst einstellen.

1

Sie sollten nicht Id Generation verwenden, nur auto_increment Spalte in Datenbanktabelle

1

Wie here beschrieben, definieren Sie Ihre Primärschlüsselspalte zu Autoinkrement für jeden erstellen einzufügen, damit Ihr Java-Code nicht manuell Primär berechnen Schlüsselwert jedes Mal.

Wenn das keine Möglichkeit ist, müssen Sie zeigen, wie Sie & initialisieren parcelID initiieren. Wie in Ihrem aktuellen Code scheint parcelID ein Feld auf Klassenebene zu sein, das für jeden Lauf auf Null initialisiert wird, sodass Sie immer den gleichen Wert erhalten - 1. Sie müssen mit dem letzten Wert aus der Datenbank initialisieren.

Auch implementieren Vorschlag wie in Kommentar zu Ihrer Frage erwähnt in Bezug auf PreparedStatement

1

Es gibt ein paar Dinge zu attent.

// parcelID should be an INT AUTOINCREMENT primary key. 
    try (PreparedStatement posted = con.prepareStatement(
      "INSERT INTO Parcels.Orders (clientMPNumber, orderPassword) " 
      + "VALUES (?, ?)", 
      Statement.RETURN_GENERATED_KEYS); 
     posted.setString(1, clientMPNumber); 
     posted.setString(2, orderPassword); 
     posted.executeUpdate(); 
     try (ResultSet rsKey = posted.getGeneratedKeys()) { 
      if (rsKey.next()) { 
       int parcelID = rsKey.getInt(1); 
       return parcelID; // Or such 
      }try-with-resources 
     } 
    } 

Die Datenbank kann mit einem automatischen Nummerierung am besten umgehen, so dass zwei Transaktionen zur gleichen Zeit nicht die gleiche „next“ Nummer stehlen.

Sie sollten schließen Dinge wie Connection, PreparedStatement und ResultSet. Dies kann am besten mit der etwas peinlichen Syntax von Try-with-Ressourcen erfolgen. Das schließt automatisch auch bei Ausnahme und Rückgabe.

PreparedStatements sollte mit Platzhaltern ? verwendet werden. Dies sorgt dafür, dass Sonderzeichen wie ' im Passwort nicht vorkommen. Außerdem verhindert SQL-Injektion.

Stilistisch bessere Verwendung SQLException oben Ausnahme. Besser vielleicht sogar ein throws SQLException.