Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5 (Tiger-Release)
Buch: Java ist auch eine Insel
gp Kapitel 20 Datenbankmanagement mit JDBC
  gp 20.1 Das relationale Modell
  gp 20.2 JDBC: der Zugriff auf Datenbanken über Java
  gp 20.3 Die Rolle von SQL
    gp 20.3.1 Ein Rundgang durch SQL-Anfragen
    gp 20.3.2 Datenabfrage mit der Data Query Language (DQL)
    gp 20.3.3 Tabellen anlegen mit der Data Definition Language (DDL)
  gp 20.4 Datenbanktreiber für den Zugriff
    gp 20.4.1 Treibertypen
  gp 20.5 Datenbanken und ihre Treiber
    gp 20.5.1 Die freie Datenbank MySQL
    gp 20.5.2 JDBC-Treiber für MySQL: MySQL Connector/J
    gp 20.5.3 Die Datenbank Microsoft Access
    gp 20.5.4 Ein Typ-4-Treiber für den Microsoft SQL Server 2000
    gp 20.5.5 Die JDBC-ODBC-Bridge
    gp 20.5.6 ODBC einrichten und Access damit verwenden
    gp 20.5.7 Oracle9i Enterprise Edition
    gp 20.5.8 JDBC-Treiber für mobile Endgeräte
  gp 20.6 Eine Beispielabfrage
  gp 20.7 Mit Java an eine Datenbank andocken
    gp 20.7.1 Der Treibermanager
    gp 20.7.2 Eine Aufzählung aller Treiber
    gp 20.7.3 Log-Informationen
    gp 20.7.4 Den Treiber laden
    gp 20.7.5 Verbindung zur Datenbank
  gp 20.8 Datenbankabfragen
    gp 20.8.1 Abfragen über das Statement-Objekt
    gp 20.8.2 Ergebnisse einer Abfrage in ResultSet
    gp 20.8.3 Java und SQL-Datentypen
    gp 20.8.4 Unicode in der Spalte korrekt auslesen
    gp 20.8.5 wasNull() bei ResultSet
    gp 20.8.6 Wie viele Zeilen hat ein ResultSet?
  gp 20.9 Die Ausnahmen bei JDBC
  gp 20.10 Transaktionen
  gp 20.11 Elemente einer Datenbank hinzufügen und aktualisieren
    gp 20.11.1 Batch-Updates
  gp 20.12 Vorbereitete Anweisungen (Prepared Statements)
    gp 20.12.1 PreparedStatement-Objekte vorbereiten
    gp 20.12.2 Werte für die Platzhalter eines PreparedStatement
  gp 20.13 Die LOBs (Large Objects)
    gp 20.13.1 Einen BLOB besorgen
  gp 20.14 Die SQL3-Datentypen ARRAY, STRUCT und REF
  gp 20.15 Metadaten
    gp 20.15.1 Metadaten über die Tabelle
    gp 20.15.2 Informationen über die Datenbank
  gp 20.16 DataSource
    gp 20.16.1 Die Schnittstelle DataSource
  gp 20.17 Java Data Objects (JDO)
  gp 20.18 XML-Datenbanken
    gp 20.18.1 Apache Xindice
    gp 20.18.2 eXist und Weitere


Galileo Computing

20.15 Metadatedowntop

Von einer Datenbank können verschiedene Informationen ausgelesen werden. Zum einen sind dies Informationen zu einer bestimmten Tabelle, zum anderen sind dies Informationen über die Datenbank selbst.


Galileo Computing

20.15.1 Metadaten über die Tabelle  downtop

Metadaten können für jede Abfrage angefordert werden. So lässt sich unter anderem leicht herausfinden:

gp  Wie viele Spalten wir in einer Zeile abfragen können
gp  Wie der Name der Spalte lautet
gp  Welchen SQL-Typ die Spalte hat
gp  Ob NULL für eine Spalte in Ordnung ist
gp  Wie viele Dezimalzeichen eine Spalte hat

Bei der Abfrage über alle Spalten müssen wir die Struktur der Datenbank kennen, insbesondere dann, wenn wir eine Abfrage vornehmen und die passenden Daten herauslesen wollen. So liefert


SELECT * FROM Pflanzen

ein ResultSet mit der gleichen Anzahl von Zeilen wie die Pflanzen-Tabelle. Doch bevor wir nicht die Anzahl und Art der Spalten kennen, können wir nicht auf die Daten zugreifen (oder alles muss als String herausgenommen werden). Um diese Art von Informationen, so genannte Metadaten, in Erfahrung zu bringen, befindet sich die Klasse ResultSetMetaData, mit der wir diese Informationen erhalten, unter den SQL-Klassen.

Bleiben wir bei den Pflanzen. Um die Anzahl und Art der Spalten herauszufinden, befragen wir das ResultSet, das vom SQL-Kommando SELECT * FROM Pflanzen angelegt wird. Zunächst der Aufruf von executeQuery():


ResultSet result = stmt.executeQuery( "SELECT * FROM Pflanzen" );

Nun können wir vom ResultSet ein ResultSetMetaData-Objekt bekommen. Dazu wird getMetaData() verwendet:


ResultSetMetaData meta = result.getMetaData();


interface java.sql.  ResultSet  

gp  ResultSetMetaData getMetaData() throws SQLException
Die Eigenschaften eines ResultSet werden in einem ResultSetMetaData zurückgegeben.

Nun bietet ResultSetMetaData viele Methoden, um Aussagen über die Tabelle und Spalten zu treffen. So fragen wir mit getColumnCount() nach, wie viele Spalten die Tabelle hat:


int columns = meta.getColumnCount();

Anschließend kann durch die Liste gegangen werden, und die Namen der Spalten lassen sich ausgeben:


int numerics = 0;

for ( int i = 1; i <= columns; i++ )
{
  System.out.println( meta.  getColumnLabel(i)   + "\t\t\t" +

    meta.  getColumnTypeName(i)   );

  if ( meta.  isSigned(i)   )
    numerics++;
}

System.out.println();
System.out.println( "Spalten: " + columns + " Numerisch: " + numerics );

Jetzt finden wir die Methoden vom ResultSetMetaData-Objekt aufgelistet. Alle Methoden können wieder eine SQLException auswerfen.

Listing 20.2   TableMetaData.java


import java.sql.*;

public class TableMetaData
{
  public static void main( String args[] ) throws Exception
  {
    Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );

    Connection con;
    Statement stmt;

    con = DriverManager.getConnection( "jdbc:odbc:Pflanzen", "", "" );
    stmt = con.createStatement();

    String sqlQuery = "SELECT * FROM PFLANZEN";

    ResultSet result = stmt.executeQuery( sqlQuery );

    ResultSetMetaData meta = result.getMetaData();

    int columns = meta.getColumnCount();
    int numerics = 0;

    for ( int i = 1; i <= columns; i++ )
    {
      System.out.println( meta.getColumnLabel(i) + "\t\t\t" +
                          meta.getColumnTypeName(i) );

      if ( meta.isSigned(i) )
        numerics++;
    }

    System.out.println();
    System.out.println( "Spalten: " + columns + " Numerisch: " + numerics );

    stmt.close ();
    con.close ();
  }
}


interface java.sql.  ResultSetMetaData  

gp  int getColumnCount()
Anzahl der Spalten im aktuellen ResultSet. Praktisch für Anweisungen wie SELECT *.

Allen folgenden Methoden wird ein int übergeben, welches die Spalte kennzeichnet.

gp  String getCatalogName( int column )
Gibt den String mit dem Katalognamen der Tabelle für die angegebene Spalte zurück.
gp  String getColumnName( int column )
Liefert den Spaltennamen der Tabelle.
gp  int getColumnDisplaySize( int column )
Maximale Anzahl der Zeichen, die die Spalte einnimmt. So ist bei einer Spalte vom Typ VARCHAR(11) mit einer maximalen Spaltenbreite von zehn Zeichen zu rechnen. Bei numerischen Spalten variiert der Wert.
gp  String getColumnLabel( int column )
Gibt einen String zurück, der den Titel der angegebenen Spalte enthält. Der Titel gibt an, welche Überschrift für die Spalte angezeigt werden soll. Einige Datenbanken erlauben die Unterscheidung zwischen Spaltenname und Spaltentitel.
gp  int getColumnType( int column )
Typ der Spalte wird ermittelt. Der Spaltentyp ist dabei eine Konstante aus der Klasse java.sql.Types. Sie definiert die Konstanten nach dem XOPEN-Standard. Die Reihenfolge der Datentypen ist: ARRAY_LOCATOR, BIGINT, BINARY, BIT, BLOB_LOCATOR, CHAR, CLOB_LOCATOR, DATE, DECIMAL, DISTINCT, DOUBLE, FLOAT, INTEGER, JAVA_OBJECT (benutzerdefinierter Datentyp), LONGVARBINARY, LONGVARCHAR, NULL, NUMERIC, REAL, REF, SMALLINT, STRUCT, STRUCT_LOCATOR, TIME, TIMESTAMP, TINYINT, VARBINARY, VARCHAR. Die Konstante OTHER zeigt ein datenbankspezifisches Element an und wird auf ein Java-Objekt abgebildet, falls ein Zugriff mittels getObject() oder setObject() erfolgt.
gp  String getColumnTypeName( int column )
Name der Spalte, so wie er in der Datenbank definiert ist.
gp  int getPrecision( int column )
Dezimalgenauigkeit der Spalte, zurückgegeben als Anzahl der Ziffern.
gp  int getScale( int column )
Liefert die Genauigkeit der Spalte. Dies ist die Anzahl der Stellen, die nach dem Dezimalpunkt verwendet werden können.
gp  String getSchemaName( int column )
Name des Tabellenschemas. Wird von den Methoden des DatabaseMetaData-Objekts benutzt. Falls kein Schema vorhanden ist, wird "" zurückgegeben.
gp  String getTableName( int column )
Tabellenname der angegebenen Spalte.
gp  boolean isAutoIncrement( int column )
Stellt fest, ob eine Spalte eine AutoIncrement-Spalte ist. Diese nimmt dann automatisch den nächsten freien Wert an, wenn ein neuer Datensatz eingefügt wird. Ist die erste Zeile einer Tabelle mit einer AutoIncrement-Spalte eingefügt, so nimmt die Spalte den Wert 1 an. In den meisten Datenbanken ist es allerdings nicht möglich, eigene Werte in diesen Spalten einzutragen.
gp  boolean isCaseSensitive( int column )
Berücksichtigt die Spalte die Groß- beziehungsweise Kleinschreibung?
gp  boolean isCurrency( int column )
Enthält die Spalte Geldwerte? Nur einige Datenbanken bieten diesen Spaltentyp.
gp  boolean isNullable( int column )
Ist ein NULL in der Spalte erlaubt?
gp  boolean isSearchable( int column )
Kann die Spalte in einer SQL-WHERE-Klausel verwendet werden?
gp  boolean isSigned( int column )
Enthält die Spalte vorzeichenbehaftete Datentypen? Vorzeichenbehaftete Typen sind unter anderem INT, LONGINT und SMALLINT. Vorzeichenlose Typen sind unter anderem UINT, ULONG und UBYTE.
gp  boolean isReadOnly( int column )
Kann auf die Spalte definitiv nicht schreibend zugegriffen werden? Ist das Ergebnis true, kann der Wert also nicht aktualisiert werden.
gp  boolean isWritable( int column )
Ist es prinzipiell möglich, auf die Spalte schreibend zuzugreifen? Häufig implementiert als !isReadOnly(column).
gp  boolean isDefinitelyWritable( int column )
Kann auf die Spalte definitiv schreibend zugegriffen werden? Viele Datenbanken liefern die gleichen Ergebnisse bei isDefinitelyWritable() und isWritable(). Prinzipiell könnte der Zustand von isWritable() abweichen, wenn sich zum Beispiel dynamisch die Schreibbarkeit ändert.

Galileo Computing

20.15.2 Informationen über die Datenbank  toptop

Metadaten sind auch für die gesamte Datenbank abfragbar. Beispiele für diese Informationen sind:

gp  Was für Tabellen liegen in der Datenbank?
gp  Wer ist mit der Datenbank verbunden?
gp  Kann die Datenbank nur gelesen oder kann auch in die Datenbank geschrieben werden?
gp  Wie lauten die Primärschlüssel für eine Tabelle?
gp  Sind gespeicherte Prozeduren auf der Datenbankseite erlaubt?
gp  Lassen sich äußere Joins (outer joins) durchführen?

Sind Informationen über die Datenbank gefragt, so lassen sich über Metadaten eines DatabaseMetaData-Objekts beispielsweise Datenbankeigenschaften des Herstellers herausfinden. Zunächst benötigen wir dazu ein DatabaseMetaData-Objekt. Dies bekommen wir über die Methode getConnection() des Treibermanagers.


Connection con = DriverManager.getConnection( "jdbc:odbc:Pflanzen" );
DatabaseMetaData meta = con.  getMetaData();  

getMetaData() gibt ein DatabaseMetaData-Objekt zurück, das eine große Anzahl von Methoden erlaubt.


Beispiel   Das nachfolgende Programmstück befragt die Datenbank Microsoft Access über die JDBC-ODBC-Brücke nach ihrem Produktnamen und einigen weiteren Attributen. Die Ausgaben beziehen sich auf die Installation von Access 2000.

Listing 20.3   DBMetaData.java


import java.sql.*;

public class DBMetaData
{
  public static void main( String args[] ) throws Exception
  {
    Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );

    Connection con = DriverManager.getConnection( "jdbc:odbc:Pflanzen" );

    DatabaseMetaData meta = con.getMetaData();

    System.out.println( "ProduktnameDatabase : " +
                         meta.getDatabaseProductName() );     // ACCESS

    System.out.println( "Version der Datenbank : " +
                         meta.getDatabaseProductVersion()  ); // 03.50.0000

    System.out.println( "Anzahl erlaubter Verbindungen : " +
                         meta.getMaxConnections() );          // 64

    System.out.println( "Version des DB-Treibers : " +
                         meta.getDriverVersion() );          
// 2.0001 (04.00.6019)

    System.out.println( "Update im Batchbetrieb : " +
                         meta.supportsBatchUpdates() );       // true

    System.out.println( "Gespeicherte Prozeduren : " +
                         meta.supportsStoredProcedures() );   // true

    con.close ();
  }
}




Copyright © Galileo Press GmbH 2004
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de