Eine Einführung in Hibernate 3 - EDV

Werbung
Kapitel 1
Eine Einführung in Hibernate 3
Die meisten wichtigen Entwicklungsprojekte arbeiten mit einer relationalen Datenbank. Ein großer Teil der meisten kommerziellen Anwendungen besteht aus einem
umfangreichen Speicher geordneter Informationen: Kataloge, Kundenlisten, Vertragstexte, veröffentlichte Texte und architektonische Entwürfe.
Mit dem Aufkommen des World Wide Web hat die Nachfrage nach Datenbanken
zugenommen. Auch wenn Sie sich vielleicht dessen nicht bewusst sind: Die Kunden
von Online-Buchhändlern und -Zeitungen arbeiten mit Datenbanken.
Irgendwo in den Tiefen der Anwendung wird eine Datenbank abgefragt und ein
Ergebnis angeboten.
Während die Nachfrage nach solchen Anwendungen gestiegen ist, ist ihre Erstellung
nicht merklich einfacher geworden. Es hat eine gewisse Standardisierung gegeben –
die erfolgreichste war der Enterprise-JavaBeans-(EJB-)Standard der Java 2 Enterprise
Edition (J2EE), der Container sowie Beans bereitstellt, um die Persistenz von EntityBean-Klassen zu verwalten. Leider litt dieses Persistenzmodell zusammen mit anderen ähnlichen Modellen unter der Unvereinbarkeit zwischen dem relationalen und
dem objektorientierten Modell. Kurz gesagt: Datenbankpersistenz ist schwierig.
Es gibt Lösungen, für die EJBs angemessen sind, andere, für die eine Art des objektrelationalen Mappings (ORM) wie Hibernate passend sind, und wieder andere, für
die der traditionelle Ansatz des direkten Zugriffs per Java Database Connectivity
(JDBC) API ausreicht. Wir sind der Auffassung, dass Hibernate eine gute erste Wahl
darstellt, da es die gleichzeitige Anwendung dieser alternativen Ansätze nicht ausschließt.
Um einige der Stärken von Hibernate zu demonstrieren, werden wir Ihnen in diesem Kapitel ein kurzes Beispiel mit Hibernate zeigen und ihm den traditionellen
JDBC-Ansatz gegenüberstellen.
1.1
Plain Old Java Objects (POJOs)1
In einer idealen Welt wäre es trivial, ein beliebiges Java-Objekt in einer Datenbank zu
persistieren (dauerhaft zu speichern). Zu diesem Zweck wäre kein spezieller Code
erforderlich, die Performance würde nicht leiden, und das Ergebnis wäre vollkommen portabel.
1
(A.d.Ü.: In den letzten Jahren hat sich die Bezeichnung Plain Old Java Object – POJO – immer
mehr durchgesetzt. Sie wird nicht übersetzt. Wörtlich bedeutet sie: einfaches altes Java-Objekt.
POJOs sind Java-Objekte, die mit der Standard-class-Syntax von Java erstellt werden. Näheres
finden Sie in der deutschen Wikipedia: http://de.wikipedia.org/wiki/POJO.)
© des Titels »Einführung in Hibernate« (ISBN 978-3-8266-1794-2) 2007 by Redline GmbH, Heidelberg
Nähere Informationen unter: http://www.mitp.de/1794
Kapitel 1
Eine Einführung in Hibernate 3
In dieser idealen Welt könnten wir eine solche Operation vielleicht in einer Art ausführen, die in Listing 1.1 gezeigt wird.
POJO pojo = new POJO();
ORMSolution magic = ORMSolution.getInstance();
magic.save(pojo);
Listing 1.1:
Eine rosarote Sicht der Objekt-Persistenz
Es gäbe keine unangenehmen Überraschungen, keine zusätzliche Arbeit, um die
Klasse Tabellen in der Datenbank zuzuordnen, und keine Probleme mit dem Leistungsverhalten.
Hibernate kommt diesem Ideal bemerkenswert nahe, zumindest im Vergleich zu
den Alternativen – aber leider müssen Konfigurationsdateien erstellt und subtile
Leistungsprobleme bedacht werden. Jedoch erreicht Hibernate sein fundamentales
Ziel: Es ermöglicht Ihnen, POJOs in der Datenbank zu speichern. Abbildung 1.1
zeigt, wie Hibernate zwischen dem Clientcode und der Datenbank in Ihre Anwendung passt.
DATENBANK
JDBC
Mappings
Hibernate
Hibernate
Systemgrenze
Konfiguration
POJOs
Client-Code
Abb. 1.1:
Die Rolle von Hibernate in einer Java-Anwendung
Die übliche Bezeichnung für die direkte Persistenz traditioneller Java-Objekte lautet
objektrelationales Mapping – das bedeutet: die Zuordnung von Objekten in Java zu
relationalen Entities in einer Datenbank.
Während Entity-Beans zahllosen umständlichen Namenskonventionen folgen müssen, können POJOs beliebige Java-Objekte sein. Mit Hibernate können Sie POJOs
mit sehr wenigen Einschränkungen persistieren.
Listing 1.2 zeigt ein Beispiel für ein einfaches POJO, das eine Nachricht repräsentiert.
public class Message {
private Message() {
}
20
© des Titels »Einführung in Hibernate« (ISBN 978-3-8266-1794-2) 2007 by Redline GmbH, Heidelberg
Nähere Informationen unter: http://www.mitp.de/1794
1.2
Die Ursprünge von Hibernate und des objektrelationalen Mappings
public Message(String messageText) {
this.messageText = messageText;
}
public String getMessageText() {
return messageText;
}
public void setMessageText(String messageText) {
this.messageText = messageText;
}
private String message;
}
Listing 1.2:
Das POJO, das in den Beispielen dieses Kapitels verwendet wird
Das einzige Zugeständnis an Hibernate besteht hier in der Bereitstellung eines privaten Standardkonstruktors. Alle POJOs, die Sie mit Hibernate speichern wollen,
müssen über einen Standardkonstruktor verfügen. Aber selbst diese Anforderung
kann umgangen werden, wenn die Klassen eines Drittanbieters diese Einschränkung nicht erfüllen (wie dies funktioniert, zeigen wir in Anhang A).
1.2
Die Ursprünge von Hibernate und des
objektrelationalen Mappings
Wenn Hibernate die Lösung ist, wie lautet dann das Problem? Eine Antwort lautet:
Wenn Sie korrekt mit JDBC arbeiten wollen, müssen Sie recht viel Code schreiben
und verschiedene Regeln (z.B. für die Verwaltung der Verbindungen) sorgfältig
beachten, damit Ihre Anwendung keine Ressourcenlöcher hinterlässt. Listing 1.3
zeigt, wie unglaublich viel Code erforderlich ist, um das Motd-Beispielobjekt mit
Daten aus der Datenbank zu füllen, selbst wenn Sie den korrekten Message-Bezeichner kennen.
public static List getMessages(int messageId)
throws MessageException {
Connection c = null;
PreparedStatement p = null;
List list = new ArrayList();
try {
Class.forName("org.postgresql.Driver");
c = DriverManager.getConnection(
"jdbc:hsqldb:testdb;shutdown=true",
"hibernate",
"hibernate");
p = c.prepareStatement(
"select message from motd");
ResultSet rs = p.executeQuery();
while (rs.next()) {
String text = rs.getString(1);
21
© des Titels »Einführung in Hibernate« (ISBN 978-3-8266-1794-2) 2007 by Redline GmbH, Heidelberg
Nähere Informationen unter: http://www.mitp.de/1794
Kapitel 1
Eine Einführung in Hibernate 3
list.add(new Message(text));
}
return list;
} catch (Exception e) {
log.log(Level.SEVERE,
"Nachricht konnte nicht abgerufen werden.", e);
throw new MotdException(
"Nachricht konnte nicht aus der Datenbank abgerufen werden.", e);
} finally {
if (p != null) {
try {
p.close();
} catch (SQLException e) {
log.log(Level.WARNING,
"Angegebene Verbindung konnte nicht geschlossen werden.", e);
}
}
if (c != null) {
try {
c.close();
} catch (SQLException e) {
log.log(Level.WARNING,
"Angegebene Verbindung konnte nicht geschlossen werden.", e);
}
}
}
}
Listing 1.3:
Das POJO per JDBC abrufen
Einige dieser Codezeilen können verkürzt werden; es gibt verschiedene Methoden,
um die Codevorlagen für das Öffnen von Verbindungen und Protokollieren von Problemen zu reduzieren; aber die grundlegende Logik, die das Objekt aus dem
ResultSet herauszieht, nimmt mit der Komplexität des Objekts zu.
Wenn das Objekt Referenzen auf andere Objekte – oder noch schlimmer: auf Sammlungen von Objekten – enthält, werden die Mängel dieser »manuellen« Methoden
immer deutlicher.
1.2.1
EJBs als Persistenz-Lösung
Und was ist mit EJBs, um Daten abzurufen? Schließlich wurden Entity Beans speziell für den Zweck konzipiert, Daten in der Datenbank zu repräsentieren, zu speichern und abzurufen.
Streng genommen unterstützt eine Entity Bean bei einem EJB-Server zwei Arten der
Persistenz: Bean-Managed-Persistenz (BMP) und Container-Managed-Persistenz
(CMP). Bei der BMP ist die Bean selbst dafür verantwortlich, den SQL-Code auszuführen, mit dem ihre Daten gespeichert und abgerufen werden. Anders ausgedrückt:
Hierbei muss der Autor die entsprechende JDBC-Logik inklusive der vorgeschriebenen Komponenten aus Listing 1.3 erstellen. Dagegen ist bei der CMP der Container
dafür verantwortlich, die Bean-Daten zu speichern und abzurufen. Doch warum
wird damit das Problem nicht gelöst?
22
© des Titels »Einführung in Hibernate« (ISBN 978-3-8266-1794-2) 2007 by Redline GmbH, Heidelberg
Nähere Informationen unter: http://www.mitp.de/1794
1.2
Die Ursprünge von Hibernate und des objektrelationalen Mappings
Hier sind nur einige der Gründe:
쐽
CMP Entity-Beans erfordern ein Eins-zu-eins-Mapping zu Datenbanktabellen.
쐽
Sie unterstützen Vererbungsbeziehungen nicht direkt.
쐽
Sie sind (so wird jedenfalls gesagt) langsam.
쐽
Jemand muss festlegen, welches Bean-Feld welcher Tabellenspalte zugeordnet
wird.
쐽
Sie erfordern spezielle Methodennamen. Werden diese nicht korrekt angewendet, scheitern die Entity-Beans stillschweigend.
쐽
Entity-Beans können nur in einer J2EE-Application-Server-Umgebung existieren
– sie sind als Lösung schwergewichtig.
쐽
Sie können nicht ohne Weiteres als »Allzweck«-Komponenten für andere Anwendungen extrahiert werden.
쐽
Sie können nicht serialisiert werden.
쐽
Sie existieren selten als portable Komponenten, die in eine fremde Anwendung
eingefügt werden können. Im Allgemeinen müssen Sie Ihre eigene EJB-Lösung
erstellen.
1.2.2 Hibernate als Persistenz-Lösung
Hibernate bietet für viele dieser Punkte eine Lösung oder verringert zumindest die
Schwere des Problems. Deshalb wollen wir auf die Punkte nacheinander eingehen.
Hibernate erfordert nicht, dass Sie ein POJO einer Tabelle zuordnen. Ein POJO kann
aus einer Auswahl von Tabellenspalten konstruiert werden; und mehrere POJOs
können in einer einzigen Tabelle gespeichert werden.
Hibernate unterstützt Vererbungsbeziehungen und die verschiedenen anderen Beziehungen zwischen Klassen direkt.
Obwohl Hibernate beim Starten einen gewissen Verwaltungsaufwand benötigt, um
seine Konfigurationsdateien zu verarbeiten, gilt es im Allgemeinen als schnelles
Tool. Diese Eigenschaft ist nur schwer zu quantifizieren; und der schlechte Ruf der
Entity-Beans ist zum Teil weniger auf ihre eigenen Mängel als auf die Fehler zurückzuführen, die diverse Entwickler beim Entwurf und Einsatz solcher Anwendungen
gemacht haben. Wie bei allen Fragen, die das Leistungsverhalten betreffen, sollten
Sie eigene Tests ausführen, statt sich auf Einzelberichte zu verlassen.
In Hibernate ist es möglich, aber nicht erforderlich, die Mappings zur DeploymentZeit zu spezifizieren. Die EJB-Lösung gewährleistet die Portabilität von Anwendungen über verschiedene Umgebungen hinweg, aber der Hibernate-Ansatz trägt dazu
bei, die Schwierigkeiten beim Einsatz einer Anwendung in einer neuen Umgebung
zu verringern.
23
© des Titels »Einführung in Hibernate« (ISBN 978-3-8266-1794-2) 2007 by Redline GmbH, Heidelberg
Nähere Informationen unter: http://www.mitp.de/1794
Kapitel 1
Eine Einführung in Hibernate 3
Die Hibernate-Persistenz erfordert keinen J2EE-Application-Server oder eine sonstige spezielle Umgebung. Sie ist deshalb viel besser für eigenständige Anwendungen
oder eine clientseitige Datenspeicherung in Umgebungen, in denen ein J2EE-Server
nicht unmittelbar verfügbar ist.
Hibernate verwendet POJOs, die sehr leicht und natürlich für einen Einsatz in anderen Anwendungen verallgemeinert werden können. Es gibt keine direkte Abhängigkeit von den Hibernate Libraries, weshalb POJOs für alle Zwecke eingesetzt werden
können, die keine Persistenz erfordern. Alternativ können sie auch mit anderen
»POJO-freundlichen« Methoden gespeichert werden.
Hibernate hat keine Probleme mit der Handhabung serialisierbarer POJOs.
Der vorhandene Code ist sehr umfangreich. Jedes Java-Objekt, das in einer Datenbank gespeichert werden kann, eignet sich als Kandidat für die Hibernate-Persistenz.
Deshalb ist Hibernate ein natürlicher Ersatz für Ad-hoc-Lösungen oder eine geeignete Persistenz-Engine für Anwendungen, in die noch keine Datenbank eingebunden ist. Indem Sie sich für die Hibernate-Persistenz entscheiden, binden Sie sich
außerdem nicht an spezielle Design-Entscheidungen für die Geschäftsobjekte Ihrer
Anwendung.
1.2.3
Eine dünne Lösung?
Ein Vorteil, der oft für Hibernate ins Feld geführt wird, bezeichnet es als »dünne«
(»thin« wie in »Thin Client«) Lösung. Leider ist die Bedeutung dieser Bezeichnung
sehr unscharf und sagt wenig darüber aus, welche Attribute von Hibernate eine solche Kategorisierung rechtfertigen.
Hibernate benötigt im Gegensatz zu EJBs keinen Anwendungsserver. Es kann deshalb für clientseitige Anwendungen verwendet werden, bei denen EJBs überhaupt
nicht in Frage kommen. Vielleicht macht dieser Aspekt Hibernate »dünn«.
Andererseits nutzt Hibernate eine ungewöhnlich große Anzahl unterstützender
Libraries.
Wenn Sie also die Download-Zeiten und den Speicherbedarf eines Applets als Kriterien heranziehen, sieht Hibernate etwas schwergewichtig aus, obwohl diese Faktoren
bei den heutigen schnellen Verbindungen und riesigen Festplatten wahrscheinlich
kaum noch ins Gewicht fallen.
1.3
Ein Hallo-Welt-Beispiel in Hibernate
Listing 1.4 zeigt, wie viel weniger Standardcode Hibernate im Vergleich zu dem
JDBC-Ansatz aus Listing 1.3 erfordert.
public static List getMessages(int messageId)
throws MessageException
{
SessionFactory sessions =
new Configuration().configure().buildSessionFactory();
24
© des Titels »Einführung in Hibernate« (ISBN 978-3-8266-1794-2) 2007 by Redline GmbH, Heidelberg
Nähere Informationen unter: http://www.mitp.de/1794
1.4
Mappings
Session session = sessions.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
List list = session.createQuery("from Message").list();
tx.commit();
tx = null;
return list;
} catch (HibernateException e) {
if (tx != null) tx.rollback();
log.log(Level.SEVERE,
"Nachricht konnte nicht abgerufen werden.", e);
throw new MotdException(
"Nachricht konnte nicht aus der Datenbank abgerufen werden.", e);
} finally {
session.close();
}
}
Listing 1.4:
Das POJO per Hibernate abrufen
Selbst bei diesem trivialen Beispiel könnte der Umfang des für den praktischen Einsatz erforderlichen Codes weiter reduziert werden – insbesondere in einer Application-Server-Umgebung. Beispielsweise würde die SessionFactory normalerweise
an anderer Stelle erstellt und der Anwendung als Java-Native-Directory-InterfaceRessource (JNDI-Ressource) zur Verfügung gestellt werden.
Beachten Sie, dass der manuelle Code, mit dem das Message-Objekt mit Daten
gefüllt wird, nicht gelöscht worden ist, sondern in eine externe Konfigurationsdatei
verlagert worden ist, die dieses Implementierungsdetail von der Hauptlogik isoliert.
Ein Teil des zusätzlichen Codes in dem Hibernate-3-Beispiel aus Listing 1.4 stellt tatsächlich Funktionalität (insbesondere Transaktionalität und Caching) zur Verfügung,
die über die des JDBC-Beispiels hinausgeht.
1.4
Mappings
Wir haben bereits angedeutet, dass Hibernate etwas braucht, das ihm sagt, welche
Tabellen zu welchen Objekten gehören (die Informationen werden gewöhnlich in
einer XML-Mapping-Datei zur Verfügung gestellt). Während einige Tools ihren
Benutzern riesige, schlecht dokumentierte XML-Konfigurationsdateien zumuten,
bildet Hibernate eine rühmliche Ausnahme – Sie erstellen und verbinden für jedes
POJO, das Sie der Datenbank zuordnen wollen, eine kleine, übersichtliche MappingDatei. Wenn Sie wollen, können Sie auch eine einzige monolithische Konfigurationsdatei erstellen, aber dies ist weder erforderlich noch empfehlenswert.
Für alle Hibernate-Konfigurationsdateien gibt es eine Document Type Definition
(DTD), weshalb Sie mit einem guten XML-Editor in der Lage sein sollten, beim
Erstellen der Dateien Funktionen wie Autocompletion (automatische Vervollständigung) und Autovalidation (automatische Validierung) zu nutzen. Alternativ können
sie durch Java-5-Annotationen komplett ersetzt werden.
25
© des Titels »Einführung in Hibernate« (ISBN 978-3-8266-1794-2) 2007 by Redline GmbH, Heidelberg
Nähere Informationen unter: http://www.mitp.de/1794
Kapitel 1
Eine Einführung in Hibernate 3
Listing 1.5 zeigt, wie das Message-POJO auf die Datenbank abgebildet wird.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Message" table="Message">
<id type="int" column="id">
<generator class="native"/>
</id>
<property name="message" column="message" type="string"/>
</class>
</hibernate-mapping>
Listing 1.5:
Die XML-Datei, die das POJO der Datenbank zuordnet
Es wäre vernünftig zu fragen, ob nicht die Komplexität einfach aus dem Anwendungscode in die XML-Mapping-Datei verlagert worden ist. Tatsächlich ist dies
jedoch aus mehreren Gründen nicht der Fall:
Erstens: Die XML-Datei lässt sich sehr viel einfacher bearbeiten als eine komplexe
Besiedlung eines POJOs anhand einer Ergebnismenge. Sie lässt sich auch nachträglich sehr viel einfacher korrigieren, falls sich Ihre Datenbank-Mappings in der Endphase der Entwicklung ändern.
Zweitens: Die komplizierte Fehlerbehandlung, die bei dem JDBC-Ansatz erforderlich war, ist komplett entfallen. Doch dies ist wahrscheinlich der schwächste Grund,
da es verschiedene Methoden gibt, diesen Aufwand zur verringern, ohne auf Hibernate zurückzugreifen.
Schließlich ist besonders anzumerken, dass Hibernate das Problem löst, ein einzelnes Objekt aus der Datenbank abzurufen, das durch Referenzen mit einer beträchtlichen Anzahl anderer Objekte in der Datenbank verbunden ist. Hibernate schiebt
diese zusätzlichen Abrufe auf, bis die Daten tatsächlich benötigt werden, und vermeidet dadurch im Allgemeinen beträchtliche Speicher- und Leistungskosten.
1.5
Datenbankerstellung
Wenn Sie eine neue Hibernate-Anwendung für eine vorhandene Datenbank erstellen, ist der Entwurf des Datenbankschemas kein Problem; es wird Ihnen fertig präsentiert. Wenn Sie dagegen eine neue Anwendung starten, müssen Sie das Schema,
die POJOs und das Mapping direkt erstellen.
Auch hier erleichtert Ihnen Hibernate die Arbeit. Es stellt Ihnen einen Satz von
Werkzeugen zur Verfügung, mit denen Sie Ihre Datenbank direkt aus der MappingDatei generieren können (im Allgemeinen mit einem Ant-Script). Dies ist in der Praxis noch besser als in der Beschreibung! Hibernate kennt verfügt über detaillierte
Kenntnisse verschiedener SQL-Dialekte, so dass das Schema genau auf Ihre spezielle
Datenbank-Software zugeschnitten ist – oder für beliebige andere Datenbanken
generiert werden kann, mit denen Sie Ihre Anwendung einsetzen wollen.
26
© des Titels »Einführung in Hibernate« (ISBN 978-3-8266-1794-2) 2007 by Redline GmbH, Heidelberg
Nähere Informationen unter: http://www.mitp.de/1794
1.6
Die Beziehung zwischen Hibernate 3 und EJB 3.0
1.6
Die Beziehung zwischen Hibernate 3 und EJB 3.0
Die aktuelle Version (3.0) von EJB wurde als Java Specification Request (JSR) 220
entwickelt und enthält einen EJB-ORM-Standard. Warum sollten Sie Hibernate lernen, wenn gerade ein neuer Standard mit dem Segen von Sun veröffentlicht worden
ist? Weil die ursprünglichen Entwickler von Hibernate intensiv an der Erstellung des
neuen Standards mitgewirkt haben und weil Hibernate als eine der erfolgreichsten
ORM-Lösungen einen großen Einfluss auf den Entwurf von EJB 3.0 gehabt hat.
Hibernate unterstützt die Teile von EJB 3.0, die sich auf ORM beziehen.
EJB 3.0 unterstützt und ermutigt die Anwendung der transparenten Persistenz von
Entity-Beans, die dieselben minimalen Anforderungen erfüllen wie die POJOs, die
von Hibernate unterstützt werden. Deshalb kann Hibernate als Implementierung
der EntityManager-Komponente eines EJB-Containers verwendet werden.
Auch die HQL (Hibernate Query Language) von Hibernate hat eine enge Verbindung
zu der neuen EJB Query Language (EJB QL) – obwohl dies wahrscheinlich eher auf
ihre gemeinsame Vorgängerin, die Structured Query Language (SQL), zurückzuführen ist als auf die Teilnahme des Hibernate-Teams an der Entwicklung des Standards.
In EJB 3.0 können die Beziehungen zwischen Entities/POJOs und der Datenbank
mit Annotations beschrieben werden, die Hibernate unterstützt. Dieser Ansatz ist so
bequem, dass er wahrscheinlich die Standardmethode zur Verwaltung dieser Mappings werden wird, wenn immer mehr Java-5-Anwendungen eingesetzt werden.
Hibernate 3 stellt Funktionen zur Verfügung, die über das hinausgehen, was der EJB3.0-Standard fordert; und es erfordert nicht die Anwesenheit und Last eines Anwendungsservers, wodurch es sich auch für Swing-Anwendungen, andere clientseitige
Anwendungen und leichtgewichtige Webanwendungen eignet, die ohne einen vollständigen J2EE Stack laufen (etwa Anwendungen, die unter Tomcat laufen).
Kurz gesagt: Wenn Sie heute mit Hibernate 3 entwickeln, wird der Aufwand für
einen späteren Übergang zu EJB 3.0 allenfalls minimal sein. Außerdem ist Hibernate 3 heute verfügbar und hat einen überzeugenden Stammbaum.
1.7
Zusammenfassung
In diesem Kapitel haben wir die Probleme und Anforderungen behandelt, die zur
Entwicklung von Hibernate geführt haben. Wir haben einige Einzelheiten einer trivialen Beispielanwendung beleuchtet, die einmal ohne und einmal mit Hibernate
geschrieben wurde. Wir haben einige Implementierungsdetails gestreift, auf die wir
ausführlich in Kapitel 3 eingehen.
Im nächsten Kapitel werden wir die Architektur von Hibernate sowie seine Integration in Ihre Anwendungen beschreiben.
27
© des Titels »Einführung in Hibernate« (ISBN 978-3-8266-1794-2) 2007 by Redline GmbH, Heidelberg
Nähere Informationen unter: http://www.mitp.de/1794
Herunterladen