PDF, 1-spaltig, DIN A5 - Praktische Informatik

Werbung
JDBC
Udo Kelter
25.11.2016
Zusammenfassung dieses Lehrmoduls
JDBC (Java Database Connectivity) ist eine Schnittstelle, über
die von Java-Programmen aus auf die Inhalte relationaler Datenbanken zugegriffen werden kann. Dieses Lehrmodul stellt die wichtigsten
Funktionen vor. Insb. wird die Frage beantwortet, wie mit einer
typsicheren Sprache wie Java die Ergebnisse von Abfragen, deren Typ
man nicht statisch bestimmen kann, verarbeitet werden können.
Vorausgesetzte Lehrmodule:
obligatorisch:
– Einführung in SQL
Stoffumfang in Vorlesungsdoppelstunden: 1.0
1
JDBC
2
Inhaltsverzeichnis
1 Motivation
3
2 Aufbau einer Verbindung zum Datenbankserver
2.1 JDBC-Treiber laden . . . . . . . . . . . . . . . . . . . . . . .
2.2 Connection-Objekt erzeugen . . . . . . . . . . . . . . . . . . .
4
4
5
3 SQL-Statements
3.1 SQL-Statement-Objekte erzeugen . . . . . . . . . . . . . . . .
3.2 executeUpdate . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 executeQuery . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
6
7
4 ResultSets
4.1 ResultSet als lineare Liste . . . . . .
4.2 Cursors (Positionsmarken) . . . . . .
4.3 Positionierbare ResultSets . . . . . .
4.4 Auslesen eines Tupels . . . . . . . .
4.5 Automatisch aktualisierte ResultSets
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
8
9
10
5 Änderbare ResultSets
5.1 Motivation . . . . .
5.2 Ändern eines Tupels
5.3 Löschen von Tupeln
5.4 Einfügen von Tupeln
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
11
11
12
12
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6 Vorübersetzte Statements
12
7 Fehlerbehandlung
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
15
c
2016
Udo Kelter
Stand: 25.11.2016
Dieser Text darf für nichtkommerzielle Nutzungen als Ganzes und unverändert in elektronischer oder
gedruckter Form beliebig weitergegeben werden und in WWW-Seiten, CDs und Datenbanken aufgenommen werden. Jede andere Nutzung, insb. die Veränderung und Überführung in andere Formate, bedarf
der expliziten Genehmigung. Die jeweils aktuellste Version ist über http://kltr.de erreichbar.
JDBC
1
3
Motivation
Viele einfache ad-hoc-Abfragen zu einer bestehenden relationalen Datenbank können mit wenigen Abfragen über einen interaktiven Kommandointerpreter, den jedes DBMS-Produkt mitliefert, erledigt werden. Für komplexere Abfragen und erst recht umfängliche Änderungen von Daten in einer Datenbank ist eine derartige interaktive, also
manuelle Vorgehensweise nicht geeignet. Stattdessen sollte bzw. muß
von einem (laufenden) Programm aus auf die Datenbank zugegriffen
werden. Hierbei treten folgende Detailprobleme auf:
– Aufbau und Überwachung einer Verbindung zum Datenbankserver
– die Konversion von Daten in der Datenbank in den Laufzeitobjekten der jeweiligen Programmiersprache und umgekehrt. In der
Regel weisen die Typsysteme der Datenbank und der Programmiersprache erhebliche Unterschiede auf. Besonders schwierig ist speziell für Abfragen die Entwicklung einer Laufzeit-Datenstruktur, die
die zurückgelieferte (Ergebnis-) Relation implementieren kann.
– die Gestaltung geeigneter und leicht nutzbarer APIs für sämtliche
SQL-Kommandos
– die Fehlerbehandlung. Im Prinzip kann z.B. bei der üblichen
Prozeßarchitektur von DBMS-Laufzeitumgebungen jederzeit die
Verbindung zum DBMS-Serverprozeß gestört sein.
Fast alle vorstehenden Detailprobleme müssen spezifisch für die jeweilige Programmiersprache gelöst werden. Daher existieren für die
gängigen Programmiersprachen jeweils eigene Anbindungen, um von
Programmen in dieser Sprache auf eine relationale Datenbank zugreifen zu können. Man kann ganz grob zwei Arten von Anbindungen
unterscheiden:
– reine APIs bzw. Bibliotheken: die Bibliotheken werden zu dem
Programm, das eine Datenbank benutzt, nach dessen Kompilierung hinzugebunden. Die Funktionen der Bibliothek werden durch
manuell erstellte Aufrufe benutzt. Derartige APIs werden auch als
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
4
Treiber (driver) bezeichnet, in Analogie zum Anschluß von Plattenlaufwerken. Ein Entwickler hat hier viele Gestaltungsmöglichkeiten, muß sich aber auch um viele Details kümmern.
– Präprozessoren und automatisierte Konversionen: Die Konversion von Daten und andere Details werden hier durch einen Präprozessor automatisiert, der insb. die Datenstrukturen analysiert, die
persistent gemacht werden sollen, und entsprechende Tabellen definiert und API-Aufrufe generiert. Auf der einen Seite wird hier viele
manuelle Programmierung vermieden, andererseits muß man i.d.R.
zunächst ein komplexes Framework verstehen.
In diesem Lehrmodul stellen wir ein API für die Sprache Java vor,
JDBC. JDBC (Java Database Connectivity) ist “... the industry standard for database-independent connectivity between the Java
programming language and a wide range of SQL databases and other
tabular data sources, such as spreadsheets or flat files.”1
2
Aufbau einer Verbindung zum Datenbankserver
2.1
JDBC-Treiber laden
Ein Datenbankprodukt, das JDBC unterstützt, muß eine eigene Implementierung des APIs mitliefern. Dieser Treiber wird identifiziert
durch Paket- und Klassennamen, beispielsweise:
org.postgresql.Driver.
Der Treiber muß als erstes zum Benutzerprogramm hinzugebunden
und geladen werden, und zwar mit einem Kommando der Form
Class.forName(driver class);. Beispiel:
Class.forName("org.postgresql.Driver");
1
Quelle:
http://www.oracle.com/technetwork/java/javase/jdbc/index.html.
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
2.2
5
Connection-Objekt erzeugen
Damit das laufende Applikationsprogramm mit dem DBMS-Serverprozeß kommunizieren kann, muß eine Kommunikationsverbindung zwischen beiden Prozessen hergestellt werden. Zur Laufzeit werden solche Verbindungen durch Connection-Objekte repräsentiert. Deklariert wird eine derartiges Objekt wie folgt
Connection con = null;
Um die Verbindung tatsächlich aufzubauen, muß die Operation getConnection benutzt werden, die der DriverManager zur
Verfügung stellt. Muster:
con = DriverManager.getConnection(db, user, passw);
Die Parameter von getConnection sind wie folgt anzugeben:
db
Die Datenbank ist in folgender Syntax anzugeben:
protokoll://rechnername/dateipfad
Beispiel:
jdbc:postgresql://pi81.informatik.uni-siegen.de/dbs1
Dieses Beispiel zeigt, daß Protokolle aufeinander aufbauen
können. Oft wird z.B. ein Java-API auf Basis eines schon existierenden C-APIs implementiert.
user
Benutzername
passw Passwort
Wenn die Operation getConnection erfolgreich ausgeführt wurde,
kann anschließend auf die Datenbank zugegriffen werden.
3
3.1
SQL-Statements
SQL-Statement-Objekte erzeugen
Letztlich will man SQL-Kommandos ausführen. Hierzu müssen
zunächst Objekte erzeugt werden, die die SQL-Kommandos repräsentieren. Diese Objekte haben den vordefinierten Typ Statement. Hierbei sind mehrere Schritte zu trennen:
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
6
1. ein Statement-Objekt erzeugen und initialisieren
2. eine Anweisung eintragen
3. die enthaltene Anweisung ausführen (ggf. mehrfach)
Ein Statement-Objekt kann mit der Operation createStatement
erzeugt und initialisiert werden:
Statement stmt;
stmt = con.createStatement();
Im Zustand des Statement-Objekts ist vermerkt, zu welcher Verbindung es gehört. Daher braucht die Verbindung nicht mehr jedesmal
erneut angegeben zu werden.
Mit einem initialisierten Statement-Objekt können nun beliebige SQL-Kommandos durchgeführt werden. Im einfachsten Fall wird
das SQL-Kommando textuell als Argument übergeben und ausgeführt.
Wegen der unterschiedlichen Rückgaben sind hier zwei Fälle zu unterscheiden:
– Abfragen: Zurückgeliefert wird hier eine Tabelle. Dementsprechend
gibt es eine Operation zur Ausführung einer Abfrage, die eine Tabelle liefert (executeQuery).
– Alle anderen SQL-Kommandos: Diese sind mit der Operation
executeUpdate durchzuführen.
3.2
executeUpdate
executeUpdate ist für alle SQL-Kommandos zu benutzen, die eine Datenbank ändern (insb. create table, insert, delete, ...). Die
Syntax ist:
int executeUpdate(String sql)
Beispiel:
int num = stmt.executeUpdate("INSERT ...");
executeUpdate liefert einen Integer-Wert zurück, der bestimmte Informationen über das Ausführungsergebnis darstellt:
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
7
– ggf. die Zahl der eingefügten / gelöschten / geänderten Tupel
– 0 bei create table und u.ä. Kommandos
3.3
executeQuery
In JDBC ist eine Tabelle durch die Klasse ResultSet implementiert.
executeQuery liefert daher einen solchen ResultSet. Beispiel:
ResultSet result = stmt.executeQuery("SELECT...");
Es gibt mehrere Arten von ResultSets, die wir i.f. vorstellen.
4
4.1
ResultSets
ResultSet als lineare Liste
Eine Tabelle ist konzeptuell betrachtet eine Kollektion von Tupeln. Es
gibt unterschiedliche Methoden, Kollektionen zu implementieren. Die
einfachste Form ist eine lineare Liste, dies ist auch das Standardverhalten von executeQuery. D.h. das Java-Kommando
ResultSet result = stmt.executeQuery("SELECT...");
erzeugt eine lineare Liste (wozu der Name ResultSet nicht so ganz
paßt) von Tupeln (rows). Lineare Listen kann man jeweils nur sequentiell von vorne bis zum Ende durchlaufen. Die Klasse ResultSet
bietet hierzu die Operation next an. Beispiel:
while(result.next()) { verarbeite aktuelles Tupel }
4.2
Cursors (Positionsmarken)
Jeder ResultSet hat als Teil seines Zustands einen “Cursor”, also eine
aktuelle Position in der Liste. Gedanklich besteht die Menge der Cursorpositionen aus den Positionen zwischen zwei aufeinanderfolgenden
Tupeln und der Position vor dem ersten und nach dem letzten Tupel.
Bei n Tupeln im ResultSet gibt es also n + 1 Cursorpositionen; diese
sind von 0 bis n durchnumeriert.
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
8
Initial steht der Cursor vor dem ersten Tupel. Die Operation next
bezieht sich implizit auf den Cursor des ResultSets. Der Haupteffekt
von next besteht darin, den Cursor eine Position weiter zu verschieben.
“Aktuelles Tupel”. Für jede Cursorposition p > 0 ist ein aktuelles
Tupel definiert, und war das Tupel, das sozusagen zwischen den Cursorpositionen p − 1 und p steht. Die Tupel eines ResultSets sind auf
diese Weise von 1 bis n durchnumeriert.
Nur auf das aktuelle Tupel kann zugegriffen werden, hierauf gehen
wir später genauer ein.
4.3
Positionierbare ResultSets
Wenn man ein Abfrageergebnis nur unverändert ausgibt, reicht eine
lineare Liste völlig aus. Wenn man hingegen den ResultSet wiederholt durchsuchen muß oder einzelne Tupel z.B. anhand ihrer Positionsnummer direkt lokalisieren will, ist eine wiederholte lineare Suche
ineffizient.
Statt als lineare Liste können ResultSets daher als beliebig positionierbare (“scrollbare”) Kollektion erzeugt werden; hierzu ist
in der Operation createStatement das Argument ResultSet.
TYPE SCROLL INSENSITIVE anzugeben. Beispiel:
stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE);
result = stmt.executeQuery("SELECT...");
Für einen solchen positionierbaren ResultSet stehen diverse Positionierungsoperationen, und zwar2 :
– relative Veränderungen der aktuellen Cursorposition:
next(), previous(), relative(int)
2
Details s. JDBC-Tutorial, Abschnitt “Cursors” http://docs.oracle.com/javase
/tutorial/jdbc/basics/retrieving.html#cursors bzw. Spezifikation der Klasse ResultSet http://docs.oracle.com/javase/6/docs/api/java/sql/ResultSet.html.
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
9
– absolute Veränderungen:
first(), beforeFirst(), last(), afterLast(),
absolute(int)
Mit der Operation int getRow() kann die Nummer der aktuellen Cursorposition bestimmt werden. Mit absolute(int) kann man
später zu dieser Cursorposition zurückkehren.
4.4
Auslesen eines Tupels
Man steht beim Zugriff von Programmen auf Datenbanken vor dem
generellen Problem, daß die Typwelten, insb. die elementaren Datentypen und die Typkonstruktoren, nicht übereinstimmen.
Im Fall von Java ist hier zusätzlich relevant, daß Java grundsätzlich als typsichere Sprache gestaltet ist, d.h. der Typ von Objekten
kann bereits beim Compilieren bestimmt werden, was extreme softwaretechnische Vorteile bei der Identifikation von Fehlern bietet.
Im krassen Widerspruch dazu steht die geringe Typsicherheit von
SQL. Die Abfrage SELECT * FROM r liefert eine Tabelle eines Typs,
der erst zur Laufzeit bestimmt werden kann. Weiterhin sind diverse Detailinformationen über die Datentypen der Spalten einer Tabelle
aus den Abfragen nicht erkennbar. Beispielsweise kann der Compiler
bei einer Abfrage executeQuery("SELECT A FROM r") statisch nicht
wissen, welchen Typ die Spalte A hat. Noch weniger weiß der Compiler, wenn der String, der die Abfrage definiert, dynamisch erzeugt
wird und von vorherigen interaktiven Eingaben abhängt.
Daher muß letzten Endes ein Entwickler explizit angeben, welche
Typen die Spalten eines zurückgelieferten ResultSets haben. Technisch wird dieses Problem dadurch gelöst, daß die Attribute des aktuellen Tupels einzeln durch typspezifische Kopieroperationen gelesen
und z.B. auf Laufzeitvariablen übertragen werden. Die Operationsnamen dieser Kopieroperationen haben die Form getXXX, worin XXX
ein Typname ist, z.B. getInt, getString usw. Eigenschaften dieser
Operationen:
– Sie beziehen sich auf das aktuelle Tupel.
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
10
– Sie lesen den Wert eines Attributs des aktuellen Tupels.
– Sie liefern einen Wert vom Typ XXX zurück. Hierbei werden ggf.
Werte implizit konvertiert(!), was u.U. nicht beabsichtigt war.
Als Entwickler muß man also den Typ des Attributs kennen und die
passende get-Operation benutzen. Für alle get-Operationen existieren
jeweils zwei Varianten, wie das gewünschte Attribut identifiziert wird:
– getXXX(string): anhand des Namens
– getXXX(int): anhand der Position (1,...)
Beispiele:
name = result.getString("Vorname");
plz = result.getInt(5);
Alle get-Operationen sind in der Spezifikation der Klasse ResultSet http://docs.oracle.com/javase/6/docs/api/java/sql/ResultSet.html genauer
beschrieben.
4.5
Automatisch aktualisierte ResultSets
Wenn ein ResultSet nach den bisherigen Verfahren durch ein
executeQuery erzeugt wird, ist sein Inhalt eine Kopie der Daten aus
der DB zum Zeitpunkt der Abfrage. Wenn sich die Datenbank danach ändert, bleibt der ResultSet unverändert, d.h. der ResultSet gibt
ggf. den aktuellen Stand der Daten nicht mehr richtig wieder. In vielen Fällen ist es wünschenswert, daß der ResultSet sich automatisch
an Änderungen in der Datenbank anpaßt. Die Lösung dieses Problems sind “sensitive” ResultSets, die mit dem Argument ResultSet.
TYPE SCROLL SENSITIVE in der Operation createStatement erzeugt
werden. Beispiel:
stmt = con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE);
result = stmt.executeQuery("SELECT...");
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
5
11
Änderbare ResultSets
5.1
Motivation
Die bisher eingeführten ResultSets waren unveränderlich, es sind nur
lesende Operationen erlaubt. Oft wäre es aber praktisch, einen ResultSet zu durchlaufen und dabei bestimmte Attribute einzelner oder aller
Tupel sofort nach dem Lesen zu verändern. Theoretisch kann man für
jede einzelne Änderung ein update-Kommando mit executeUpdate
durchführen. Dies wäre allerdings sehr umständlich und ineffizient.
Eine elegantere Lösung sind änderbare ResultSets3 . Um einen
änderbaren ResultSet zu erzeugen, ist die Operation createStatement
mit dem Argument ResultSet.CONCUR UPDATABLE aufzurufen. Beispiel:
stmt = con.createStatement(
ResultSet.CONCUR_UPDATABLE);
result = stmt.executeQuery("SELECT...");
5.2
Ändern eines Tupels
In einem änderbaren ResultSet können die Attribute des aktuellen Tupels mit updateXXX-Operationen verändert werden, z.B. updateInt,
updateString usw. Diese sind analog zu den getXXX-Operationen konzipiert. Eigenschaften der updateXXX- Operationen:
– Sie beziehen sich implizit auf das aktuelle Tupel.
– XXX ist ein Typname.
– Der 1. Parameter ist der Name (Typ: string) oder die Nummer
(Typ: integer) des gewünschten Attributs.
– Der 2. Parameter ist vom Typ XXX, er enthält den neuen Wert des
Attributs. Auch hier werden ggf. Werte implizit konvertiert, was
u.U. nicht beabsichtigt war.
– Der Rückgabewert ist void.
3
Nach einer Änderung ist der Begriff ResultSet eigentlich nicht mehr korrekt.
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
12
Beispiele:
result.updateString("Vorname", "Hans");
result.updateInt(5,57076);
Alle update-Operationen sind in der Spezifikation der Klasse ResultSet beschrieben. Die Änderungen einzelner Attribute werden nicht
sofort in die Datenbank übertragen, sondern nur gesammelt pro Tupel
mit der Operation updateRow().
5.3
Löschen von Tupeln
Die Operation deleteRow() löscht das aktuelle Tupel im ResultSet
und in der Datenbank.
5.4
Einfügen von Tupeln
Das Einfügen von Tupeln in einen ResultSet wird durch eine spezielle zusätzliche Cursorposition und ein zugehöriges virtuelles “EinfügeTupel” (“insert row”) unterstützt. Zunächst muß man mit der Operation moveToInsertRow() den Cursor auf das Einfüge-Tupel setzen:
result.moveToInsertRow();
Danach kann man mit den update-Operationen Attribute dieses Tupels ändern. Wenn man damit fertig ist, fügt man mit der Operation
insertRow() das neue Tupel in den ResultSet und in die Datenbank
ein:
result.insertRow();
Danach kann man mit der Operation moveToCurrentRow() den Cursor wieder an die Stelle zurücksetzen, den er vor Ausführung des
moveToInsertRow() hatte.
6
Vorübersetzte Statements
Wenn man viele Daten ändert, sind änderbare ResultSets i.d.R. die
beste Methode. Änderbare ResultSets werden aber nicht von allen Systemen unterstützt, dann bleibt nichts anderes übrig als mit einzelnen
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
13
Änderungskommandos zu arbeiten. Dies ist relativ rechenaufwendig,
weil bei der Übersetzung des Kommandotextes jedesmal erneut alle
üblichen Prüfungen auf korrekte Syntax, Vorhandensein der Bezeichner usw. durchgeführt werden müssen.
Dieser Aufwand ist vermeidbar, wenn immer wieder fast das gleiche
SQL-Kommando ausgeführt wird, und zwar mithilfe vorübersetzter
Statements (Prepared Statements). Ein vorübersetzbares Statement ist ein Kommando-Text, der an den Stellen, wo ein Eingabeparameter (ein Bezeichner oder eine Konstante) erwartet wird, ein Fragezeichen enthält. Man kann dies auch als eine Funktionsdeklaration
betrachten, jedes Fragezeichen steht für einen Parameter. Beispiel:
String insertcmd = "INSERT INTO lieferungen "
+ "(Kundennummer, Lieferadresse, Betrag, Datum) "
+ "VALUES ( ?, ?, ?, 31.12.2016 )";
In diesem Beispiel wird die Eintragung mehrerer Lieferungen am
31.12.2016 in die Relation lieferungen vorbereitet.
Vorübersetztende Statements werden in 3 Phasen definiert und ausgeführt:
1. Der vorzuübersetzende Text wird mit der Operation
prepareStatement übersetzt, zurückgeliefert wird ein Objekt
vom Typ PreparedStatement. Beispiel:
PreparedStatement psInsertLfg;
psInsertLfg = con.prepareStatement(insertcmd);
2. Die offenen Stellen, sozusagen die Parameter des PreparedStatements, werden gefüllt, s.u.
3. Nach Setzen der Werte aller Parameter wird das vervollständigte
PreparedStatement mit der Operation executeUpdate ausgeführt.
Beispiel:
psInsertLfg.executeUpdate();
Setzen der Parameter eines PreparedStatements. Hierzu
dienen setXXX-Kommandos, die für Objekte des Typs Preparedc
2016
Udo Kelter
Stand: 25.11.2016
JDBC
14
Statement definiert sind. Analog wie bei den getXXX-Kommandos
steht XXX auch hier wieder für einen elementaren Datentyp. Die
setXXX-Kommandos haben 2 Parameter:
1. die Nummer des offenen Eingabeparameters
2. den zu benutzenden Wert, der vom Typ XXX sein muß
Beispiele:
psInsertLfg.setInt
(1, 181917);
psInsertLfg.setString (2, "Bahnhofstr. 55");
Weitere Details s.
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
7
.
Fehlerbehandlung
Wie schon früher erwähnt sind bei jedem Datenbankzugriff prinzipiell
immer Fehler möglich, z.B. Syntaxfehler oder der Verlust der Verbindung zum DBMS-Serverprozeß. Alle Datenbankzugriffe müssen daher selbst bei ersten Übungsaufgaben in try/catch-Blöcken gekapselt
werden. Eine detaillierte Behandlung aller Fehlerursachen ist relativ aufwendig und kann ggf. Teile der Applikationslogik beinhalten.
Bei ersten Übungen kann man auf eine detaillierte Fehlerbehandlung
zunächst verzichten.
Alle SQL-Zugriffsoperationen werfen Exceptions vom Typ
SQLException. Über diese exception-Objekte können diverse Informationen über die Art des Fehlers herausgefunden werden. Die Klasse
SQLException bietet hierzu folgende Operationen an:
getMessage() liefert eine verbale Beschreibung des Fehlers
getSQLState() liefert einen Fehlercode gemäß dem ANSI- bzw. ISOStandard
getErrorCode() liefert einen herstellerspezifischen Fehlercode, dessen
Bedeutung in der Produktdokumentation definiert sein muß.
Bei einen Datenbankzugriff können i.a. mehrere SQLExceptions
c
2016
Udo Kelter
Stand: 25.11.2016
JDBC
15
auftreten. Deren Abhängigkeitsstruktur kann mit Hilfe der Operation
getCause() abgefragt werden.
Warnungen. Neben Fehlern können Datenbankzugriffe auch Warnungen produzieren. Während ein Fehler die nicht erfolgreiche
Ausführung eines SQL-Kommandos anzeigt und ggf. zu einem Programmabbruch führt, treten Warnungen auch bei einer erfolgreichen
Ausführung des Kommandos auf. Beispielsweise kann bei einer Konversion von Datenwerten ein Rundungsfehler aufgetreten sein.
Warnungen müssen mit der Operation getWarnings abgerufen
werden. Diese Operation ist u.a. für die Klassen Connection,
Statement, PreparedStatement und ResultSet definiert, also bei allen Objekten aufrufbar, die Ergebnis von Datenbankzugriffen sind.
Analog zu Fehlern sind Informationen über die Warnung abrufbar,
und ein Datenbankzugriff kann mehrere Warnungen verursachen.
Weitergehende Informationen u.a. zum Auslesen der Liste der
SQLExceptions bzw. Warnungen s.
http://docs.oracle.com/javase/tutorial/jdbc/basics/sqlexception.html
c
2016
Udo Kelter
Stand: 25.11.2016
Herunterladen