# Doppelte Datensätze



## cam (26. Jan 2009)

Hallo,

ich habe eine wahrscheinlich blöde Frage...

Wenn man die Verbindung zur Datenbank nicht nach jeder Abfrage beendet, kann es dann passieren, dass Datensätze mehrfach in eine Tabelle geschrieben werden?

Es ist folgendes passiert:
Ich lagere einen Artikel ein - beim ersten Mal funktioniert alles wie es soll - es wird alles richtig in die Lagerplatz-Tabelle geschrieben und auch alles richtig in die Bestands-Tabelle. Wenn ich jetzt aber hintereinander den gleichen Artikel einlagere, ist zwar immer noch alles richtig in der Lagerplatz-Tabelle, aber in der Bestands-Tabelle tauchen die Datensätze plötzlich doppelt und dreifach auf.

Ich möchte nur wissen, ob es an den nicht-geschlossenen Verbindungen liegt, oder ob es auch einen anderen Fehler geben kann. (Bin dabei, den Code zu überarbeiten und hoffentlich zu verbessern.)


----------



## The_S (26. Jan 2009)

An der nicht geschlossenen Verbindung? Sehr unwahrscheinlich!


----------



## foobar (26. Jan 2009)

Die Verbindung sollte auf keinen Fall nach jeder Query geschlossen werden, das ist viel zu zeitintensiv.
Wenn du mit reinem Jdbc arbeitest solltest du aber immer darauf achten das Statement und Resultset im Finally-Block zu schliessen, sonst kann es zu einer Fehlermeldung im Dbms kommen wie "Too many open files".


----------



## Ebenius (26. Jan 2009)

foobar hat gesagt.:
			
		

> Die Verbindung sollte auf keinen Fall nach jeder Query geschlossen werden, das ist viel zu zeitintensiv.


Nur anbei erwähnt: Das hängt immer davon ab, wie oft die Verbindung benutzt wird. Und wenn man ConnectionPools verwendet, dann _sollte_ die (mehr oder weniger virtuelle) Verbindung auch geschlossen werden, wenn sie nicht mehr benötigt wird. Vorsichtig mit Pauschalurteilen; es gibt immer verschiedene Problemstellungen die verschiedene Herangehensweisen erfordern.


----------



## foobar (26. Jan 2009)

Ja, Ok ich bin jetzt von einer typischen Java SE Anwendung ausgegangen, da wird normalerweise kein Connectionpool verwendet.


----------



## cam (26. Jan 2009)

Hmhmhm, wie kann der Fehler dann passieren?
Wenn ich das Lagerprogramm beende und jedesmal neu starte, wenn ich etwas einlagern will, macht es alles richtig. Aber man soll ja auch hintereinander weg einlagern können. Ich habe jetzt die Variablen zurückgesetzt, aber nun hab ich eben quasi leere Datensätze in der Datenbank, das Problem ist also damit nicht behoben.


----------



## foobar (26. Jan 2009)

Da hilft nur ein Logger oder Debugger. Ohne Code können wir dir da auch net helfen.


----------



## maki (26. Jan 2009)

>> Hmhmhm, wie kann der Fehler dann passieren? 

Dafür gibt es viele, sehr viele Möglichekiten.

Bei denen von dir gelieferten Infos ganz klar: Da stimmt was nicht.

Woran erkennt deine Anwendung dass ein Datensatz schon existiert?


----------



## cam (26. Jan 2009)

Ich schicke euch mal einen Codeausschnitt - ich denke, hier liegt irgendwo der Fehler:


```
if(EinlagernM5.boxGr5 == "G0"){
						try{
							PreparedStatement stmG0 = (PreparedStatement) Frame.cn.prepareStatement("INSERT INTO bestand(best_id, eing_zeit, art_nr, art_id, reihe, spalte, ebene, fach, boxgroesse, prim_lapla, reserv, lief) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
							stmG0.setString(1, bestandID);
							stmG0.setTimestamp(2, new java.sql.Timestamp(new java.util.Date().getTime()));
							stmG0.setString(3, Frame.artikelNr);
							stmG0.setString(4, artikelID);
							stmG0.setString(5, Lagerplatz.reihe);
							stmG0.setString(6, Lagerplatz.spalte);
							stmG0.setString(7, Lagerplatz.ebene);
							stmG0.setString(8, Lagerplatz.fach1);
							stmG0.setString(9, EinlagernM5.boxGr5);
							stmG0.setString(10, primLapla);
							stmG0.setBoolean(11, false);
							stmG0.setString(12, Lieferant.lieferant);
							stmG0.execute();
							System.out.println("erledigtReihe1");															
						}catch(Exception ex){
							System.out.println("Keine Verbindung: " + ex);
						}
						try{
							PreparedStatement stmG0 = (PreparedStatement) Frame.cn.prepareStatement("INSERT INTO bestand(best_id, eing_zeit, art_nr, art_id, reihe, spalte, ebene, fach, boxgroesse, prim_lapla, reserv, lief) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
							stmG0.setString(1, bestandID);
							stmG0.setTimestamp(2, new java.sql.Timestamp(new java.util.Date().getTime()));
							stmG0.setString(3, Frame.artikelNr);
							stmG0.setString(4, artikelID);
							stmG0.setString(5, Lagerplatz.reihe);
							stmG0.setString(6, Lagerplatz.spalte);
							stmG0.setString(7, Lagerplatz.ebene);
							stmG0.setString(8, Lagerplatz.fach2);
							stmG0.setString(9, EinlagernM5.boxGr5);
							stmG0.setString(10, primLapla);
							stmG0.setBoolean(11, false);
							stmG0.setString(12, Lieferant.lieferant);
							stmG0.execute();
							System.out.println("erledigtReihe2");															
						}catch(Exception ex){
							System.out.println("Keine Verbindung: " + ex);
						}
						
						/**
						 * UPDATE la_platz
						 */
						
						try{
							PreparedStatement stmG0 = (PreparedStatement) Frame.cn.prepareStatement("UPDATE la_platz SET belegt = ?, best_id = ?, bel_g0 = ?, reserv = ? WHERE reihe = ? AND spalte = ? AND ebene = ? AND (fach = ? OR fach = ?)");
							stmG0.setBoolean(1, true);
							stmG0.setString(2, bestandID);
							stmG0.setBoolean(3, true);
							stmG0.setBoolean(4, false);
							stmG0.setString(5, Lagerplatz.reihe);
							stmG0.setString(6, Lagerplatz.spalte);
							stmG0.setString(7, Lagerplatz.ebene);
							stmG0.setString(8, Lagerplatz.fach1);
							stmG0.setString(9, Lagerplatz.fach2);
							stmG0.executeUpdate();
							System.out.println("erledigtUPDATEla_platz");															
						}catch(Exception ex){
							System.out.println("Keine Verbindung: " + ex);
						}
					}
```


----------



## foobar (26. Jan 2009)

Hier mal ein paar generelle Tipps:


```
if(EinlagernM5.boxGr5 == "G0"){
```
Strings vergleicht manmit equals

Warum benutzt du 2 mal die selbe Querie? Das solltest du besser in eine private Methode auslagern und die 2 mal mit unterschiedlichen Werten aufrufen.

Deine Preparedstatements werden nirgends geschlossen. Das ist sehr unschön.

Wenn man eine Exception fängt sollte man diese zumindest loggen siehe Log4J oder java.util.logging.


----------



## cam (26. Jan 2009)

Einige Artikel sind so groß, dass sie über 2 Fächer gelagert werden, G0 gehört dazu, daher 2 mal diese Query (fach1 und fach2).

Ich weiß, dass ich generell viel am Code verbessern muss, aber danke für die Hinweise   :wink:


----------



## foobar (26. Jan 2009)

> Ich weiß, dass ich generell viel am Code verbessern muss, aber danke für die Hinweise


Wenn du damit fertig bist, hast bestimmt auch deinen Fehler gefunden *gg*

Füg mal ein paar Traceausgaben ein und überprüf genau wann, wo, welche Query abgesetzt wird und was zu dem Zeitpunkt in der DB steht.


----------

