SQLite Datenverlust nach beenden des Programmes

Jochim

Mitglied
Hallo,

ich arbeite nun seit einiger Zeit an einem Projekt rund um die Lagerhaltung. Bei einem Programm zum Ein-/Auslagern von Gütern werden die Produkte mittels eines RFID-Readers gescannt und anschließend kann die gewünschte Menge eingetragen werden.
Nun funktioniert alles soweit, die Güter werden eingelagert und in meiner Tabelle (Nach einem Update) angezeigt. Sobald ich das Programm schließe und neu starte, sind die Daten verloren. Auch wenn ich das Programm schließe und mir mittels eines SQLite Managers die DB anschaue, sind die Daten nicht vorhanden.

Java:
public void adddata(String table, String data[]){
        String sql="Insert into "+table+" values(?,?,?,?)";
        System.out.println("addata mit länge: "+data.length);
        try{
            pst=conn.prepareStatement(sql);
            pst.setString(1, data[0]);
            pst.setString(2, data[1]);
            pst.setString(3, data[2]);
            pst.setString(4, data[3]);
            pst.execute();
            System.out.println("Saved");
        }catch(Exception e){
            JOptionPane.showMessageDialog(null, e);
        }
    }

Gruß Jochim
 
prüf doch mal mit :

Java:
int result = pst.executeUpdate();
// Abfrage
if(result > 0){
// gespeichert
}else{
// fehler
}

ich kenn das nur mit
Code:
.executeUpdate();
 
prüf doch mal mit :

Java:
int result = pst.executeUpdate();
// Abfrage
if(result > 0){
// gespeichert
}else{
// fehler
}
Keine Veränderung, result ist > 0 und der Datensatz geht trotzdem verloren.

Ich würde auf einen fehlenden close tippen
Habe ein close angehängt aber es Funktioniert trotzdem nicht.

mach mal nach dem execute noch ein commit() obs daran liegt?
Wenn ich ein commit() mache wird mir die Meldung: java.sqlException: database in auto-commit mode, ausgegeben.

Gruß Jochim
 
Nun funktioniert alles soweit, die Güter werden eingelagert und in meiner Tabelle (Nach einem Update) angezeigt. Sobald ich das Programm schließe und neu starte, sind die Daten verloren. Auch wenn ich das Programm schließe und mir mittels eines SQLite Managers die DB anschaue, sind die Daten nicht vorhanden.
Heißt das, dass du während des Programmlaufs die neu angelegten Daten auch wieder liest und dass sie da vorhanden sind ?

Kann es sein, dass du irrtümlich mit einer In-Memory-Datenbank arbeitest ?
 
Heißt das, dass du während des Programmlaufs die neu angelegten Daten auch wieder liest und dass sie da vorhanden sind ?
Nachdem ich die Daten eingelagert habe, wird mir eine Übersicht des Lagers angezeigt. Und es Funktioniert auch, dass ich die Menge erhöhen kann bzw. wieder etwas auslagern kann.

Kann es sein, dass du irrtümlich mit einer In-Memory-Datenbank arbeitest ?
Von dieser Möglichkeit habe ich noch nichts gehört, gewollt ist dies zumindest nicht. Wie erkenne ich ob ich irrtümlich damit arbeite?
 
mach mal so:
Java:
public synchronized void addData(String table, String data[]){
   String sql = "INSERT INTO "+table+" VALUES(?,?,?,?)";
   try{
      pst = con.prepareStatement(sql);
      pst.setString(1, data[0]);
      pst.setString(2, data[1]);
      pst.setString(3, data[2]);
      pst.setString(4, data[3]);
   
/*-->>*/int rs = pst.executeUpdate(); // --> nicht exceute() verwenden!
      System.out.printl((rs > 0)? "gespeichert":"nicht gespeichert");
     pst.close();
   }catch(Exception e){
       e.printStackTrace();
   }
}

ich glaube da das mit dem
Code:
execute();
nicht ganz passt...

Code:
int executeUpdate()
Executes the SQL statement in this PreparedStatement object, which must be an SQL Data Manipulation Language (DML) statement, such as INSERT, UPDATE or DELETE; or an SQL statement that returns nothing, such as a DDL statement.
 
Zuletzt bearbeitet:
du hast es so gemacht wie ich es geschrieben habe mit synchronized und executeUptade()??
nicht falsch verstehen, speicherst du auch wirklich in die richtige DB oder table oder
brichst du die transaktion irgendwo ab, rollback(), close().....
 
Java:
public void adddatainventory(String data[]){
        String sql="Insert into inventory values(?,?,?,?)";
        System.out.println("addata mit länge: "+data.length);
        try{
            pst=conn.prepareStatement(sql);
            pst.setString(1, data[0]);
            pst.setString(2, data[1]);
            pst.setString(3, data[2]);
            pst.setString(4, data[3]);
           
            int result=pst.executeUpdate();
            System.out.println((result > 0)? "gespeichert":"nicht gespeichert");
            pst.close();
        }catch(Exception e){
            JOptionPane.showMessageDialog(null, e);
        }
    }

Das ist meine aktuelle Methode, anschließend aktualisiere ich die Tabelle mittels:
Java:
private void Update_table(){
        rs=dh.SelectTable("SELECT * FROM inventory");
        tbl_stock.setModel(DbUtils.resultSetToTableModel(rs));
        dh.close();
    }
Dort wird mir die Table mit den neuen Werten korrekt ausgegeben. Zu dem close: Meine Methoden zum zugriff auf die Datenbank stehen in einer anderen klasse, daher dh.close(), auch wenn ich diese Zeile auskommentiere Funktioniert es nicht
 
Nachdem ich die Daten eingelagert habe, wird mir eine Übersicht des Lagers angezeigt. Und es Funktioniert auch, dass ich die Menge erhöhen kann bzw. wieder etwas auslagern kann.
Nur noch einmal zur Sicherheit: Du liest die Werte auch aus der Datenbank aus und verwendest nicht einfach die Java Objekte weiter ?

Nachtrag: Das hast du gerade (als ich die Frage schrieb) beantwortet.

Von dieser Möglichkeit habe ich noch nichts gehört, gewollt ist dies zumindest nicht. Wie erkenne ich ob ich irrtümlich damit arbeite?
Zeig uns einmal wie du die Datenbank-Connection aufbaust.
 
Zeig uns einmal wie du die Datenbank-Connection aufbaust.

Dies ist meine Klasse JavaConnection:
Java:
public class JavaConnection {
    Connection conn=null;
    static String Laufwerk="G";
    public static Connection ConnecrDB(){
        try{
            Class.forName("org.sqlite.JDBC");
            Connection conn=DriverManager.getConnection("jdbc:sqlite:"+Laufwerk+":\\Warenwirtschaftsprogramm\\Warenwirtschaftssystem\\wawi.sqlite");
            return conn;
        }catch(Exception e){
            JOptionPane.showMessageDialog(null, e);
            return null;
        }
    }
}

und hiermit verbinde ich mich mit der DB:
Java:
conn=JavaConnection.ConnecrDB();
 
Das sieht für mich unverdächtig aus.

Wahrscheinlich bleibt dir nichts anderes übrig als das Beispiel zu weit wie möglich auf das Wesentliche zu reduzieren.
 
Ist es denn sinnvoll, die Methoden die auf die Datenbank zugreifen in eine extra Klasse zu schreiben? Weil wenn es keinen Sinn macht dann könnte ich dort mögliche Fehler ausschließen.
 
Ich verstehe das nicht ganz. ich möchte mal erklären wie es bei mir Aufgeteilt ist:
In meiner Main-Klasse befindet sich alles zum Frame und das nötige zum Umwandeln der Daten.
Mit der Klasse DataHandling greife ich auch die Datenbank zu. Beispiel:
Beim Update der Tabelle gibt mit die Klasse DataHandling ein ResultSet zurück, das ich anschließend in meiner JTable anzeige.
 
Ich habe nun einen Lösungsweg gefunden, ich mache zusätzlich ein conn.close() und bevor ich die Tabelle Update, Verbinde ich mich wieder mit der Datenbank. So funktioniert es nun, doch normalerweise ist das doch nicht nötig oder?
 
Man läßt eine Connection nur so lange offen, wie man sie braucht, danach schließt man sie wieder, d.h. nach einen Update, Insert, etc. macht man sie zu und beim nächsten Mal wieder vorher auf.
 
Man läßt eine Connection nur so lange offen, wie man sie braucht, danach schließt man sie wieder, d.h. nach einen Update, Insert, etc. macht man sie zu und beim nächsten Mal wieder vorher auf.

Für jedes Statement auf keinen Fall, nicht mal unbedingt zwingend für jede Transaktion. "so lange offen, wie man sie braucht", wie du ja selbst sagst, trifft es da viel besser. Das kann aber durchaus für die Dauer mehrerer Transaktionen mit zahlreichen abgesetzten Statements sein. Und selbst dann wird man sie anschließend in aller Regel nur logisch schließen, nicht aber physisch, soll heißen statt sie selbst zu schließen gibt man sie einfach in einen Pool von Connections zurück und überlasst es dem Pool, ob und wann er die Verbindung tatsächlich schließt. Ein physischer Verbindungsaufbau kostet jedenfalls viel Zeit.
 
Ja, ich meinte damit für sagen wir einen "Block" oder Workflow. Manchmal hat man ja wirklich nur 1 Update oder Insert beim Speichern einer Maske, manchmal sind es halt viele SQLs, bis man den Workflow durchlaufen hat. Aber danach schließt man und läßt die Connection nicht bis zum Sankt Nimmerleinstag offen.
 

Zurück
Oben