Java Programmierung

Kap.15:  VERBINDUNG (Connection) ZU DATENBANKEN


Kapitel-Index
  15.1   Installieren eines SQL-Datenbank-Servers,  z.B. MySQL
  15.2   Einrichtung  einer SQL-Datenbank, z.B. Lager in MySQL
  15.3   Java-DB-Verbindung, z.B. zur Datenbank Lager in MySQL
  15.4   Testfragen
  Relationale Datenbanken nach E.F. Codd mit Structured Query Language (SQL) sind weit verbreitet. Die SQL-Datenbank-Server können vom Klienten entweder über das Web genutzt oder lokal im eigenen Rechner installiert (15.1) und genutzt (15.2) werden. Objektorientierte Datenbanken konnten sich wegen ihres hohen Speicherbedarfs (9.11, 9.1.3) nicht durchsetzen. Statt dessen stellt Java im Paket java.sql die Klasse DriverManager sowie die Schnittstellen Connection, Statement und ResultSet zum Zugriff auf SQL-Datenbanken zur Verfügung.

  Nach dem JDBC-Standard (Java Database Connectivity), den mittlerweile alle bekannten SQL-Datenbank-Server erfüllen, können SQL-Anweisungen als String-Argumente in Methoden der Java-Schnittstelle Statement geschrieben werden und die aktualisierten Ergebnisse der Datenbank mit Methoden der Java-Schnittstelle ResultSet abgefragt werden (15.3).


15.1     Installieren eines SQL-Datenbank-Servers, z.B. MySQL

  Als Beispiel wählen wir den bekanntesten frei verfügbaren plattformunabhängigen SQL-Datenbank-Server MySQL. Nach heutigem Entwicklungsstand ist MySQL eine echte Alternative zu kommerziellen SQL-Datenbank-Servern wie z.B. Access oder Oracle. Auch Apache Derby, ein ganz in Java geschriebener (relationaler) SQL-Datenbank -Server, wäre eine solche Alternative.

  Man lädt den MySQL-Server und den MySQL-Konnektor von
   http://dev.mysql.com/downloads/
und installiert MySQL lokal auf dem eigenen Rechner. Folgt man den Download- und Installations-Hinweisen
   # Windows Essentials, Typical, Developer Machine,
     Include BinDirectory in Windows PATH,
     Non-Transactional Database Only, Decision Support,
     Enable TCP/IP Networking, no firewall exception,
     Enable Strict Mode, Install as Windows Service, MySQL,
     Administrator root, Passwort z.B. mypassword,
so erhält MySQL die Port-Number 3306 und der MySQL-Server und der MySQL-Konnektor werden wie folgt installiert:
,----------------------------------------- Laufwerk C:\ ---------,
|                                                                |
|                    ,-------------------- Verzeichnis --------, |
| Programme\MySQL\MySQL Server 5.0\                            | |
|                    |   ,---------------- Unterverzeichnis -, | |
|                    |  bin\                                 | | |
|                    |   |  mysql.exe      Kommando          | | |
|                    |   |  mysqld-nt.exe  Kommando          | | |
|                    |   |                                   | | |
|                    |   '---------------- ... --------------' | |
|                    |   ,---------------- Unterverzeichnis -, | |
|                    | data\                                 | | |
|                    |   |  Lager          Unterverzeichnis  | | |
|                    |   |                                   | | |
|                    |   '---------------- ... --------------' | |
|                    |                                         | |
|                    '-------------------- ... ----------------' |
| ,--------------------------------------- Verzeichnis --------, |
| my\                                                          | |
| |          mysql-connector-java-5.1.5-bin.jar    Jar-File    | |
| |                                                            | |
| '--------- (hier einkopieren!) --------- ... ----------------' |
|                                                                |
'----------------------------------------- ... ------------------'
Fig. 15.1a: Verzeichnisse für MySQL in Windows 

  Man kontrolliere den Pfad (ggf. setzen) auf das Verzeichnis des Server-Aufruf-Kommandos mysql und des Dämon-Aufruf-Kommandos mysqld-nt und lösche ggf. die Systemvariable CLASSPATH:
   # Start, Systemsteuerung, System, Erweitert,
     Umgebungsvariablen, Sytemvariablen, Path, Bearbeiten,
     Einfügen von C:\Programme\MySQL\MySQL Server 5.0\bin;
     Löschen von CLASSPATH, Neustart.

  Der Standard-MySQL-Konnektor Connector/J für Java-Plattformen wird beim Download als Zip-Datei mysql-connector-java-5.1.5.zip abgelegt, z.B. von Firefox auf dem Desktop unter "Eigene Dateien". Nach dem Entzippen findet ich darin das Java-Archiv
                mysql-connector-java-5.1.5-bin.jar               ,
das ich in mein aktuelles Verzeichnis C:\my einkopiere und dort entpacke mit dem Jar-Kommando xvf ('x'tract, 'v'erbose standard output, jar'f'ile)
        jar xvf mysql-connector-java-5.1.5-bin.jar               .
  Durch Aufruf dieses Kommandos werden in C:\my die entpackten Unterverzeichnisse com, META-INF und org des Archivs angelegt. Siehe Dokumentation "jar - The Java Archive Tool".

,----------- Laufwerk C:\ ---------------------------------------, 
|                                                                |
| ,--------- Verzeichnis --------------------------------------, |
| my\                                                          | |
| |          Artikel.tab              Tabelle-Textdatei        | |
| |                                                            | |
| | ,------- Unterverzeichnis ------- entpackt aus Jar-File -, | |
| | com\                                                     | | |
| | | ,----- Unterverzeichnis -----------------------------, | | |
| | | mysql\                                               | | | |
| | | | ,--- Unterverzeichnis ---------------------------, | | | |
| | | | jdbc\                                            | | | | |
| | | | |    Driver.class             DriverManager      | | | | |
| | | | |                                                | | | | |
| | | | '--- ... ----------------------------------------' | | | |
| | | |                                                    | | | |
| | | '----------------------------------------------------' | | |
| | |                                                        | | |
| | '--------------------------------------------------------' | |
| |                                                            | |
| |          Lager.sql                SQL-Kommandodatei        | |
| |          LagerApplet.class        Java-Byte-Code           | |
| |          LagerApplet.html         HTML-Dokument            | |
| |          LagerApplet.java         Java-Quell-Code          | |
| |                                                            | |
| | META-INF Unterverzeichnis         entpackt aus Jar-File    | |
| |                                                            | |
| |          mysql-connector-java-5.1.5-bin.jar    Jar-File    | |
| |                                                            | |
| | org      Unterverzeichnis         entpackt aus Jar-File    | |
| |                                                            | |
| '--------- ... ----------------------------------------------' |
|                                                                |
'----------- ... ------------------------------------------------'
Fig. 15.1b: Aktuelles Verzeichnis C:\my\ mit entpacktem Jar-File

  Die im Java-Programm, siehe LagerApplet.java (15.3), für den DriverManager benötigte Datei Driver.class ist demnach zu finden unter
                  C:\my\com\mysql\jdbc\Driver.class              .
  Das Installationsprogramm trägt den Dämon mysqld-nt in die Liste der in Windows im Hintergrund laufenden Dienste ein. Der Prozess kann beendet werden durch
                  Ctrl+Alt+Del
                     Windows Task-Manager
                        mysqld-nt.exe   (Mausklick)
                           Prozess beenden   (Mausklick)
und wieder aktiviert werden durch Neustart.


15.2     Einrichtung einer SQL-Datenbank, z.B. Lager in MySQL


  Läuft MySQL im Hintergrund, siehe 15.1, dann kann aus jedem Verzeichnis heraus, z.B. aus meinem aktuellen Verzeichnis C:\my, eine Datenbank, z.B. die Datenbank Lager bestehend aus der Tabelle Artikel, in MySQL eingerichtet werden. Dazu schreibe man eine Textdatei Artikel.tab
/************************** Artikel.tab *************************/

(           7,"Rieker      ","Schuh       ",       99.99)
(           5,"Boss        ","Hose        ",      199.99)
(           2,"Armani      ","Hose        ",      499.99)
(           4,"Armani      ","Jacke       ",      999.99)

/****************************************************************/
und eine Textdatei Lager.sql, die Zeilenstruktur (,,,) und String -Begrenzer "..." für die Tabelle Artikel angibt und die Textdatei Artikel.tab lädt.
/************************** Lager.sql ***************************/

DROP   DATABASE             Lager;
CREATE DATABASE             Lager;
USE                         Lager;

CREATE TABLE                Artikel
                             (
                              Nummer_int      INT NOT NULL,
                              Marke_char_12   CHAR(12),
                              Name_char_12    CHAR(12),
                              Preis_real_12_2 REAL(12,2)
                             );

LOAD DATA INFILE     "C:/my/Artikel.tab"               /* Pfad von
                      C:\Programme\MySQL\MySQL Server 5.0\bin  auf
                      C:\my\Artikel.tab   mit / an Stelle von \ */
 INTO TABLE                 Artikel
 FIELDS TERMINATED          BY ","
        OPTIONALLY ENCLOSED BY '"'
 LINES  STARTING            BY "("
        TERMINATED          BY ")";

SELECT
                            Nummer_int,
                            Marke_char_12,
                            Name_char_12,
                            Preis_real_12_2 
 FROM                       Artikel
 ORDER BY                   Nummer_int;

/****************************************************************/
  Der MySQL-Monitor wird aufgerufen mit dem Kommando mysql und Nennung des bei der Installation angegebenen Benutzernamens root, d.h. Administrator, und des Passworts, d.h. mypassword.

Fig.15.2a.gif
Fig. 15.2a: Aufruf des MySQL Monitors            

  Der MySQL-Monitor stellt um auf mysql> Kommandoebene. Dort wird die Quelle der Datenbank Lager eingerichtet.

Fig.15.2b.gif
Fig. 15.2b: Einrichtung der Datenbank Lager

  Mit quit kehre ich in mein Verzeichnis C:\my zurück.

  Für Fragen zur MySQL-Syntax, z.B. REAL[(length,decimals)], und zur SQL-Syntax, z.B. CREATE TABLE tbl_name (create_definition); verweisen wir auf das MySQL Reference Manual.

15.3     Java-Verbindung, z.B. zur Datenbank Lager in MySQL

  Im folgenden Beispiel LagerApplet wird eine Java-DB-Verbindung (JDBC) aufgebaut zur im Hintergrund in MySQL laufenden Datenbank Lager mit Tabelle Artikel.
//********************** LagerApplet.java ************************
//  ResultSet-Zugriff auf rel. SQL-Datenbank Lager aus Artikeln, *
//             die im Hintergrund unter MySQL laeuft.            *
// JDBC-Konnektor-Verzeichnis com steht im aktuellen Verzeichnis *
//****************************************************************
//            java.lang.              Object
import static java.lang.System.*; //   ||||`System
import java.sql.*;      //DriverManager'|||   Connection Statement 
                        //              |||              ResultSet      
import java.awt.event.*;//   ActionEvent'|`--------,ActionListener 
import java.awt.*;      //        C o m p o n e n t`GridLayout      
                        //Container'Label'`Button`TextField 
import java.applet.Applet; // `Applet       

public class LagerApplet extends Applet implements ActionListener
 {Connection          connection;
  Statement           statement;
  ResultSet           resultset;
  public void init()                           // overrides Applet
   {try{Class.forName("com.mysql.jdbc.Driver");
                          // Pfad auf com\mysql\jdbc\Driver.class, 
                          // d.h. den DriverManager, mit . statt \
                          // Kann entfallen, falls JDBC 4 erfuellt
                      connection=DriverManager 
                      .getConnection              // DriverManager
                        ("jdbc:mysql://localhost:3306/Lager",
                          // Uniform Resource Locator (URL)  aus
                          // Protokoll   jdbc:mysql,Trenner ://,
                          // Host-Name    localhost,Trenner :  ,
                          // MySQL-Port-Nummer 3306,Trenner /  ,
                          // DB-Datei-Name    Lager
                         "root",                  // Administrator
                         "mypassword"                  // Passwort
                        );
                      statement=connection
                      .createStatement               // Connection
                        (ResultSet.TYPE_SCROLL_SENSITIVE,
                                 // resultset absolut adressierbar
                         ResultSet.CONCUR_UPDATABLE
                        );       // resultset updatable
                      resultset=statement
                      .executeQuery                   // Statement
                        ("SELECT * FROM Artikel "   // alle Zeilen
                        +"ORDER BY Nummer_int;" // werden geordnet
                        );        
       }catch        (Exception e) {err.println(e.toString());}
   }
  Label[]             lab={new Label("Nummer_int"),
                           new Label("Marke_char_12"),
                           new Label("Name_char_12"),
                           new Label("Preis_real_12_2")};
  TextField[]         fld= new TextField[lab.length];
  Button[]            but={new Button("first ^"),
                           new Button("previous ^"),
                           new Button("next v"),   
                           new Button("last v")};
  public void start()                          // overrides Applet
   {int               size=getHeight()/6;
    setFont          (new Font("SansSerif",Font.BOLD,size));
    setLayout        (new GridLayout(   3,   4,size/2,size/2));
                                  // rows,cols,  hgap,  vgap
    for(Label         each:lab)                    // grid[1,1..4]
     {add            (each);}                         // Container
    for(int           i=0;i<fld.length;i++)        // grid[2,1..4]
     {add            (fld[i]=new TextField());}       // Container
    setTextField     ("first");        // setzt erste ArtikelZeile
    for(Button        each:but)                    // grid[3,1..4]
     {add            (each);                          // Container
      each.setActionCommand (each.getLabel());
      each.addActionListener(this);              
     }                                         // this LagerApplet
   }                           
  public void setTextField(String ArtikelZeile)   // set TextField 
   {try{switch       (ArtikelZeile.trim().charAt(0))
         {case 'f':   resultset.first   ();                 break;
          case 'p':   resultset.previous();                 break;
          case 'n':   resultset.next    ();                 break;
          case 'l':   resultset.last    ();                 break;
         }
        but[0].setEnabled(!resultset.isFirst());
        but[1].setEnabled(!resultset.isFirst());
        but[2].setEnabled(!resultset.isLast ());
        but[3].setEnabled(!resultset.isLast ());
        for(int       i=0;i<fld.length;i++)
         {fld[i].setText(resultset.getString(lab[i].getText()));}
       }catch        (SQLException e) {err.println(e.toString());}
   }                       
  public void actionPerformed(ActionEvent e)     // Button pressed
   {setTextField     (e.getActionCommand());}
 }
//****************************************************************
Fig.15.3.jpg
Fig. 15.3: LagerApplet Darstellung
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"   >
<!--***************** LagerApplet.html ************************-->
    <meta http-equiv="content-type"
             content="text/html;charset=ISO-8859-15"             >
    <title>           LagerApplet                         </title>
    <applet     code="LagerApplet.class" width="636" height="108">
                      LagerApplet
    </applet>
<!--***************** width=Hochformat height=6*size **********-->
  Es können Zeilen direkt (first,last) oder sukzessive (previous, next) auf Knopfdruck angezeigt werden. Knöpfe but können aktiviert (schwarz) werden mit but.setEnabled(true) bzw. deaktiviert (grau) werden mit but.setEnabled(false) , siehe Dokumentation der Klasse java.awt.Button .

  Mit Hilfe der Verbindung connection wird ein statement vereinbart, das den int resultSetType, hier absolute Adressierbarkeit,
                          ResultSet.TYPE_SCROLL_SENSITIVE
  und die int resultSetCocurrency, hier Änderungserlaubnis,
                          ResultSet.CONCUR_UPDATABLE
festlegt, siehe Dokumentation der Schnittstelle java.sql.Statement,
    Statement statement=connection.createStatement             
                         (ResultSet.TYPE_SCROLL_SENSITIVE,           
                          ResultSet.CONCUR_UPDATABLE);        .
  Danach wird ein resultset initialisiert durch Aufruf der Methode statement.executeQuery(String) mit einem String Argument, das eine SQL-SELECT-Anfrage stellt an die Tabelle Artikel, siehe Dokumentation der Schnittstelle java.sql.ResultSet.
    ResultSet resultset=statement.executeQuery     
                         ("SELECT * FROM Artikel "  
                         +"ORDER BY Nummer_int;"
                         );

  Die MySQL-Syntax (15.2) folgt weitgehend der SQL-Syntax. Auch UPDATE oder INSERT oder DELETE wäre möglich:
  statement.executeUpdate("UPDATE Artikel SET ... WHERE ... "); 

  statement.executeUpdate("INSERT INTO Artikel(..)VALUES(..)"); 

  statement.executeUpdate("DELETE FROM Artikel    WHERE ... ");

  Anschließend erfolgt wieder die Zuweisung
 resultset=
  statement.executeQuery ("SELECT * FROM Artikel  ORDER BY.."); 

         ,----------------------------------------------,
VVVVVVVVV| JDBC-Verbindung zur SQL-Datenbank  (Prinzip) |VVVVVVVVV
VV       '----------------------------------------------'       VV  
VV Es  soll  eine  JDBC-Verbindung (Java Database Connectivity) VV
VV zwischen dem Java-Programm eines Klienten und der SQL-Daten- VV
VV bank Lager eines SQL-Datenbank-Servers aufgebaut werden.     VV
VV                                                              VV
VV    # Dazu  benötigt der Klient die vom Server in einem Java- VV
VV Archiv bereitgestellten Verzeichnisse com, META-INF und org, VV
VV die entpackt ins aktuelle Verzeichnis C:\my gesetzt werden.  VV
VV                                                              VV
VV    # Die in Unterverzeichnissen  von  com  enthaltene Klasse VV
VV C:\my\com\mysql\jdbc\Driver.class wird zur Klasse des Driver VV
VV Manager erklärt:                                             VV
VV                                                              VV
VV           Class.forName("com.mysql.jdbc.Driver");            VV
VV                                                              VV
VV Für Java-Verionen>=1.6  und für Server mit  JDBC-Standard>=4 VV
VV erübrigt sich der Aufruf von Class.forName(String) .         VV
VV                                                              VV
VV    # Bei  der  Installation  des Servers MySQL lokal auf dem VV
VV eigenen Rechner (15.1) wird  dem  Klienten die default-Port- VV
VV Number 3306  des Servers mitgeteilt.  Demnach lautet die URL VV
VV (UniformResource  Locator)  der  beim  Server eingerichteten VV
VV Datenbank  Lager  "jdbc:mysql://localhost:3306/Lager" .  Die VV
VV Installation  des  Servers  MySQL  verlangt vom Klienten die VV
VV Anmeldung  als Administrator  "root"  und  empfiehlt ihm die VV
VV Setzung eines Passworts, z.B. "mypassword" . Damit kann eine VV
VV JDBC-Verbindung  zwischen  dem  Java-Programm und  der  SQL- VV
VV Datenbank  Lager  aufgebaut  werden:                         VV
VV                                                              VV
VV  Connection connection=                                      VV
VV   DriverManager.getConnection                                VV
VV                  ("jdbc:mysql://localhost:3306/Lager",       VV
VV                   "root",                                    VV
VV                   "mypassword");                           . VV
VV                                                              VV
VV (siehe Dokumentation der Schnittstelle  java.sql.Connection) VV
VV                                                              VV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV


15.4     Testfragen

zu    Frage                                  | abdeckbare Antwort
---------------------------------------------+--------------------
                                             |
15.1    Wie prüft man in C:\my,  ob der Pfad | path
      C:\Programme\MySQL\MySQL Server 5.0\bin|           
      (bei der Installation) gesetzt wurde?  |
                                             |
15.1   Wie prüft man in C:\my, ob die Ssytem-| set classpath
      vaiable CLASSPATH gelöscht wurde?      |   
                                             |
15.2     Wie  gelange  ich als Administrator |C:\mysql --user=root
       (root)   mit   meinem   MySQL-Paßwort |         --password=
       (mypassword)  aus  meinem Verzeichnis |          mypassword
       C:\ auf die MySQL-Kommandoebene?      |            
                                             |
15.2     Wie  gelange ich von der MySQL-Kom- |mysql> quit 
       mandoebene zurück in mein Verzeichnis |       
       C:\ ?                                 |
                                             |
15.3     Wie kann man die Anzahl count() der |public int count()
      Zeilen   eines   TYPE_SCROLL_SENSITIVE |{try
      resultset bestimmen mit den ResultSet- |{boolean
      Methoden                               | a=isAfterLast();
                                             | b=isBeforeFirst();
       # isBeforeFirst()                     | int curr=getRow();
       # isAfterLast()                       | last();
       # getRow()                            | int numb=getRow();
       # beforeFirst()                       | if(a) afterLast();
       # afterLast()                         | else
       # absolute(int)                       | if(b)beforeFirst();
                                             | else
      ohne  die  Zeilen und die gegenwärtige | absolute(curr);
      absolute Zeilen-Position des ResultSet | return numb;
      zu verändern  (vgl.  Dokumentation  zu |}
      ResultSet) ?                           |catch(Exception e){}
                                             |return 0;
                                             |}
                                             |
    Java Programmierung
  Syntaxdiagramme