Home ORDIX AG             Dienstleistung             Trainingsshop    Kunden / Referenzen Aktuelles    Kontakt
Home  Pfeil  ORDIX News  Pfeil  1/2010  Pfeil  Java/JEE
suche: 
Dieser Artikel ist für Java-Entwickler und Software-Architekten von Interesse.

Glossar

Data Access Object (DAO)
Entwurfsmuster, das eine separate Software-Schicht für den Zugriff auf die Datenbank vorsieht.
Design Pattern
Entwurfsmuster. Beschreibt Architekturen von Software-Komponenten, die sich bewährt haben.
EJB (Enterprise Java Bean)
Teil des JEE-Standards. Objekt, dass von einem Application Server erstellt und dessen Methoden von einem Client aufgerufen werden.
Factory
Fabrik - Entwurfsmuster für Klassen, die Objekte erstellen und zur Verwendung instrumentieren.
JEE (Java Enterprise Environment)
Standardisiertes Framework für die Entwicklung von Server-Anwendungen.
JPA (Java Persistence API)
Teil des JEE-Standards. Über diese Schnittstelle erfolgt das dauerhafte Speichern oder Laden von Daten. Wesentliche Eigenschaft ist die Umwandlung von Objekten in Zeilen von Datenbanktabellen.
Mock-Objekt
Diese Objekte werden für die Entwicklung und Modultests eingesetzt. Sie implementieren Service Interfaces in möglichst einfacher Weise. Sie stehen dadurch zeitnah zur Verfügung. Ihr Verhalten ist gut vorhersehbar.
Titelbild

Java Best Practice (Teil VI)

Data Access Object -
Profis für den Zugriff


Das Entwurfsmuster Data Access Objekt (DAO) [1] beschreibt eine separate Software-Schicht für den Zugriff auf die Datenbank. Wesentliche Vorzüge dieser Lösung sind die Wiederverwendbarkeit des Codes sowie die Abstraktion des Datenzugriffs. Dies allein sind schon gute Gründe, das Entwurfsmuster unter die Lupe zu nehmen.

Abb. 1: Kommunikationsdiagramm für einen Bestellvorgang.
Abb. 1: Kommunikationsdiagramm für einen Bestellvorgang. Vergrößern
Abb. 2: Schichten-Architektur der Business Layer.
Abb. 2: Schichten-Architektur der Business Layer. Vergrößern
Abb. 3: Implementierung in einer JEE-Architektur.
Abb. 3: Implementierung in einer JEE-Architektur. Vergrößern
package ejb;
import java.io.Serializable;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import common.Artikel;
import service.ArtikelDao;

@Stateless(name = "ArtikelDao")
@Local(service.ArtikelDao.class)
public class ArtikelDaoBean implements ArtikelDao, Serializable {
  @PersistenceContext(unitName = "containerPersistence")
  private EntityManager entityManager;

  public void delete(Artikel artikel) {
    entityManager.remove(artikel);
  }
  public Artikel getById(Long id) {
    return entityManager.find(Artikel.class, id);
  }
  public void save(Artikel artikel) {
    entityManager.persist(artikel);
  }
  public void update(Artikel artikel) {
    entityManager.merge(artikel);
  }
Abb. 4: Quellcode einer DAO-Klasse für die Persistenz von Artikel-Objekten.
Java Best Practice
Teil I: Java-Objekte in der Identitätskrise
Teil II: Konfiguration der IDE
Teil III: Typisch Ant
Teil IV: Ausnahmen sind die Regel
Teil V: Das kleine 1x1
der Software-Entwicklung

Teil VI: Data Access Object

Data Access Object

Der Name dieses Entwurfsmusters ist Programm: Es schlägt vor, Klassen zu erstellen, deren einzige Aufgabe es ist, Daten dauerhaft zu speichern oder dauerhaft gespeicherte Daten zur Verfügung zu stellen.

Eine DAO-Klasse enthält Methoden wie

Das Objekt der Begierde ist in unserem Beispiel ein Artikel. Seine einzige Aufgabe ist es, Daten strukturiert aufzunehmen, die dauerhaft gespeichert werden sollen.

In der DAO-Schnittstelle werden so genannte Business-Objekte verwendet wie beispielsweise Kunde oder Bestellung. Die Namen der DAO-Klassen werden anhand der Business-Objekte hergeleitet. Kunden-Objekte werden in der KundenDao, Bestellung-Objekte in einer BestellungDao abgespeichert.

Klasse DAO

Die Benutzung des DAO-Patterns wird anhand des Kommunikationsdiagramms der Abbildung 1 diskutiert. Als Beispiel wird ein fiktiver Bestellvorgang in einer JEE-Architektur skizziert.

Der Client verfügt über Kunden- und Artikelnummer und kennt die zu bestellende Menge. Mit diesen Informationen wird der Bestellvorgang auf den Weg geschickt. Die BestellBean nimmt die Nachricht entgegen und delegiert sie an einen Bestellservice. Dieser wird passend zur Kunden- und Artikelnummer die entsprechenden Kunden und Artikel aus der Datenbank laden.

Dazu verwendet der Service Instanzen von KundenDao und ArtikelDao. Darauf wird der Service ein Bestell-Objekt erzeugen und dieses mit Hilfe einer BestellungDao in der Datenbank ablegen.

Software klar geschichtet

Anhand des Kommunikationsdiagramms (Abbildung 1) lassen sich wesentliche Vorteile der Verwendung des Entwurfsmusters darstellen. Ein Service kann mehrere DAO-Objekte in Anspruch nehmen. Durch die Separation von Service und DAO ist die Wiederverwendbarkeit des Codes für den Zugriff auf die Daten gewährleistet.

Die Dienstleistung der DAO-Klassen wird offensichtlich angeboten: Sind Informationen zu einem Artikel oder einem Kunden erforderlich, welche Klasse muss eingesetzt werden? Die ArtikelDao und KundenDao, natürlich.

Offensichtlich ist auch, dass die DAO-Klassen eine Schicht bilden. Oberhalb dieser Schicht, zu den Service-Klassen hin, werden Informationen immer als Objekt (wie Kunde oder Artikel) behandelt. Aspekte der Datenbank bleiben verborgen.

In Abbildung 2 wird verdeutlicht, wie sich das DAO-Pattern in die Business Layer eingliedert. In der Business Layer wird die Geschäftslogik umgesetzt. Es wird von einer JEE-Architektur ausgegangen. Die Business Layer ist als Anwendung auf dem Application-Server deployed.

Durch den Einsatz des DAO-Patterns ist es möglich, die Business Layer weiter zu gliedern. Die DAO-Klassen sind dabei das Herzstück der Persistence Layer. In der Regel verwenden diese ein Persistence-Framework wie beispielsweise Hibernate oder eine Implementierung der Java Persistence API. Doch die Implementierung ist der Service Layer nicht bekannt – sie kennt nur die Schnittstellen der DAO-Klassen.

Die Service Layer implementiert die eigentliche Geschäftslogik. Sie ist durch die Persistence Layer aller Aufgaben der Datenpersistenz entledigt und kann sich dadurch auf ihre Kernaufgabe konzentrieren.

Zum Client hin sorgt eine Communication Layer (z. B. in Form einer Session Facade) dafür, dass die Kommunikation zwischen Client und Server problemlos verläuft. Schnittstellen können dadurch stabil gehalten werden, Services können in gewissem Umfang entkoppelt von der Client-Schnittstelle (weiter-)entwickelt werden. Exceptions werden mundgerecht an den Client weitergereicht.

Die Abstraktion der Persistenz führt dazu, dass die DAO-Schicht einfach austauschbar ist. Zu diesem Zweck sind DAO-Interfaces zu definieren. Die Austauschbarkeit beflügelt den Entwicklungs- und Testprozess, indem einfache Varianten der DAO-Klassen (so genannte Mock-Klassen) eingesetzt werden.

Performance-Probleme stehen nicht selten in Zusammenhang mit Datenbankzugriffen. Die Kapselung dieser Zugriffe ist eine gute Voraussetzung dafür, dass sich Spezialisten genau auf diese Aspekte konzentrieren können.

Wo bleiben die Transaktionen?

Für die Implementierung sind noch wesentliche Aspekte nicht angesprochen worden:

Die Beantwortung dieser Fragen richtet sich sehr nach der Umgebung, in der die Implementierung erfolgt. Unabhängig davon sollte eine Lösung aber die folgenden Aspekte berücksichtigen:

Da die Implementierung von DAO zu den Standardaufgaben der Anwendungsentwicklung gehört, gibt es Standardlösungen. Vielfach erprobt ist der Einsatz des Java-Enterprise-Standards oder aber des Spring-Frameworks [2].

Im Folgenden wird die Implementierung von DAOs in einer Java-Enterprise-Architektur weiter verfolgt.

DAO-Implementierung mit JEE

Die Geschäftslogik ist in einer JEE-Architektur in einem EJB-Container auszuführen. Dieser Container stellt unter anderem genau die erforderliche Infrastruktur für die Implementierung des DAO-Entwurfsmusters zur Verfügung: Er verwaltet sowohl die Verbindung zur Datenbank als auch Transaktionen. In Abbildung 3 sind die Aufgaben des EJB-Containers skizziert:

Er erzeugt die DAO-Beans und injiziert diesen einen Entity Manager. Mit diesem kann direkt ein objekt-relationaler Zugriff auf die Datenbank erfolgen. Auch die BestellBean wird vom EJB-Container erzeugt und mit den erforderlichen DAOs ausgestattet.

Die Transaktionssteuerung kann und sollte der EJB-Container ebenfalls übernehmen (Container Managed Transaction). Ruft ein Client eine Service-Methode auf, so kümmert sich der EJB-Container um die Transaktion.

In dieser Infrastruktur kann sich jede Schicht auf ihre Kernaufgabe konzentrieren. Die Implementierung des DAO-Patterns wird stark vereinfacht. In Abbildung 4 ist sie exemplarisch für die Klasse ArtikelDaoBean dargestellt.

Der Entity Manager stellt die erforderlichen Methoden unmittelbar zur Verfügung. Doch das wird sich im Laufe der Zeit ändern: In der Regel kommen umfangreichere Methoden dazu, wenn die Business Objekte Kollektionen anderer Objekte enthalten oder aber spezielle Datenbanksuchen erforderlich sind.

Schwieriger zu deuten sind die Annotations zu Beginn des Quellcodes von Abbildung 4. Damit der EJB-Container für DAOs genutzt werden kann, müssen diese als EJBs implementiert werden. Die Annotation @Stateless konfiguriert diese Klasse als Stateless-Session-Bean.

DAOs werden durch @Local als lokale EJB konfiguriert: Der Client darf keinen direkten Zugriff auf diese Beans haben. So wird verhindert, dass ein Client seine eigene Applikationslogik implementiert.

Schlussfolgerung

Das Entwurfsmuster Data Access Object gehört für die Implementierung von Geschäftslogik mit Datenbankanschluss zum Stand der Technik. Die Herausforderung ist weniger die Entwicklung der Data Access Klassen sondern vielmehr die Einrichtung der erforderlichen Infrastruktur. In unseren JEE-Seminaren [4] erfahren Sie mehr zur Implementierung des DAO-Patterns. Gern unterstützen wir Sie auch beim Entwurf und der Implementierung ihres Entwicklungsprojekts.


Dr. Stefan Koch (info@ordix.de).