Java und DBs

Table of Contents

Java kommt von Haus aus mit einer relationalen Open-Source-Datenbank, der Apache-Derby-Datenbank, welche in reinem Java geschrieben ist und sich dadurch nicht nur als eigener Prozess betreiben lässt, sondern auch als Embeded Bestandteil einer Java Anwendung betrieben werden kann.

Das ist jedoch für den produktiven Betrieb nicht empfohlen. Für testgetriebene Entwicklung ist es jedoch sehr praktisch.

Eine relationale Datenbank zeichnet sich dadurch aus, das Sie eine strenge Struktur vorgibt, wie die Daten aussehen müssen. Die grösste Dateneinheit ist die Tabelle. Jede Tabelle besteht aus Spalten. Eine Spalte hat jeweils einen Namen und einen Datentyp. Der Datentyp einer Spalte kann nur aus einer vorgegebenen Liste von primitiven Datentypen gewählt werden.

Genauso wichtig wie die Tabellen selbst, sind die Beziehungen zwischen ihnen. Da eine Tabelle keine komplexen Datentypen als Spalten enthalten kann, werden Beziehungen zwischen Datenbankeinträgen durch Schlüsselbezeichnungen (Fremdschlüssel) von einer Tabelle zur anderen dargestellt.  Ein Eintrag in einer Tabelle, deren Inhalt von einer anderen Tabelle abhängt, enthält dabei einen Verweis auf den Eintrag der Ursprungs-Tabelle. Dafür muss ein eindeutiger Schlüssel des übergeordneten Eintrags verwendet werden, meist ein ID-Feld, dessen einziger Zweck es ist, ein eindeutiger Schlüssel zu sein, der primary key (Primärschlüssel).

Die Datenbank kann sicherstellen, dass für diese Art von Beziehung keine fehlerhaften Werte eingetragen werden können. Wenn im Feld Kunde_ID ein Schlüssel steht, zu dem kein passender Eintrag in der Tabelle Kunde existiert, kann die Transaktion nicht abgeschlossen werden, weil die Konsistenz der Daten verletzt würde. Genauso kann ein Kunde nicht gelöscht werden, ohne dass gleichzeitig seine Bestellungen gelöscht würden, denn sonst würde zu dem nun herrenlosen Bestellungen kein Kunde existieren und wieder wäre die Konsistenz nicht mehr vorhanden. Diese Art von Beschränkungen auf den Daten einer Datenbank nennt man einen Constraint.

DDL

Die Data Definition Language wird verwendet, um die Struktur einer Datenbank anzulegen, also Tabellen, Spalten, Constraints und mehr.

CREATE TABLE Kunde (
    id            INTEGER      PRIMARY KEY,
    vorname       VARCHAR(50) NOT NULL,
    nachname      VARCHAR(75) NOT NULL,
    strasse       VARCHAR(50) NOT NULL,
    …
);

SQL

Die Structured Query Language, dient dazu, Daten in einer Datenbank zu bearbeiten und wiederzufinden. SQL ist ein extrem mächtiges Werkzeug, denn Datenbanken sind so auf das Durchsuchen grosser Datenbestände optimiert, dass sie gerade komplexe Anfragen oft schneller verarbeiten können, als eine Anwendung eine Liste im Speicher nach denselben Kriterien durchsuchen kann.

SELECT SUM(best.gesamtpreis) 
  FROM Bestellung best
  JOIN Kunde k ON (best.kunde_id = k.id)
 WHERE k.id = 1
   AND best.datum BETWEEN '01/01/2016' AND '12/31/2016'

Transaktionen

Änderungen an relationalen Datenbanken werden als Transaktionen gruppiert und müssen die ACID Kriterien erfüllen.

ACID-Kriterien

  • Atomicity: Jede Transaktion muss atomar sein, es werden entweder alle dazugehörigen Schreibvorgänge ausgeführt, oder keiner. Zudem ist sichergestellt, dass die von einer Transaktion betroffenen Datensätze nicht zwischenzeitlich von einer anderen Transaktion manipuliert wurden.
  • Consistency: Am Ende einer Transaktion ist sichergestellt, dass bestimmte Konsistenzregeln, die Sie auf der Datenbank konfigurieren können, eingehalten werden. Man kann durch diese Regeln nicht alle logischen Einschränkungen einer Anwendung abbilden, aber man kann verhindern, dass zu einem Benutzer mehrere Einkaufswagen existieren, oder umgekehrt.
  • Isolation: Jede Transaktion wird isoliert von allen anderen Transaktionen ausgeführt, so dass der Effekt für das Gesamtsystem so ist, als würden die Transaktionen nacheinander verarbeitet.
  • Durability: Für alle abgeschlossenen Transaktionen ist garantiert, dass die Daten dauerhaft gespeichert sind, auch wenn die Datenbank abstürzt.

JDBC

Der Zugriff mit Java auf eine Datenbank erfolgt durch die JDBC (Java Database Connectivity)-API. Die API sorgt dafür, dass der Java Entwickler auf alle DBs, egal welchen Hersteller auf die exakt gleiche Weise zugreifen kann. Das ermöglicht dass die Datenbank ausgetauscht wird, ohne das dafür der Java Code angepasst werden muss. Alle verbreiteten Datenbanken werden direkt mit JDBC-Treiber ausgeliefert.

JDBC ermöglicht es, aus einer Java Anwendung heraus direkt DDL- und SQL-Anweisungen auf die DB auszuführen. Das Einzige was man wissen muss, ist, wie man die Verbindung zum DB-Server konfiguriert. Dazu wird ein URL-Format verwendet:

jdbc:mysql://192.168.1.1:3306/meineDatenbank

Der erste Teil der URL, das Protokoll, ist immer gleich (jdbc). Der zweite Teil identifiziert den zu verwendenden Treiber und die Verbindungsinformationen zur Datenbank.

JPA

Die Java Persistence API setzt auf JDBC auf und ist heute der standard Weg, aus einer Java-Anwendung auf eine DB zuzugreifen. Die JPA ist Bestandteil von JEE. Sie ermöglicht nicht nur die Kommunikation mit einer DB, sie nimmt auch noch den Arbeitsschritt ORM (Object Relational Mapping) ab, also die Abbildung von Tabellenzeilen auf Java-Objekte. Für den Datenbankzugriff durch die JPA schreibt man eine ganz normale Java Klasse, die man durch eine Reihe von Annotationen zu einer JPA-Entität macht (eine Klasse, die mit der DB-Tabelle verbunden ist):

@Entity
public class Kunde {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private int id;
    private String vorname;
    private String nachname;
    …

    @OneToMany()
    private final List<Kunde> freunde = new ArrayList<Kunde>();

    public int getId() {
      return id;
    }

    public void setId(int id) {
      this.id = id;
    }
    …
}