Rechtliches

Bearbeiten

Java™ und JDBC™ sind Trademarks der Firma Sun Microsystems. Auch andere verwendete Soft- oder Hardwarenamen können, ohne besonders gekennzeichnet zu sein, eingetragene Markenbezeichnungen sein und sollen auch als solche betrachtet werden.

Einleitung

Bearbeiten

JDBC ist die Abkürzung für Java Database Connectivity. Die JDBC-API ermöglicht den Zugriff auf RDBMS (relationale Datenbankmanagementsysteme) mittels Java und SQL.

Die JDBC-API residiert in folgenden Packages:

  • java.sql
  • javax.sql (erweitert JDBC um Server-Side-Möglichkeiten)

Datenbanktreiber

Bearbeiten

RDBMS gibt es fast so viele wie Sandkörner am Strand. Jedes weist seine Besonderheiten auf und unterstützt verschiedene SQL-Versionen mit herstellerspezifischen Einschränkungen oder Erweiterungen.

Um nun die Möglichkeit zu schaffen diese Datenbanksysteme mittels eines einheitlichen Interfaces, nämlich der JDBC-API, ansprechen zu können, bedarf es noch mindestens einer Zwischenschicht. Diese Zwischenschicht oder zumindest einen Teil davon stellen die JDBC-Datenbanktreiber dar.

Typen von Datenbanktreibern

Bearbeiten
  • Typ 1: JDBC-ODBC-Bridge
  • Typ 2: Setzt auf einen herstellerspezifischen Treiber auf
  • Typ 3: JDBC-Netzwerktreiber
  • Typ 4: Nativer JDBC-Treiber

Wie diese Treibertypen genau funktionieren soll hier nicht weiter interessieren.

Prinzipiell kann aber folgendes gesagt werden: Je höher die Typnummer, desto besser und effizienter die Datenbankanbindung. Ein Typ 4-Treiber ist, falls für das jeweilige Datenbanksystem vorhanden, den anderen Treibertypen normalerweise vorzuziehen.

Ein JDBC-ODBC-Bridge-Treiber (= Typ 1-Treiber) ist in den aktuellen Java-Releases enthalten. Sun Microsystems weist aber ausdrücklich darauf hin, dass dieser nur für experimentelle Zwecke verwendet werden soll oder wenn keine anderen Treiber für die Datenbank verfügbar sind.

Sun Microsystems listet unter [1] viele verfügbare JDBC-Datenbanktreiber.

Einen Datenbanktreiber laden

Bearbeiten

Alle nachfolgenden Beispiele beziehen sich auf das RDBMS PostgreSQL 8.0 und den JDBC-Treiber "8.0-312 JDBC3". Dieser Typ 4-Treiber ist unter [2] als Datei "postgresql-8.0-312.jdbc3.jar" verfügbar. Diese JAR-Datei muss natürlich für ein funktionsfähiges Programm in den CLASSPATH eingebunden werden.

try
 {
   Class.forName("org.postgresql.Driver");
 }
 catch(ClassNotFoundException e)
 {
   // ...
 }

Der Klassenname ist treiberabhängig. Suns JDBC-ODBC-Bridge würde mittels sun.jdbc.odbc.JdbcOdbcDriver angesprochen. In der Regel finden Sie diesen in der Dokumentation zum entsprechenden Treiber des Datenbankherstellers.

Der Treibermanager

Bearbeiten

Bei fehlerfreier Abarbeitung des obigen Codefragmentes ist der Treiber nun beim Treibermanager (Klasse DriverManager) angemeldet.

Folgendes Programmstück schreibt die Aktivitäten des Treibermanagers und der Treiber in die Log-Datei test.log.

try
 {
   DriverManager.setLogWriter(new PrintWriter(new File("test.log")));	
   Class.forName("org.postgresql.Driver");
 }
 catch(ClassNotFoundException e)
 {
   // ...
 }  
 catch(FileNotFoundException e)
 {
   // ...
 }

Alternativ zur forName-Methode kann ein Datenbanktreiber auch so geladen werden

try
 {
   Driver driver = new org.postgresql.Driver();
   DriverManager.registerDriver(driver);
 }
 catch(SQLException e)
 {
   // ...
 }

Auch die Verbindung zu einer konkreten Datenbank wird durch den Treibermanager hergestellt. Dazu mehr im nächsten Abschnitt.

Datenbankverbindung

Bearbeiten

Wir wollen nun eine Verbindung mit der PostgreSQL-Datenbank testdb herstellen. Die Datenbank ist am lokalen Rechner (localhost) abgelegt und es wird der Standardport 5432 verwendet. Der Datenbankbenutzer soll user mit dem Passwort password sein.

try
 {
   Class.forName("org.postgresql.Driver");
   Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", "user", "password");
   conn.close();
 }
 catch(ClassNotFoundException e)
 {
   // ...
 }
 catch(SQLException e)
 {
   // ...
 }

Die getConnection()-Methode der Klasse DriverManager gibt es mit verschiedenen Signaturen. Der erste Parameter ist immer erforderlich. Dabei handelt es sich um die sogenannte URL (Uniform Ressource Locator) der Datenbank. Diese URL beginnt immer mit jdbc:, dann folgt die Datenbankprotokoll-/Treiberidentifikation und abschließend noch die Angabe der Datenquelle. Die genaue Syntax dieser URL ist treiberabhängig. Im Anwendungsfall also immer das maßgebliche RDBMS-Handbuch und/oder die Treiberdokumentation konsultieren.

Die Verbindung zur Datenbank kann mittels close() wieder geschlossen werden.

Datenbankabfragen

Bearbeiten

Beispieldatenbank

Bearbeiten

Die Datenbank testdb enthalte eine Tabelle (Relation) leute mit der Tabellenstruktur

Spaltenbezeichnung SQL-Datentyp PostgreSQL-Datentyp Anmerkung
id INTEGER INTEGER PRIMARY KEY
vorname VARCHAR(15) VARCHAR(15)
nachname TEXT
geburtsdatum DATE DATE

und dem Inhalt

id vorname nachname geburtsdatum
1 Hansi Hubsi 1999-12-01
2 Willy Wupp 1964-02-22
3 Struppi Strupp 2001-03-27
4 Milly Miker 1948-11-08

Statement und ResultSet

Bearbeiten

Alle JDBC-Datenbankabfragen setzen auf Statement-Interfaces auf.

Statement

Bearbeiten

Die Schnittstelle Statement kann für alle einfachen SQL-Abfragen verwendet werden.

try
{
  Class.forName("org.postgresql.Driver");
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", "user", "password");
  Statement statement = conn.createStatement();	
  statement.close();
  conn.close();	
}
catch(ClassNotFoundException e)
{
  // ...
}
catch(SQLException e)
{
  // ...
}

ResultSet

Bearbeiten

Damit man an die Daten in der Datenbank herankommt, führt man die Statement-Methode executeQuery() aus. Diese Methode retourniert eine ResultSet-Instanz mit den angeforderten Daten.

try
{
  Class.forName("org.postgresql.Driver");
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", "user", "password");
  Statement statement = conn.createStatement();			
  ResultSet rset = statement.executeQuery("SELECT * FROM leute;");
  rset.close();
  statement.close();
  conn.close();
}
catch(ClassNotFoundException e)
{
  // ...
}   
catch(SQLException e)
{
  // ...
}

Hinweise

Bearbeiten
  • Pro Statement-Instanz kann jeweils nur eine ResultSet-Instanz existieren.
  • Der übergebene SQL-String muss natürlich SQL-konform, sinnvoll und korrekt sein. Übergibt man Datenmüll, so bekommt man auch nur Fehlermeldungen oder Unsinn zurück.
  • Gefährlich: Man muss keinen SELECT-String übergeben. Man kann z.B. auch einen INSERT-String übergeben. Man erhält dann zwar eine Fehlermeldung, der Datensatz wurde aber trotzdem eingefügt.

Daten aus ResultSet herausholen

Bearbeiten

In der ResultSet-Instanz sind nun die vom Datenbanksystem als Reaktion auf unsere Anfrage zurückgegebenen Daten gespeichert.

Die einzelnen Tupel kann man mit der ResultSet-Methode next() durchlaufen. Damit der Datensatzcursor auf das erste Tupel zeigt, muss next() einmal aufgerufen werden.

Um an die einzelnen Datenwerte des Tupels heranzukommen, liefert ResultSet verschiedene getter-Methoden (hier nur auszugsweise dargestellt):

int getInt(int columnIndex)
int getInt(String columnName)
String getString(int columnIndex)
String getString(String columnName)
Date getDate(int columnIndex)
Date getDate(String columnName)

Die Identifikation der gewünschten Spalte erfolgt mittels Index oder direkt durch Angabe der Spaltenbezeichnung. Bei Angabe der Spaltennummer ist zu beachten, dass der Index bei 1 beginnt (Spalte1 = 1). Weiters kann man durch die SQL-Abfrage die Tabellenspalten durcheinanderwürfeln. Das muss bei der Indexmethode zusätzlich berücksichtigt werden.

try
{
  Class.forName("org.postgresql.Driver");
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", "user", "password");
  Statement statement = conn.createStatement();			
  ResultSet rset = statement.executeQuery("SELECT * FROM leute;");

  while(rset.next())
  {
    System.out.println(rset.getInt("id") + "\t" + rset.getString("vorname") + "\t" +
              rset.getString("nachname") + "\t" + rset.getDate(4));
  }
  rset.close();
  statement.close();
  conn.close();
}
catch(ClassNotFoundException e)
{
  // ...
}   
catch(SQLException e)
{
  // ...
}

liefert wie erwartet als Ergebnis

1  Hansi     Hubsi    1999-12-01
2  Willy     Wupp     1964-02-22
3  Struppi   Strupp   2001-03-27
4  Milly     Miker    1948-11-08

NULL-Check

Bearbeiten
  • Bei getXXX()-Methoden, die als Ergebnis ein Objekt zurückliefern, kann man einen NULL-Wert durch den Rückgabewert null erkennen.
  • Ansonsten erfolgt die Überprüfung eines Datenwertes auf NULL mit der wasNull()-Methode
try
{
  Class.forName("org.postgresql.Driver");
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", "user", "password");
  Statement statement = conn.createStatement();
  ResultSet rs = statement.executeQuery("SELECT * FROM leute;");
  rs.next();
  rs.getInt(1);
  System.out.println("Ist Datenwert NULL? " + rs.wasNull());
  rs.close();
  statement.close();
  conn.close(); 
}
catch(ClassNotFoundException e)
{
  // ...
} 
catch(SQLException e)
{
  // ... 
} 

liefert

Ist Datenwert NULL? false

Scrollable ResultSet

Bearbeiten

(ab JDBC 2.0)

Eine komfortable Datensatznavigation ermöglichen folgende Connection-Methoden:

Statement createStatement(int resultSetType, int resultSetConcurrency);
Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability);

mit

resultSetType:

  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE

resultSetConcurrency:

  • ResultSet.CONCUR_READ_ONLY
  • ResultSet.CONCUR_UPDATABLE

resultSetHoldability:

  • ResultSet.HOLD_CURSORS_OVER_COMMIT
  • ResultSet.CLOSE_CURSORS_AT_COMMIT

Die genaue Bedeutung dieser Parameter soll hier nicht erläutert werden. Für ein scrollbares ResultSet ist der Parameter resultSetType auf ResultSet.TYPE_SCROLL_INSENSITIVE oder ResultSet.TYPE_SCROLL_SENSITIVE zu setzen.

Schon kann der Datensatzcursor fast beliebig positioniert werden:

next() Bewegt den Datensatzcursor zum nächsten Datensatz
previous() Bewegt den Datensatzcursor zum vorherigen Datensatz
first() Bewegt den Datensatzcursor zum ersten Datensatz
last() Bewegt den Datensatzcursor zum letzten Datensatz
afterLast() Bewegt den Datensatzcursor hinter den letzten Datensatz
beforeFirst() Bewegt den Datensatzcursor vor den ersten Datensatz
absolute(int n) Bewegt den Datensatzcursor auf den n-ten Datensatz
relative(int n) Bewegt den Datensatzcursor relativ zur momentanen Position
try
{
  Class.forName("org.postgresql.Driver");
    
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", "user", 
             "password");
     
  Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 
             ResultSet.CONCUR_UPDATABLE);
  ResultSet rs = statement.executeQuery("SELECT * FROM leute");
     
  // Erster Datensatz
  rs.next();
  System.out.println(rs.getInt("id") + "\t" + rs.getString("vorname") + "\t"
             + rs.getString("nachname") + "\t" + rs.getDate(4));
   // Letzter Datensatz
  rs.afterLast();
  rs.previous();
  System.out.println(rs.getInt("id") + "\t" + rs.getString("vorname") + "\t"
             + rs.getString("nachname") + "\t" + rs.getDate(4));
  // 2. Datensatz
  rs.absolute(2);
  System.out.println(rs.getInt("id") + "\t" + rs.getString("vorname") + "\t"
             + rs.getString("nachname") + "\t" + rs.getDate(4));
  // 1. Datensatz
  rs.relative(-1);
  System.out.println(rs.getInt("id") + "\t" + rs.getString("vorname") + "\t"
             + rs.getString("nachname") + "\t" + rs.getDate(4));
  // Letzter Datensatz
  rs.absolute(-1);
  System.out.println(rs.getInt("id") + "\t" + rs.getString("vorname") + "\t"
             + rs.getString("nachname") + "\t" + rs.getDate(4));
  System.out.println("Tuple = " + rs.getRow());
  rs.close();
  statement.close();
  conn.close();
}
catch(ClassNotFoundException e)
{
  System.out.println("Class Error");
}
catch(SQLException e)
{
  e.printStackTrace();
}

liefert

1    Hansi    Hubsi   1999-12-01
4    Milly    Miker   1948-11-08
2    Willy    Wupp    1964-02-22
1    Hansi    Hubsi   1999-12-01
4    Milly    Miker   1948-11-08
Tuple = 4

PreparedStatement

Bearbeiten

Will man SQL-Abfragen parametrisieren, dann ist die Schnittstelle PreparedStatement genau richtig. PreparedStatement ist ein Subinterface von Statement.

try {
  Class.forName("org.postgresql.Driver");
    
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", "user", "password");
  PreparedStatement statement = conn.prepareStatement(
             "SELECT * FROM leute WHERE vorname LIKE ?;", 
             ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
  statement.setString(1, "Milly");
  ResultSet rs = statement.executeQuery();
     
  while(rs.next()) {
    System.out.println(rs.getInt("id") + "\t" + rs.getString("vorname") + "\t"
             + rs.getString("nachname") + "\t" + rs.getDate(4));
  }  
   
  rs.close();
  statement.close();
  conn.close();
}
catch(ClassNotFoundException e){
  // ...
}
catch(SQLException e) {
  // ...
}


liefert

4    Milly    Miker    1948-11-08

Darüber hinaus speichert die Datenbank alle Prepared Statements (genauer gesagt den berechneten Execution Plan) um es bei nachfolgenden Ausführungen zu beschleunigen.

Datenbankmanipulation

Bearbeiten

JDBC-Datenbankmanipulationen setzen auf den bereits bekannten Statement-Interfaces auf.

executeUpdate()

Bearbeiten

Die Statement-Anweisung

int executeUpdate(String sql)

ist für die Ausführung von INSERT-, UPDATE-, DELETE- oder DDL-Anweisungen gedacht.

try
{
  Class.forName("org.postgresql.Driver");
    
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", 
           "user", "password");
  Statement statement = conn.createStatement();
              
  int result = statement.executeUpdate("INSERT INTO leute VALUES(5, 'Trude', 'Trudscherl', '2005-08-18');");
            
  System.out.println("Eingefügte Datensätze: " + result);
     
  statement.close();
  conn.close();
}
catch(ClassNotFoundException e)
{
  // ...
}
catch(SQLException e)
{
  // ...
}

Updateable ResultSet

Bearbeiten

Wir haben bereits die Realisierung scrollbarer ResultSets unter Zuhilfenahme der Connection- Methode

Statement createStatement(int resultSetType, int resultSetConcurrency)

kennengelernt.

Setzen wir darin den zweiten Parameter auf ResultSet.CONCUR_UPDATEABLE, so können wir auch auf diese Weise Datensätze einfügen, löschen oder einzelne Datenwerte ändern, wenn für die Tabelle ein Primärschlüssel vorhanden ist.

try
{
  Class.forName("org.postgresql.Driver");
    
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", 
          	  "user", "password");
     
  Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
         ResultSet.CONCUR_UPDATABLE);
     
  ResultSet rs = statement.executeQuery("SELECT * FROM leute;");
     
  // Den Nachnamen von Trude Trudscherl ändern
  rs.last();
  rs.updateString("nachname", "Tridscherl");
  rs.updateRow();
            
  rs.close();
  statement.close();
  conn.close();
}
catch(ClassNotFoundException e)
{
  // ...
}
catch(SQLException e)
{
  // ...
}

Datensätze kann man mit der ResultSet-Methode void insertRow() einfügen und mit void deleteRow() löschen.

Transaktionen

Bearbeiten

Auch Transaktionen lassen sich mit Hilfe der Connection-Methoden

void setAutoCommit(boolean autoCommit)
void commit()
void rollback()
void rollback(Savepoint savepoint)

nachbilden.

Standardmäßig arbeitet JDBC im AutoCommit-Modus.

Als Beispiel wollen wir nun einige Datensätze "in einem Rutsch" in die Tabelle leute einfügen. Die Betonung liegt auf dem Wörtchen "wollen".

try
{
  Class.forName("org.postgresql.Driver");
    
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", 
            "user", "password");
  conn.setAutoCommit(false);
     
  Statement statement = conn.createStatement();
     
  statement.executeUpdate("INSERT INTO leute VALUES(11, 'Andi', 'Handi', '1999-02-04')");
  statement.executeUpdate("INSERT INTO leute VALUES(12, 'Bandi', 'Handi', '1999-02-04')");
  statement.executeUpdate("INSERT INTO leute VALUES(13, 'Candi', 'Handi', '1999-02-04')");
  statement.executeUpdate("INSERT INTO leute VALUES(14, 'Dandi', 'Handi', '1999-02-04')");
  statement.executeUpdate("INSERT INTO leute VALUES(14, 'Eandi', 'Handi', '1999-02-04')");
  conn.commit();
  conn.setAutoCommit(true);
     
  statement.close();
  conn.close();      
}
catch(ClassNotFoundException e)
{
  // ...
}    
catch(SQLException e)
{
  // eventuell ein explizites Rollback durchführen. PostgreSQL führt 
  // automatisch intern ein Rollback durch wenn kein commit erfolgt.
}

Was geschieht bei der Ausführung dieses Codes? Die letzte INSERT-Anweisung verletzt die Bedingung für einen Primärschlüssel, somit wird eine SQLException geworfen. Die commit()-Anweisung wird nie aufgerufen. Allfällige Änderungen werden durch ein Rollback wieder rückgängig gemacht. Die Tabelle bleibt konsistent im ursprünglichen Zustand erhalten.

Alternativ können Transaktionen natürlich auch ohne die JDBC-Transaktionsmethoden komplett mittels SQL-Code übergeben werden.

statement.executeUpdate("BEGIN TRANSACTION");
statement.executeUpdate("INSERT INTO leute VALUES(11, 'Andi', 'Handi', '1999-02-04')");
// ... 
statement.executeUpdate("COMMIT");

Batch-Updates

Bearbeiten

(ab JDBC 2.0)

Sind viele Daten auf einmal zu manipulieren, so spielt die Effizienz des Übertragungsvorganges eine große Rolle. Batch-Updates sind dann den konventionellen execute-Methoden überlegen.

try
{
  Class.forName("org.postgresql.Driver");
    
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", 
             "user", "password");
  conn.setAutoCommit(false);
     
  Statement statement = conn.createStatement();
     
  statement.addBatch("INSERT INTO leute VALUES(11, 'Andi', 'Handi', '1999-02-04')");
  statement.addBatch("INSERT INTO leute VALUES(12, 'Bandi', 'Handi', '1999-02-04')");
  statement.addBatch("INSERT INTO leute VALUES(13, 'Candi', 'Handi', '1999-02-04')");
  statement.addBatch("INSERT INTO leute VALUES(14, 'Dandi', 'Handi', '1999-02-04')");
  statement.addBatch("INSERT INTO leute VALUES(15, 'Eandi', 'Handi', '1999-02-04')");
  statement.executeBatch();
     
  conn.commit();
  conn.setAutoCommit(true);
     
  statement.close();
  conn.close();      
}
catch(ClassNotFoundException e)
{
  // ...
}    
catch(SQLException e)
{
  // eventuell ein Rollback durchführen. PostgreSQL führt automatisch ein Rollback durch, wenn 
  // kein commit erfolgt       
}

Metadaten

Bearbeiten

Die Struktur der in einer Datenbank gespeicherten Daten wird durch die so genannten Metadaten repräsentiert.

Datenbank-Metadaten

Bearbeiten
try
{
  Class.forName("org.postgresql.Driver");
    
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", 
          "user", "password");
  DatabaseMetaData dbmd = conn.getMetaData();
     
  System.out.println("RDBMS = " + dbmd.getDatabaseProductName());
  System.out.println("Version = " + dbmd.getDatabaseProductVersion());
  System.out.println("Treiber = " + dbmd.getDriverName());
  System.out.println("Version = " + dbmd.getDriverVersion());
  System.out.println("Datenbank-URL = " + dbmd.getURL()); 
  // usw.    
          
  conn.close();      
}
catch(ClassNotFoundException e)
{
  // ...
}    
catch(SQLException e)
{
  // ...       
}    

liefert

RDBMS = PostgreSQL
Version = 8.0.3
Treiber = PostgreSQL Native Driver
Version = PostgreSQL 8.0 JDBC3 with SSL (build 312)
Datenbank-URL = jdbc:postgresql:testdb

Tabellen-Metadaten

Bearbeiten
try
{
  Class.forName("org.postgresql.Driver");
    
  Connection conn = DriverManager.getConnection("jdbc:postgresql:testdb", 
             "user", "password");
     
  Statement statement = conn.createStatement();
     
  ResultSet rs = statement.executeQuery("SELECT * FROM leute;");
  ResultSetMetaData rsmd = rs.getMetaData();
     
  System.out.println("Anzahl der Tabellenspalten = " + rsmd.getColumnCount());
  System.out.println("Spaltenname der Spalte 2 = " + rsmd.getColumnName(2));
  System.out.println("Typ der Spalte 2 = " + rsmd.getColumnType(2));
  // usw.
                       
  rs.close();
  statement.close();
  conn.close();      
}
catch(ClassNotFoundException e)
{
  // ...
}    
catch(SQLException e)
{
  // ...
}

liefert

Anzahl der Tabellenspalten = 4
Spaltenname der Spalte 2 = vorname
Typ der Spalte = 12

Ausblick

Bearbeiten

Im Rahmen dieses Konvoluts konnte das komplexe Thema JDBC nur an der Oberfläche angekratzt werden. Interessierte werden zwecks weiterführender Information auf die Java-API-, JDBC-API-Dokumentation und die Sun-Tutorials (in englischer Sprache) verwiesen. Die API-Dokumentationen und die Sun-JDBC-Tutorials können unter Oracle Java-Homepage gefunden werden.


Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String path = "C:/example.mdb";
String dsn = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=" + path + ";UID=admin";
accessConn = DriverManager.getConnection(dsn, "", "");
try {
   Class.forName("com.mysql.jdbc.Driver");
   Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/MySite?user=MyAccount&password=MyPassword");
   conn.close();
} catch(SQLException e) { e.printStackTrace(); }


import java.sql.*; 
import java.io.*; 
import oracle.jdbc.*; 
import oracle.sql.*; 

public class OracleDatabase {
  public static void main(String[] args) {
    try {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:MyDatabase", "MyAccount", "MyPassword"); 	
      conn.setAutoCommit(true);
      String sql = "SELECT sum(bytes) from dba_segments;";
      Statement stmt = conn.createStatement();
      stmt.execute(sql); 
      stmt.close();
      conn.close();   
    } catch(SQLException e) { e.printStackTrace(); }
  }
}