Wöhrmann Softwareentwicklung - Java Best Practices

JDBC - Java Database Connectivity

Die Java JDBC API definiert eine Vielzahl von Methoden, über die auf alle gängigen Datenbanken zugegriffen werden kann. Sie stellt eine transparente Zwischenschicht dar, um Inhalte von Datenbanken verschiedener Hersteller mit einheitlichen Aufrufen zu lesen und zu schreiben. Somit ist nicht nur ein schneller und unkomplizierter Wechsel von einer Datenbank zu einer anderen möglich, sondern es können auch Softwaresysteme entwickelt werden, die durch geschickte Parametrisierung den Zugriff auf verschiedene Datenbanksysteme erlauben.

Voraussetzungen

Zwar wird mit der JDBC API eine einheitliche Schnittstelle angeboten, jedoch werden die spezifischen Klassen jeweils von den Datenbankanbietern realisiert. Deshalb müssen diese Klassen, die in der Regel als .jar Dateien zur Verfügung stehen, zunächst einmal beschafft und dann zur Laufzeit über den Java CLASSPATH eingebunden werden. (s.a. Sun JDBC Resources)

Database Connections

Für jeden Zugriff auf eine Datenbank wird zunächst einmal eine Connection benötigt und an diese Connection gelangt man in der Regel über die Registrierung eines Treibers seiner datenbankspezifischen URL, einem User-Namen und dem zugehörigen Passwort:

import java.sql.*;

public class JdbcConExample
{ public static void main(String[] args) throws Exception
  { Class.forName("oracle.jdbc.driver.OracleDriver");
    String dbUrl = "jdbc:oracle:thin:@myHostName:1521:myDatabaseName";
    Connection con = DriverManager.getConnection(dbUrl, "scott", "tiger");
    try
    { // Exec Database calls ...
    }
    finally
    { con.close();
    }
  }
}
Vendor Driver-Class / Database-URL Driver-Lib
DB2 COM.ibm.db2.jdbc.net.DB2Driver
jdbc:db2://{host}[:{port}]/{dbname}
db2java.zip
Derby org.apache.derby.jdbc.EmbeddedDriver
bzw. org.apache.derby.jdbc.ClientDriver
jdbc:derby://server[:port]/databaseName[;URLAttributes=value[;...]]
derby.jar
HSQLDB org.hsqldb.jdbcDriver
jdbc:hsqldb[:{dbname}][:hsql://{host}[/{port}]]
hsqldb.jar
MS SQL-Server com.microsoft.jdbc.sqlserver.SQLServerDriver
jdbc:microsoft:sqlserver://{host}[:{port}][;DatabaseName={dbname}]
msbase.jar
mssqlserver.jar
msutil.jar
MySQL com.mysql.jdbc.Driver
jdbc:mysql://{host}[:{port}]/[{dbname}]
mysql-connector-java-5.1.5-bin.jar
Oracle oracle.jdbc.driver.OracleDriver
jdbc:oracle:thin:@{host}:{port}:{dbname}
classes12.zip
Postgre org.postgresql.Driver
jdbc:postgresql://[{host}[:{port}]]/{dbname}
pgdev.307.jdbc3.jar

Zufriffs Templates

Der Zugriff auf die Datenbanken folgt im Wesentlichen immer nach dem gleichen Schema. Wichtig in diesem Zusammenhang ist lediglich, peinlich darauf zu achten, dass geöffnete Ressourcen wie ResultSets und PreparedStatements nach ihrer Verwendung auf jeden Fall wieder geschlossen werden, denn sonst kann es zu unangenehmen Überraschungen wie beispielsweise Out-Of-Memory Fehlern kommen. Wichtig ist weiterhin, String-Werte in Select-Statements mit Hochkommas wie hier bei 'StringValue' zu begrenzen:

void selectTemplate() throws Exception
{ ResultSet rs = null;
  PreparedStatement ps = null;
  try
  { ps = con.prepareStatement("SELECT * from MyDB");
    rs = ps.executeQuery();
    while (rs.next())
    { String content = rs.getString("fieldName");
      // ...
    }
  }
  finally
  { if (rs  != null) 
      try { rs.close();  } 
      catch (Exception ex) { /* ex.printStackTrace(); */ }
    if (ps  != null) 
      try { ps.close();  } 
      catch (Exception ex) { /* ex.printStackTrace(); */ }
  }
}
int insertTemplate() throws Exception
{ PreparedStatement ps = null;
  try
  { Sting stmt =
    "INSERT INTO MyDB (Field_1,Field_2,Field_n) VALUES (1,'string_val_2',4711)"
    ps = con.prepareStatement(stmt);
    return ps.executeUpdate(); // num rows affected
  }
  finally
  { if (ps  != null) 
      try { ps.close();  } 
      catch (Exception ex) { /* ex.printStackTrace(); */ }
  }
}
int updateTemplate() throws Exception
{ PreparedStatement ps = null;
  try
  { Sting stmt = 
      "UPDATE MyDB SET Field_1 = 1, Field_2 = 'string_val_2', Field_n = 4711 "
    + "WHERE Index_Field = 'Index-Value'"
    ps = con.prepareStatement(stmt);
    return ps.executeUpdate(); // num rows affected
  }
  finally
  { if (ps  != null) 
      try { ps.close();  } 
      catch (Exception ex) { /* ex.printStackTrace(); */ }
  }
}
int deleteTemplate() throws Exception
{ PreparedStatement ps = null;
  try
  { ps = con.prepareStatement("DELETE FROM MyDB WHERE Field_Name = 'Field-Value'");
    return ps.executeUpdate(); // num rows affected
  }
  finally
  { if (ps  != null) 
      try { ps.close();  } 
      catch (Exception ex) { /* ex.printStackTrace(); */ }
  }
}

Transaktions Verarbeitung

JDBC Datenbanken befinden sich nach dem Öffnen im AutoCommit-Modus, d.h. jeder Update, Insert und Delete wirkt sich unmittelbar auf den Inhalt der Datenbank aus. Wenn gefordert ist, dass ein kompletter Satz von Datenbank-Anweisungen entweder durchgeführt, oder im Fehlerfall die Datenbank in den ursprünglichen Stand zurück versetzt werden soll, müssen diese Anweisungen durch eine Transaktion geklammert werden.

void myTransaction(Connection con) throws Exception
{ try
  { // 1. Einleitung der Transaktion
    con.setAutoCommit(false);

    // 2. Ausführung der Transaktion
    myDatabaseAccess_1();
    myDatabaseAccess_2();
    // ...
    myDatabaseAccess_N();

    // 3. Abschluß der Transaktion
    con.commit();
  }
  catch (Exception ex)
  {  // Zurückfahren der Transaktion im Fehlerfall
     con.rollback();
     throw ex;
  }
  finally
  { // Commit-Modos in jedem Fall wieder auf Auto setzen!
    con.setAutoCommit(true);
  }
}

Voraussetzung ist natürlich, dass die Datenbank Transaktionen unterstützt. Tut sie das nicht, arbeitet sie in der Regel immer im Modus AutoCommit, ganz egal, ob man sie mittels setAutoCommit(...) auf true oder false einstellt und auch ein commit() oder rollback() bewirkt in diesem Fall nichts. Allerdings sauberer ist, zunächst einmal festzustellen, ob die Datenbank überhaupt Transaktionen ünterstützt und den Programmcode dann daraufhin abzustimmen:

boolean supportsTransactions(Connection con) throws SQLException
{ return con.getMetaData().supportsTransactions();
}

Weiterführende Informationen

SQL Datenbank Frontend

SpeedJDB - Frontend für alle gängigen Datenbanken. Gleichzeitiges öffnen mehrerer Connections verschiedener Datenbanken verschiedener Hersteller.

SpeedJDB Datenbank Frontend

Generierung, Modifikation, Ausführung und Abspeicherung von SQL-Befehlen.
Kostenloser Download

Die Produktbezeichnungen sind überwiegend eingetragene Warenzeichen der jeweiligen Hersteller. Alle verwendeten Abbildungen, Markennamen und Warenzeichen unterliegen dem Urheberrecht der Eigentümer. Wir übernehmen keine Gewähr und Haftung für fehlerhafte oder unterbliebene Angaben.

Member of W3C Sites dot com Valid HTML 4.01 Strict WSE Quality-Certified Website Valid HTML 4.01

Copyright © 2008 Wöhrmann Softwareentwicklung

Software-Tools Impressum Kontakt

Service Partner

macteq®
Ihr preisgünstiger Apple Macintosh Hardware, Software Shop und Service Partner.

Siegel IT Consulting
Domain Hosting und Support, sowohl technisch als auch inhaltlich.

Java Practices