JDBC−Treiber

Werbung
JDBC−Treiber
•
•
Middleware−Spezialist OpenLink bietet universellen
Treiber für die meisten DBMS (inkl. PostgreSQL) und
ODBC−Datenquellen.
–
JDBC−Treiber kontaktiert Request Broker.
–
Request Broker vermittelt Zugriff zur Datenbank
Sun Microsystems bietet mit JDBC eine JDBC−ODBC−
Brücke für Zugriff auf ODBC−Datenquellen.
–
•
Treiber−Klasse: sun.jdbc.odbc.JdbcOdbcDriver
Weitere JDBC−Treiber:
–
http://industry.java.sun.com/products/jdbc/drivers
–
Web−Anwendung zur Treiberauswahl
Web−Anwendungen mit Java
401
Datenbankverbindung aufbauen
•
Connection con =
DriverManager.getConnection
("jdbc:postgresql://mark:5712/eshop",
"user", "password");
•
JDBC−URL identifiziert Datenbank.
–
•
•
Aufbau: jdbc:subprotocol:subname
Treibermanager übergibt JDBC−URL der Reihe nach
an registrierte Treiber.
–
Driver.acceptsURL(String url)
–
Liefert true, falls der Treiber das Subprotocol erkennt.
Beispiel: JDBC−ODBC−Bridge erkennt
jdbc:odbc:mydb;UID=me;PWD=secret
Web−Anwendungen mit Java
402
Connection
•
Ergebnis von DriverManager.getConnection()
ist eine Connection (oder eine SQLException).
•
Verbindung zur Datenbank
•
Connection ist teure Ressource:
–
Aufbau der Verbindung kostet viel Zeit.
–
Anzahl gleichzeitiger Verbindungen häufig beschränkt.
–
•
Voreinstellung bei PostgreSQL: max. 32 Verbindungen
Wichtigste Aufgaben:
–
Erzeugen von Statement−Objekten
–
Beschreibungen von Datenbank und DBMS erfragen
–
Transaktionen handhaben
Web−Anwendungen mit Java
403
Statement
•
Statement stmt = con.createStatement();
•
Wird immer aus bestehender Connection erzeugt
•
Ausführen einer SQL−Anweisung über die Connection.
•
Mehrere parallele Statements pro Connection möglich
•
SELECT−Anweisung ausführen:
–
•
ResultSet rs =
stmt.executeQuery("SELECT * FROM kunden");
Daten ändern:
–
int updates =
stmt.executeUpdate("DELETE FROM kunden ...");
Web−Anwendungen mit Java
404
ResultSet: Zeilendurchlauf
•
ResultSet rs =
stmt.executeQuery("SELECT * FROM kunden");
•
Ergebnis einer Selektionsanweisung: Tabelle
–
•
Wird aus Statement erzeugt.
ResultSet enthält einen Datensatz−Zeiger (Cursor)
zum Durchlauf der Tabelle.
–
Voreinstellung: sequentiell und lesend
–
JDBC 2: nichtsequentielle und aktualisierbare ResultSets
•
Zeiger steht initial vor der ersten Tabellenzeile.
•
ResultSet.next() positioniert zur nächsten Zeile.
–
Liefert false, falls bereits auf letzter Zeile
Web−Anwendungen mit Java
405
ResultSet: Attribute lesen
•
Spaltenwerte (Attribute) einer Zeile mit getXXX()−
Methoden lesen
•
Treiber konvertiert Daten, falls möglich
•
Beispiel: Lesen einer ganzen Zahl in Spalte »anzahl«:
–
•
Effizientere Methode, falls Spaltenindex bekannt:
–
•
int n = rs.getInt("anzahl");
int n = rs.getInt(4);
Spaltenindex zum Spaltennamen finden
–
int findColumn(String columnName)
–
Strategie: Spaltenindex einmalig ermitteln und merken,
Werte danach immer über den Index abrufen.
Web−Anwendungen mit Java
406
ResultSet: Attribute lesen
•
Zahlreiche weitere Methoden
–
getArray, getAsciiStream, getBigDecimal,
getBinaryStream, getBlob, getBoolean,
getByte, getBytes, getCharacterStream,
getClob, getDate, getDouble, getFloat,
getInt, getLong, getObject, getRef,
getShort, getString, getTime, getTimestamp
Web−Anwendungen mit Java
407
ResultSet: Attribute lesen
•
•
Methode getObject
–
Liest jeden beliebigen SQL−Datentyp
–
Liefert Ergebnis als entsprechenden Java−Typ
Nullwerte
Temperaturen
Datum Temperatur
24.12.2001
2
25.12.2001
0
26.12.2001
27.12.2001
−2
–
Spalte kann leere Zellen
enthalten (Nullwert, SQL−NULL).
–
Bei leerer Zelle liefert getInt()
ebenfalls das Ergebnis 0.
–
Unterscheidung zu echter 0 möglich durch wasNull()
–
true, falls zuletzt mit getXXX() gelesene Zelle
SQL−NULL enthielt
–
false sonst
Web−Anwendungen mit Java
408
ResultSet: Ressourcen freigeben
•
Nach Bearbeitung ResultSet schließen
–
void close()
–
Gibt Ressourcen frei
–
Ausführen einer weiteren Anweisung mit demselben
Statement schließt das ResultSet implizit.
Web−Anwendungen mit Java
409
ResultSet: positionieren und ändern
•
Statement createStatement(int
resultSetType, int resultSetConcurrency)
–
Parameter (ResultSet−Konstanten) ermöglichen
beliebiges Positionieren (»Scrolling«) und Ändern der
Datensätze.
–
TYPE_FORWARD_ONLY: sequentieller Durchlauf
–
TYPE_SCROLL_INSENSITIVE: positionierbar,
Änderungen an Datenbank werden nicht bemerkt.
–
TYPE_SCROLL_SENSITIVE: positionierbar, Änderungen
an Datenbank werden bemerkt.
–
CONCUR_READ_ONLY: nur lesen
–
CONCUR_UPDATABLE: Änderungen möglich
Web−Anwendungen mit Java
410
ResultSet: positionieren
•
void beforeFirst()
–
•
boolean first()
–
•
Positioniert auf den ersten Satz.
boolean last()
–
•
Positioniert vor den ersten Satz.
Positioniert auf den letzten Satz
void afterLast()
–
Positioniert hinter den letzten Satz.
Web−Anwendungen mit Java
411
ResultSet: positionieren
•
boolean absolute(int pos)
–
•
boolean relative(int rows)
–
•
Positioniert relativ zum aktuellen Satz vorwärts (rows
positiv) oder rückwärts (rows negativ).
boolean next()
–
•
Positioniert relativ zum Anfang (pos positiv) oder relativ
zum Ende (pos negativ).
Positioniert auf den nächsten Satz.
boolean previous()
–
Positioniert auf den vorigen Satz.
Web−Anwendungen mit Java
412
ResultSet: positionieren
•
int getRow()
–
•
boolean isBeforeFirst()
–
•
Liefert true, falls auf dem ersten Satz.
boolean isLast()
–
•
Liefert true, falls vor dem ersten Satz.
boolean isFirst()
–
•
Liefert aktuelle Satznummer.
Liefert true, falls auf dem letzten Satz.
boolean isAfterLast()
–
Liefert true, falls hinter dem letzten Satz.
Web−Anwendungen mit Java
413
ResultSet: Datensatz ändern
•
Methoden updateXXX() ändern Werte in aktueller
Zeile.
• rs.absolute(5);
rs.updateString("Name", "Klute");
rs.updateInt(2, 42);
rs.updateNull(3);
rs.updateRow();
•
void updateRow()
–
•
void cancelRowUpdates()
–
•
Schreibt geänderte Zeile in die Datenbank.
Macht Änderungen rückgängig − vor updateRow().
void deleteRow()
–
Löscht aktuelle Zeile aus ResultSet und Datenbank
Web−Anwendungen mit Java
414
ResultSet: Datensatz einfügen
•
Einfügezeile: im ResultSet, nicht in der Datenbank
• rs.moveToInsertRow();
rs.updateString("Name", "Klute");
rs.updateInt(2, 42);
rs.insertRow();
rs.moveToCurrentRow();
•
void moveToInsertRow()
–
•
void insertRow()
–
•
Positioniert auf die Einfügezeile
Schreibt Einfügezeile in ResultSet und Datenbank
void moveToCurrentRow()
–
Positioniert von der Einfügezeile auf die aktuelle
Zeile im ResultSet
Web−Anwendungen mit Java
415
ResultSet: Änderungen erkennen
•
Datenbank kann sich jederzeit ändern...
–
...durch andere Benutzer,
–
...durch eigene parallele Anweisungen.
•
Ziel: beim Lesen des ResultSets Änderungen
erkennen
•
Voraussetzung:
–
•
Statement mit ResultSet.TYPE_SCROLL_SENSITIVE
erzeugen.
Mehraufwand kostet Performance.
–
Implementationsabhängig
Web−Anwendungen mit Java
416
ResultSet: Änderungen erkennen
•
void refreshRow()
–
•
boolean rowDeleted()
–
•
Liefert true, falls aktuelle Zeile in der Datenbank
gelöscht wurde.
boolean rowInserted()
–
•
Liest aktuelle Zeile neu aus der Datenbank.
Liefert true, falls aktuelle Zeile »Einfügung hatte«.
boolean rowUpdated()
–
Liefert true, falls aktuelle Zeile in Datenbank geändert
wurde.
Web−Anwendungen mit Java
417
PostgreSQL und JDBC 2
•
Mit dem PostgreSQL beigegebenen JDBC−Treiber
ist nicht alles möglich, was JDBC 2 für ResultSets
vorsieht.
•
TYPE_FORWARD_ONLY: Ja
•
TYPE_SCROLL_INSENSITIVE: Ja
•
TYPE_SCROLL_SENSITIVE: Nein
•
CONCUR_READ_ONLY: Ja
•
CONCUR_UPDATABLE: Nein
Web−Anwendungen mit Java
418
Daten ändern mit UPDATE
•
SQL−Anweisung UPDATE ändert bestehende
Datensätze.
•
Viele Datensätze durch einen einzigen Befehl ändern
•
Daten ändern auch ohne modifizierbare ResultSets
•
Beispiele:
–
UPDATE artikel SET preis = 100;
–
UPDATE artikel SET preis = preis * 1.05
where id = 538;
–
UPDATE artikel SET preis = preis * 1.05
where preis < 1000;
Web−Anwendungen mit Java
419
Daten löschen mit DELETE
•
SQL−Anweisung DELETE löscht bestehende
Datensätze.
•
Viele Datensätze durch einen einzigen Befehl löschen
•
Daten löschen ohne modifizierbare ResultSets
•
Beispiele:
–
DELETE FROM artikel WHERE id = 538;
–
DELETE FROM artikel WHERE preis < 100;
–
DELETE FROM artikel WHERE NOT id IN
(artikel FROM bestellungen);
–
Löscht alle Artikel, die nie bestellt wurden
Web−Anwendungen mit Java
420
ResultSet: Treiberhinweise
•
void setFetchDirection(int direction)
–
Optimierungshinweis an den JDBC−Treiber: In welcher
Richtung liest die Anwendung das ResultSet?
–
FETCH_FORWARD, FETCH_REVERSE oder
FETCH_UNKNOWN
•
int getFetchDirection()
•
void setFetchSize(int rows)
•
–
JDBC−Treiber muß nicht alle Zeilen sofort aus der
Datenbank holen.
–
Optimierungshinweis an den JDBC−Treiber:
Wieviel Zeilen am Stück holen?
int getFetchSize()
Web−Anwendungen mit Java
421
ResultSet: Diverses
•
Statement getStatement()
–
•
int getType()
–
•
TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE
oder TYPE_SCROLL_SENSITIVE
int getConcurrency()
–
•
Statement, das dieses ResultSet erzeugt hat
CONCUR_READ_ONLY oder CONCUR_UPDATABLE
String getCursorName()
–
Zum Ändern oder Löschen der aktuellen Zeile
–
–
UPDATE table SET n = 42 WHERE CURRENT OF cursor
DELETE FROM table WHERE CURRENT OF cursor
Web−Anwendungen mit Java
422
ResultSet: Metadaten
•
Informationen über das ResultSet
•
public ResultSetMetaData getMetaData()
•
Anzahl der Spalten
•
Spaltentyp, −name und −titel
•
Kann man Spalte nur lesen oder auch schreiben?
•
Entsteht Spaltenwert durch automatische Numerierung
(Sequenz)?
•
Läßt sich Spalte in WHERE−Klausel verwenden?
•
Darf Spalte Nullwert enthalten?
•
usw.
Web−Anwendungen mit Java
423
Statement: Daten ändern
•
ResultSet executeQuery(String) führt
SELECT−Anweisung aus.
•
int Statement.executeUpdate(String) führt
INSERT−, UPDATE− oder DELETE−Anweisung aus.
•
–
Liefert Anzahl betroffener Zeilen (»Update count«).
–
Auch für sonstige Befehle (»CREATE ...«) geeignet.
boolean execute(String) führt beliebige SQL−
Anweisung aus.
–
Liefert true, falls Ergebnis ein ResultSet ist
⇒ ResultSet rs = stmt.getResultSet();
–
Liefert false, falls Ergebnis ein Update count ist
⇒ int count = stmt.getUpdateCount();
Web−Anwendungen mit Java
424
Statement: vorbereitete Anweisungen
•
Aufbau der Anweisung fest, Parameter wechseln
•
Beispiel
– PreparedStatement pstmt = con.prepareStatement
("INSERT INTO temperaturen VALUES (?, ?)");
pstmt.setString(1, "{d 2001−12−24}");
pstmt.setInt(2, 2);
pstmt.executeUpdate();
pstmt.setString(1, "{d 2001−12−25}");
pstmt.setInt(2, 0);
pstmt.executeUpdate();
pstmt.setString(1, "{d 2001−12−26}");
pstmt.setNull(2, Types.INTEGER);
pstmt.executeUpdate();
pstmt.setString(1, "{d 2001−12−27}");
pstmt.setInt(2, −2);
pstmt.executeUpdate();
•
Läßt sich auch für Queries nutzen.
Web−Anwendungen mit Java
425
Statement: Stapelverarbeitung
•
•
Mehrere SQL−Anweisungen in einem Rutsch
ausführen (optionale JDBC−Operation)
–
Schritt 1: Anweisungen sammeln
–
Schritt 2: Stapel ausführen
void clearBatch()
–
•
void addBatch(String sql)
–
•
Stapel löschen
SQL−Anweisung zum Stapel hinzufügen
int[] executeBatch()
–
Stapel ausführen
–
Ergebniscode pro Anweisung
Web−Anwendungen mit Java
426
DBMS−Metadaten
•
Connection−Methode
public DatabaseMetaData getMetadata()
•
Methoden liefern Informationen über das DBMS, SQL−
Features, JDBC−Treiber, Tabellen,
Datenbankprozeduren u.v.a.m.
•
Nicht jeder JDBC−Treiber unterstützt jede Methode
von DatabaseMetaData.
–
Richtig: SQLException
–
Falsch: Fehlende oder falsche Informationen
Web−Anwendungen mit Java
427
DBMS−Metadaten
•
•
int−Methoden: beschreiben technische
Einschränkungen
–
Maximale Anzahl von Spalten je Tabelle
–
Größte Länge einer SQL−Anweisung
–
usw.
boolean−Methoden: Fähigkeit verfügbar oder nicht.
–
•
Beispiele:
boolean supportsANSI92EntryLevelSQL()
boolean supportsANSI92FullSQL()
Ergebnisse häufig als ResultSet
–
Beispiel: unterstützte Datentypen mittels Servlet
anzeigen
Web−Anwendungen mit Java
428
Beispiel: DBMS−Metadaten anzeigen
Web−Anwendungen mit Java
429
Beispiel: DBMS−Metadaten anzeigen
Web−Anwendungen mit Java
430
Beispiel: DBMS−Metadaten anzeigen
package de.rainer_klute.jdbc;
import
import
import
import
java.io.*;
java.sql.*;
javax.servlet.*;
javax.servlet.http.*;
public class DBInfo extends HttpServlet
{
/**
* <p>Initializes the servlet by setting the
* jdbc.drivers system property from the
* "databaseDrivers" servlet context init
* parameter.</p>
*
* <p><strong>FIXME:</strong> The method should
* append only those driver class names that are not
* already in the "jdbc.drivers" property.</p>
*/
public void init(ServletConfig config)
throws ServletException
Web−Anwendungen mit Java
431
Beispiel: DBMS−Metadaten anzeigen
{
}
final String driverProp = "jdbc.drivers";
super.init(config);
StringBuffer newDrivers = new StringBuffer();
String oldDrivers =
System.getProperty(driverProp);
if (oldDrivers != null)
{
newDrivers.append(oldDrivers);
newDrivers.append(’:’);
}
String s;
if ((s = config.getServletContext().
getInitParameter
("databaseDrivers")) != null)
newDrivers.append(s);
System.setProperty
(driverProp, newDrivers.toString());
Web−Anwendungen mit Java
432
Beispiel: DBMS−Metadaten anzeigen
public void doGet(HttpServletRequest req,
HttpServletResponse resp)
{
PrintWriter out = null;
try
{
out = resp.getWriter();
doGetLocal(req, resp, out);
}
catch (SQLException ex)
{
out.println("<pre>");
ex.printStackTrace(out);
out.println("</pre>");
}
catch (IOException ex)
{
out.println("<pre>");
ex.printStackTrace(out);
out.println("</pre>");
}
}
Web−Anwendungen mit Java
433
Beispiel: DBMS−Metadaten anzeigen
private void doGetLocal(HttpServletRequest req,
HttpServletResponse resp,
PrintWriter p)
throws SQLException
{
// Parameter für Connection ermitteln:
ServletContext sc = getServletContext();
String url =
sc.getInitParameter("databaseURL");
String user =
sc.getInitParameter("databaseUser");
String password =
sc.getInitParameter("databasePassword");
// Datenbankverbindung aufbauen:
Connection con = DriverManager.getConnection
(url, user, password);
DatabaseMetaData dbmd = con.getMetaData();
Web−Anwendungen mit Java
434
Beispiel: DBMS−Metadaten anzeigen
p.println("<div>");
p.println("<p>Database system: " +
dbmd.getDatabaseProductName() +
" " +
dbmd.getDatabaseProductVersion() +
"</p>");
p.println("<p>JDBC driver: " +
dbmd.getDriverName() + " " +
dbmd.getDriverVersion() + "</p>");
ResultSet rs;
/* Schemas */
p.println("<p>Schemas:</p>");
rs = dbmd.getSchemas();
Util.printAsHTML(p, rs);
/* Catalogs */
p.println("<p>Catalogs:</p>");
rs = dbmd.getCatalogs();
Util.printAsHTML(p, rs);
Web−Anwendungen mit Java
435
Beispiel: DBMS−Metadaten anzeigen
/* TableTypes */
p.println("<p>Table types:</p>");
rs = dbmd.getTableTypes();
Util.printAsHTML(p, rs);
/* Tables */
p.println("<p>Tables:</p>");
rs = dbmd.getTables(null, null, null, null);
Util.printAsHTML(p, rs);
/* Data types */
p.println("<p>Data types supported by " +
"this database system:</p>");
rs = dbmd.getTypeInfo();
Util.printAsHTML(p, rs);
// Datenbankverbindung schließen:
con.close();
}
}
p.println("</div>");
Web−Anwendungen mit Java
436
Beispiel: Klasse Util
package de.rainer_klute.jdbc;
import java.io.*;
import java.sql.*;
import java.util.*;
/**
* <p>Contains static methods for dealing with JDBC
* objects.</p>
*
* @author Rainer Klute <klute@rainer−klute.de>
*/
public class Util
{
Web−Anwendungen mit Java
437
Beispiel: Klasse Util
/**
* <p>Prints the contents of a {@link ResultSet} to
* a {@link PrintWriter} as an HTML table with cell
* borders.</p>
*
* @param p The HTML table is rendered to this
* {@link PrintWriter}
* @param re The {@link ResultSet} to print
*
* @see #printAsHTML(PrintWriter, ResultSet, Map)
*/
public static void printAsHTML(PrintWriter p,
ResultSet rs)
throws SQLException
{
Map m = new HashMap(1);
m.put("border", "1");
printAsHTML(p, rs, m);
}
Web−Anwendungen mit Java
438
Beispiel: Klasse Util
/**
* <p>Prints the contents of a {@link ResultSet} to
* a {@link PrintWriter} as an HTML table.</p>
*
* @param p The HTML table is rendered to this
* {@link PrintWriter}
* @param re The {@link ResultSet} to print
* @param tableAttr Attributes to use for the
* HTML table
*
* @see #printAsHTML(PrintWriter, ResultSet)
*/
public static void printAsHTML(PrintWriter p,
ResultSet rs,
Map tableAttr)
throws SQLException
{
p.print("<table");
/* Print table attributes */
for (Iterator i = tableAttr.keySet().iterator();
i.hasNext();)
Web−Anwendungen mit Java
439
Beispiel: Klasse Util
{
String attr = (String) i.next();
p.print(’ ’);
p.print(attr);
p.print("=\"");
p.print((String) tableAttr.get(attr));
p.print(’\"’);
}
p.println(">");
/* Get number of columns */
ResultSetMetaData rsmd = rs.getMetaData();
int columns = rsmd.getColumnCount();
/* Get column names from metadata and print them
* to the first table row. */
p.print("<tr>");
for (int i = 1; i <= columns; i++)
p.print("<th><p>" + rsmd.getColumnName(i) +
"</p></th>");
p.println("</tr>");
Web−Anwendungen mit Java
440
Beispiel: Klasse Util
}
/* Print result set lines. */
while (rs.next())
{
p.print("<tr>");
for (int i = 1; i <= columns; i++)
{
/* Print cell contents. */
String s;
Object o;
if ((o = rs.getObject(i)) != null)
s = o.toString();
else
s = " ";
p.print("<td><p>" + s + "</p></td>");
}
p.println("</tr>");
}
p.println("</table>");
}
Web−Anwendungen mit Java
441
Transaktionen
•
Zusammengehörende Datenbankoperationen
–
•
Entweder alle ausführen oder keine
Beispiel: Überweisung
int amount = 100;
/* Transaktion einleiten. */
con.setAutoCommit(false);
fromAccount(con, 1, amount);
if (Math.random() > 0.5)
throw new RuntimeException("Crash");
toAccount(con, 2, amount);
/* Transaktion abschließen: Ergebnisse endgültig
* in Datenbank schreiben. */
con.commit();
con.setAutoCommit(true);
Web−Anwendungen mit Java
442
Transaktionen
/*
* <p>Lastschrift</p>
*/
private static void fromAccount
(Connection c, int account, int amount)
throws SQLException
{
/* Alten Kontostand holen. */
PreparedStatement s;
s = c.prepareStatement
("SELECT saldo FROM konten WHERE konto = ?");
s.setInt(1, account);
ResultSet rs = s.executeQuery();
rs.next();
int balance = rs.getInt(1);
/* Neuen Kontostand berechnen. */
balance −= amount;
Web−Anwendungen mit Java
443
Transaktionen
}
/* Neuen Kontostand in Datenbank speichern. */
s = c.prepareStatement
("UPDATE konten SET saldo = ? " +
"WHERE konto = ?");
s.setInt(1, balance);
s.setInt(2, account);
s.executeUpdate();
s.close();
/*
* <p>Gutschrift</p>
*/
private static void toAccount
(Connection c, int account, int amount)
throws SQLException
{
fromAccount(c, account, −amount);
}
Web−Anwendungen mit Java
444
Transaktionen
•
•
void setAutoCommit(boolean autoCommit)
–
true: Jede SQL−Anweisung ist separate Transaktion.
–
false: SQL−Anweisungen sind zu Transaktionen
gruppiert.
boolean getAutoCommit()
–
•
void commit()
–
•
Zustand erfragen
Transaktion abschließen: Änderungen endgültig in
Datenbank schreiben
void rollback()
–
Transaktion zurücksetzen: Änderungen verwerfen
Web−Anwendungen mit Java
445
Transaktionen voreinander schützen
•
•
void setTransactionIsolation(int level)
–
Legt fest, wie stark Transaktionen voneinander
abgeschottet sind.
–
Sind Änderungen während einer Transaktion T1 bereits
in einer Transaktion T2 sichtbar?
–
Daumenregel: geringe Abschottung = hoher Durchsatz
int getTransactionIsolation()
–
Aktuellen Wert abfragen
Web−Anwendungen mit Java
446
Transaktionen voreinander schützen
•
Schmutzlesen (»dirty read«):
–
•
Einmallesen (»non−repeatable read«)
–
•
T1 schreibt Satz, T2 liest Satz, T1 bricht ab
⇒ Satz ist »dirty«.
T1 liest Satz, T2 ändert Satz, T1 liest Satz noch einmal
⇒ Satz ist bei jedem Lesen anders.
Phantomlesen (»phantom read«)
–
T1 selektiert Relation mit Selektionsbedingung B, T2 fügt
Satz ein, der B erfüllt, T1 selektiert Relation mit B noch
einmal
⇒ Relation enthält zusätzlichen »Phantomsatz«.
Web−Anwendungen mit Java
447
Transaktionen voreinander schützen
•
TRANSACTION_READ_UNCOMMITTED
–
•
•
•
Erlaubt Schmutzlesen, Einmallesen und Phantomlesen
TRANSACTION_READ_COMMITTED
–
Verhindert Schmutzlesen
–
Erlaubt Einmallesen und Phantomlesen
TRANSACTION_REPEATABLE_READ
–
Verhindert Schmutzlesen und Einmallesen
–
Erlaubt Phantomlesen
TRANSACTION_SERIALIZABLE
–
Verhindert Schmutzlesen, Einmallesen und
Phantomlesen
Web−Anwendungen mit Java
448
Parallele SQL−Anweisungen
•
Datenbankoperationen benötigen viel Zeit
1
•
... datenbankunabhängige Aktivitäten erledigen
–
•
In separatem Thread ausführen und in der Wartezeit...
Benutzeroberfläche aktualisieren usw.
... weitere Datenbankoperation parallel ausführen
C
C
C
S
S
S
RS
RS
RS
RS
Web−Anwendungen mit Java
449
C
C
S
S
S
RS
RS
RS
Parallele Anweisungen: Varianten
•
•
Paralleles ResultSet erzeugen
–
Statement für weitere SQL−Anweisung nutzen
–
Nicht möglich, da Statement.execute() das
geöffnete ResultSet schließt
Paralleles Statement erzeugen
–
Connection für weiteres Statement nutzen
–
JDBC−Treiber synchronisiert, falls nötig
–
•
Güte der Synchronisierung abhängig von DBMS und Treiber
Parallele Connection erzeugen
Herunterladen