# SQLException: Lässt sich der Fehler feststellen?



## Grizzly (27. Jul 2005)

Ich habe eine PostgreSQL Datenbank und pflege Daten ein.

Jetzt kann mir u.U. an der Stelle, an der ich den Datensatz in die Datenbank speichere, eine SQLException geworfen werden. Das kann bspw. dadurch passieren, dass die Netzwerkverbindung streikt. Die Ausnahmen kann aber auch durch Verletzung der Unique Regel einer Spalte oder Verletzung ausgelöst werden.

Und in diesem Fall würde ich gerne eine entsprechende Meldung an den Benutzer ausgeben bzw. den entsprechenden Dialoge geöffnet lassen, so dass der Benutzer das entsprechende Feld anpassen kann. Ich habe schon versucht den PostgreSQL JDBC 2 Treiber mit _sqlexception.getErrorCode()_ auszuquetschen. Dort steht aber immer _0_ drin.

Mach ich etwas falsch? Gibt es eine andere Möglichkeit?


----------



## Guest (27. Jul 2005)

Grizzly hat gesagt.:
			
		

> Ich habe eine PostgreSQL Datenbank und pflege Daten ein.
> 
> Jetzt kann mir u.U. an der Stelle, an der ich den Datensatz in die Datenbank speichere, eine SQLException geworfen werden. Das kann bspw. dadurch passieren, dass die Netzwerkverbindung streikt. Die Ausnahmen kann aber auch durch Verletzung der Unique Regel einer Spalte oder Verletzung ausgelöst werden.
> 
> ...


Frage Dich zuerst, was es dem Anwender bringt, wenn Du einen Datenbankfehler in Klartext benennst?
Fehler wie "Verletzung der Unique Regel" sind Programmierfehler, die nicht auftreten sollten, wenn
Du alles korrekt machst. Das gleiche gilt für "required" Felder etc. Dies solltest Du schon früher prüfen,
also bevor Du die SQL-Statements absetzts. Ansonsten alle ungewöhnlichen Fehler mit z.B. Log4J loggen, 
um später die Ursachen rausfinden und beheben zu können.
"Leitung dicht" oder ähnliches, sind vielleicht die einzigen Ausnahmen. Prüfe bei den SQLExceptions mit 
sqlException.getCause(), was dahinter steckt.

SQLException sollte wirklich eine Ausnahme bleiben, wenn alles korrekt ist.


----------



## Grizzly (27. Jul 2005)

Wie soll ich prüfen ob es bspw. einen Kunden mit dem gleichen Namen nochmal gibt? Dann müsste ich vorher eine Transaktion starten, in dieser mit einem _SELECT_ prüfen, ob es einen gleichnamigen Kunden gibt und dann ggf. abbrechen. Bei einem Feld geht das ja noch. Sind bspw. jedoch meherere Felder jedoch _UNIQUE_, müsste ich erst alle durchprüfen. ???:L

Oder an was dachtest Du da? :bahnhof:


----------



## Guest (27. Jul 2005)

Genau so war es auch gemeint. Exceptions sind ja Ausnahmen, kein Mittel, 
um semantische Fehler abzufangen.

Wenn es um Batchbetrieb geht, dann wird die Sache komplizierter, kann aber
auch einfach gelöst werden. 

- temporäre Tabelle mit Kunden anlegen
- diese mit den Daten füllen
- alle aus der temprären Tabelle löschen, die bereits in der Haupttabelle vorhanden sind
- die übrigen in die Tabelle eintragen.

Das ganze in einer Transaktion, versteht sich.
Bei einzelnen Datensätzen ist es dann noch einfacher. Diese paar Abfragen davor
kosten ja kaum Zeit. Es ist eine Sache von paar Millisekunden.

Um es noch weiter zu führen... SQLExceptions haben clientseitig auch nichts zu suchen,
sollten bereits in der Persistenzschicht abgefangen und in entsprechende UserExceptions
mit mehr Informationsgehalt umgewandelt werden.
z.B. "Nachname darf nicht fehlen" etc. bei required Feldern oder "Benutzer existiert bereits"
bei unique Feldern und beim Client nachfragen, ob die Daten des bestehende Kunden
geladen werden sollen (oder sie gleich anzeigen).

Manchmal kann das Speichern auch die Bedeutung haben
"Speichern wenn noch nicht vorhanden, sonst Klappe halten und fortsetzen"

Denke immer an den Anwende bzw. welche Information ist für ihn überhaupt relevant 
sind und auf was hat er überhaupt Einfluss.


----------



## Guest (27. Jul 2005)

:autsch: Der letzte Satz sollte wie folgt lauten

Denke immer an den Anwende bzw. welche Information für ihn überhaupt relevant 
sind und auf was er überhaupt Einfluss hat.


----------



## Guest (27. Jul 2005)

OK, letzter Versuch. Ich sollte heute nichts mehr schreiben, sonst wird es 
peinlich. 

Denke immer an den Anwender bzw. welche Informationen für ihn überhaupt 
relevant sind und auf was er Einfluss hat.

--------------------------
Übrigens. Manche SQL Dialekte erlauben in ihrer Syntax solche Fälle
auszuschliessen.
z.B. in mySQL (aus dem Handbuch)

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;

Besser ist aber die SELECT-vor-UPDATE Lösung, da sie auf andere Datenbanksysteme
portierbar ist.


----------



## Grizzly (28. Jul 2005)

Hm, hm, hm, ... Ja, wahrscheinlich ist das die beste (und einzige? ???:L) Möglichkeit.
Schankedön.


----------



## Grizzly (28. Jul 2005)

Jetzt bin ich gerade nur auf ein Problem gestoßen: Ich kann ja gar nicht UNIQUE Spalten im Voraus feststellen, da ich die UNIQUE Spalten nicht bestimmen kann. Zumindest bietet ResultSetMetaData dazu keine Möglichkeit.


----------



## Guest (28. Jul 2005)

Du kennst aber den Tabellenaufbau.


----------



## Grizzly (28. Jul 2005)

Anonymous hat gesagt.:
			
		

> Du kennst aber den Tabellenaufbau.


Nicht, wenn ich das ganze in die ganze Datenbankzugriffe über eigene Klasse abstrahiere möchte und für mehrere Tabellen / Datenbanken verwende. Dann kennt die Klasse bzw. die Bibliothek den Aufbau nicht. Außer ich hinterlege den Aufbau nochmal in einer extra Datei oder setze die Unique Felder über eine entsprechende Methode der Klasse.

Alternativ könnte ich noch versuche die Datenbank per Datenbanksystem spezifischem SQL über den Aufbau auszuquetschen. Das müsste ich dann halt für jedes (R)DBMS extra implementieren (sprich einmal bspw. für PostgreSQL, einmal für MySQL, einmal für HSQLDB, usw.).


----------



## Guest (28. Jul 2005)

Baust Du ein Framework? 
Es gibt viele Fälle, die sich nicht so ohne weiteres aus den Metadaten 
einer Datenbank ermitteln lassen.
z.B. maximale Bestellmenge bestimmter Artikel etc.

Es gibt aber für solche Fälle zahlreiche Frameworks. Auch viele 
Rule Engines unterstützen so etwas.
Siehe: http://www.manageability.org/blog/stuff/rule_engines/view


----------

