From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/html/k100289.html | 680 +++++++++++++++++++++ 1 file changed, 680 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100289.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100289.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100289.html b/Master/Reference Architectures and Patterns/hjp5/html/k100289.html new file mode 100644 index 0000000..30e17ee --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100289.html @@ -0,0 +1,680 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 45 - Objektorientierte Persistenz +
+
+ + + + +

45.2 Datenbank-Tabellen und Javaobjekte

+
+ +
+ + + + +

45.2.1 Eine einfache Javaklasse für Tabellen

+ +

+Wenn wir uns an die Tabelle dir +aus Kapitel 42 erinnern, könnten +wir auf die Idee kommen, dass diese auch durch eine Java Bean repräsentiert +werden kann, deren Instanzen die Datensätze repräsentieren. +Zur Erinnerung - und damit Sie nicht immer hin- und herblättern +müssen - sei hier noch einmal die Tabellenstruktur angeführt: + +

+ + + + + + + + + + + + + + + + + + + + + + +
Name Typ Bedeutung
did INT Primärschlüssel
dname CHAR(100) Verzeichnisname
fatherdid INT Schlüssel Vaterverzeichnis
entries INT Anzahl der Verzeichniseinträge
+

+Tabelle 45.1: Die Struktur der dir-Tabelle

+ +

+Der Einfachheit halber wollen wir uns hier auf die Tabelle dir +der Datenbank konzentrieren, obwohl die Java Bean für die Klasse +file ganz analog wäre. Hierfür entwerfen wir zunächst +eine einfache Javaklasse mit Variablen, die den Attributen der Datenbank-Tabelle +entsprechen. Jede Instanz der Klasse kann damit eine Zeile bzw. einen +Datensatz der Tabelle repräsentieren. + + +

+ + + + +
+ +
+001 /**
+002  * Diese Klasse repräsentiert die Tabelle 'dir' der 'DirDB'
+003  * Jede Instanz der Klasse repräsentiert wiederum einen
+004  * Datensatz
+005  */
+006 public class Directory {
+007 
+008   // Variablen die den Attributen der Tabelle entsprechen
+009   private int did;
+010   private String dname;
+011   private int fatherid;
+012   private int entries;
+013 
+014   /**
+015    * Ein einfacher Konstruktor ohne Initialisierung der
+016    * Objektvariablen
+017    */
+018   public Directory() {
+019   }
+020 
+021   /**
+022    * Konstruktor zum Erzeugen von Instanzen der Klasse
+023    */
+024   public Directory(int did,
+025                    String dname,
+026                    int fatherid,
+027                    int entries)
+028   {
+029       this.did = did;
+030       this.dname = dname;
+031       this.fatherid = fatherid;
+032       this.entries = entries;
+033   }
+034 
+035   // Zugriffsmethoden, um die Daten
+036   // Lesen und Schreiben zu können  
+037   public int getDid()
+038   {
+039     return did;
+040   }
+041 
+042   public void setDid(int did)
+043   {
+044     this.did = did;
+045   }
+046 
+047   public String getDname()
+048   {
+049     return dname;
+050   }
+051 
+052   public void setDname(String dname)
+053   {
+054     this.dname = dname;
+055   }
+056 
+057   public int getFatherid()
+058   {
+059     return fatherid;
+060   }
+061 
+062   public void setFatherid(int fatherid)
+063   {
+064     this.fatherid = fatherid;
+065   }
+066 
+067   public int getEntries()
+068   {
+069     return entries;
+070   }
+071 
+072   public void setEntries(int entries)
+073   {
+074     this.entries = entries;
+075   }
+076 
+077   public String toString() 
+078   {
+079     return "Directory[id:"+ did + ", name:" + dname +  "]";
+080   }    
+081 }
+
+
+ +Listing 45.1: Eine Klasse für die dir-Tabelle

+ +

+Wie wir sehen enthält die Klasse Directory +für jedes Datenbank-Attribut eine äquivalente Variable, +die über Getter-Methoden ausgelesen und über Setter-Methoden +verändert werden kann. Derartige Javaobjekte werden auch als +Java Beans bezeichnet, die wir in Abschnitt 44.1 +kennen gelernt haben. + + + + +

45.2.2 Verknüpfen der Javaklasse mit der Datenbank

+ +

+Die soeben erstellte Javaklasse ist sehr einfach und entspricht auf +triviale Weise der Datenbank-Tabelle, jedoch müssen wir diese +Verknüpfung Java auch direkt und unmissverständlich anzeigen. +Hierzu bedienen wir uns zusätzlicher Metainformationen in Form +so genannter Annotationen, die in Abschnitt 43.6 +beschrieben wurden. + +

+Diese Metainformationen beeinflussen die Klasse oder den Programmablauf +in keiner Weise, können jedoch zur Laufzeit - zum Beispiel über +die Reflection API - ausgelesen werden. Die in den Annotationen hinterlegten +Informationen teilen der Persistenzschicht dabei mit, welche Tabelle +der Datenbank und welche Spalten auf die jeweiligen Attribute abgebildet +werden. Das folgende Listing zeigt die hierfür notwendigen Erweiterungen: + + +

+ + + + + +
+ +
+001 import javax.persistence.*;
+002 
+003 /**
+004  * Diese Klasse repräsentiert die Tabelle 'dir' der 'DirDB'
+005  * Jede Instanz der Klasse repräsentiert wiederum einen
+006  * Datensatz
+007  */
+008 @Entity
+009 @Table( name = "dir" )
+010 public class Directory {
+011 
+012   // Variablen die den Attributen der Tabelle entsprechen
+013   private int did;
+014   private String dname;
+015   private int fatherid;
+016   private int entries;
+017 
+018   /**
+019    * Ein einfacher Konstruktor ohne Initialisierung der
+020    * Objektvariablen
+021    */
+022   public Directory() {
+023   }
+024 
+025   /**
+026    * Konstruktor mit Initialisierung der Variablen
+027    */
+028   public Directory(int did,
+029                    String dname,
+030                    int fatherid,
+031                    int entries)
+032   {
+033     this.did = did;
+034     this.dname = dname;
+035     this.fatherid = fatherid;
+036     this.entries = entries;
+037   }
+038 
+039   // Zugriffsmethoden, um die Daten der Klasse
+040   // Auslesen und Schreiben zu können
+041   @Id
+042   @Column( name = "id" )
+043   public int getDid()
+044   {
+045     return did;
+046   }
+047 
+048   public void setDid(int did)
+049   {
+050     this.did = did;
+051   }
+052 
+053   @Column( name = "dname", nullable = false ) 
+054   public String getDname()
+055   {
+056     return dname;
+057   }
+058 
+059   public void setDname(String dname)
+060   {
+061     this.dname = dname;
+062   }
+063 
+064   @Column ( name = "fatherid" )
+065   public int getFatherid()
+066   {
+067     return fatherid;
+068   }
+069 
+070   public void setFatherid(int fatherid)
+071   {
+072     this.fatherid = fatherid;
+073   }
+074 
+075   @Column ( name = "entries" )
+076   public int getEntries()
+077   {
+078     return entries;
+079   }
+080 
+081   public void setEntries(int entries)
+082   {
+083     this.entries = entries;
+084   }
+085     
+086   public String toString() 
+087   {
+088     return "Directory[id:"+ did + ", name:" + dname +  "]";
+089   }    
+090 }
+
+
+Directory.java
+ +Listing 45.2: Annotierte Klasse für die dir-Tabelle

+ +

+Wenn wir dieses Listing mit dem vorangegangenen vergleichen, sehen +wir, dass lediglich einige Annotationen hinzugekommen sind. Sie enthalten +Informationen, die Java benötigt, um die Instanzen der Klasse +mit der Tabelle in der Datenbank zu verknüpfen. Die Annotationen +für das Java Persistenz API können entweder über den +Variablen der Klasse selbst oder über die damit verknüpften +Getter-Methoden stehen. Die Reihenfolge der Methoden spielt keine +Rolle. + +

+Die Annotationen haben folgende Bedeutung: + +

+ + + + + + + + + + + + + + + + + +
Annotation Beschreibung
@Entity +Markiert die Klasse als persistierbares, +dass heißt mit einer Datenbank verknüpftes Objekt
@Table +Bezeichnet die verknüpfte Datenbanktabelle
@Id +Markiert das Attribut als Primärschlüssel +der Datenbank. Das ist z.B. für Suchoperationen wichtig
@Column +Verknüpft das Attribut mit einer Datenbankspalte
+

+Tabelle 45.2: Die Struktur der dir-Tabelle

+ +

+Die Annotationen Table +und Column +besitzen jeweils das Attribut name, +das den Namen der verknüpften Tabelle bzw. Spalte enthält. +Ist dieser Name identisch mit dem Namen des Javaattributes kann die +Angabe auch weggelassen werden. Allerdings empfehlen wir Ihnen - schon +allein um die Dokumentation zu erhöhen - diese Angabe mit aufzunehmen. +Zeile 053 zeigt zudem, dass +die Annotationen weitere Attribute aufnehmen können, mit denen +die Struktur und Beschränkungen der Datenbank granular konfiguriert +werden können. + +

+Die Annotation @Column unterstützt +folgende Attribute + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Attribut Typ Beschreibung Standardwert
name +String +Name der Tabellenspalte Name des Java Bean Attributs
length +int +Maximale Länge des Eintrags 255
table +String +Name einer Tabelle Namen der Tabelle dieser Java Bean
nullable +boolean +Sind null-Werte +erlaubt? true
insertable +boolean +Darf dieser Wert mit INSERT Statements verändert +werden? true
updateable +boolean +Darf dieser Wert mit UPDATE Statements geändert +werden? true
+

+Tabelle 45.3: Attribute der Annotation @Column

+

+ + + + + + + + + + + +
+ +

+Egal welche Konstruktoren wir für die mit der Datenbank verknüpfte +Java Bean vorsehen, das Persistenz Framework benötigt zusätzlich +einen »leeren« Standardkonstruktor. Bei Bedarf können +Sie dessen Sichtbarkeit auch auf protected +setzen und damit für andere Klassen weitestgehend einschränken. +Er muss jedoch vorhanden sein, da das Framework sonst nicht mit der +Java Bean arbeiten kann!

+ + + + +
 Warnung 
+
+ + + + +

45.2.3 Konfiguration des Datenbank-Zugriffs

+ +

+Jetzt haben wir eine Java Bean erstellt, die in der Lage, ist einen +Datensatz der Tabelle dir aufzunehmen +und diese zudem mit Zusatzinformationen ausgestattet, um die Verknüpfung +zwischen Datenbank auf Javaklasse beschreiben. Was noch fehlt sind +Informationen darüber, in welcher Datenbank sich die entsprechenden +Tabellen befinden. + +

+Natürlich könnten diese Informationen theoretisch ebenfalls +in der Javaklasse abgelegt werden, dies würde jedoch zu unflexiblem +Code führen, der nicht mit verschiedenen Datenbanken zusammenarbeiten +könnte. Um die tatsächliche Datenbank auch im Nachhinein +flexibel austauschen und beispielsweise statt der Hypersonic DB eine +Access Datenbank verwenden zu können, werden diese Konfigurationsdaten +in einer separaten Datei gepflegt. Diese wird auch als Persistence +Descriptor bezeichnet und könnte +beispielsweise folgende Form haben: + + +

+ + + + + +
+ +
+001 <?xml version="1.0" encoding="ISO-8859-1"?>
+002 
+003 <!-- Persistenz Descriptor zur Konfiguration -->
+004 <persistence>
+005 
+006   <!-- Hinterlegen eines symbolischen Namens -->
+007   <persistence-unit name="persistenceExample" 
+008                     transaction-type="RESOURCE_LOCAL">
+009 
+010     <!-- Zu verwendende Implementierung -->
+011     <provider>org.hibernate.ejb.HibernatePersistence</provider>
+012 
+013     <!-- Persistierbare Klassen -->
+014     <class>Directory</class> 
+015 
+016     <!-- Konfiguration der Hibernate Implementierung -->
+017     <properties>
+018       <!-- Name des intern verwendeten JDBC-Treibers -->
+019       <property name="hibernate.connection.driver_class"
+020                 value="org.hsqldb.jdbcDriver"/> 
+021 
+022       <!-- URL der zu verwendenden Datenbank -->
+023       <property name="hibernate.connection.url"
+024                 value="jdbc:hsqldb:hsqldbtest"/> 
+025 
+026       <!-- SQL-Dialect, den Hibernate verwenden soll -->
+027       <property name="hibernate.dialect"
+028                 value="org.hibernate.dialect.HSQLDialect"/>
+029 
+030       <!-- Benutzername und Passwort; Standardwerte der HSQLDB -->
+031       <property name="hibernate.connection.username" value="SA"/> 
+032       <property name="hibernate.connection.password" value=""/> 
+033 
+034       <!-- Flag, ob Tabellen automatisch erzeugt werden sollen -->
+035       <property name="hibernate.hbm2ddl.auto" value="create"/> 
+036 
+037       <!-- Flag, ob SQL-Statements ausgegeben werden sollen -->
+038       <property name="hibernate.show_sql" value="true"/> 
+039     </properties>
+040   </persistence-unit>
+041 </persistence>
+
+
+persistence.xml
+ +Listing 45.3: Konfigurationsdatei für das Java Persistenz API

+ +

+Diese Datei muss unter dem Namen persistence.xml +im Classpath abgelegt werden, und schon kann das Persistenz API die +Klasse Directory mit der Tabelle +dir in der HSQLDB verknüpfen. +Am einfachsten ist dies zu bewerkstelligen, indem die Datei persistence.xml +gemeinsam mit der kompilierten Class-Datei Directory.class +gespeichert wird. + + + + +

Aufbau der Konfigurationsdatei

+ +

+Die Konfigurationsdatei ist in einzelne Seqmente aufgeteilt, die verschiedene +Aufgaben besitzen. Listing 45.3 +ist so vorkonfiguriert, dass es mit der HSQLDB aus Kapitel Kapitel 42 +verwenden werden kann. Um auf die Tabellen einer anderen Datenbank +zuzugreifen müssen der Datenbanktreiber, die URL und die Zugangsdaten +angepasst werden. Wenn wir dieses Listing mit Listing 42.3 +vergleichen, sollten uns viele Optionen vertraut vorkommen. Diese +sind nun nicht mehr fest in die Javaklasse einkompiliert, sondern +können in einer separaten Datei gewartet werden. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Zeile Beschreibung der Konfigurationseinstellung
Zeile 007 +Ein symbolischer Name für die Konfiguration, +den wir später für den Zugriff verwenden werden
Zeile 014 +Liste der Klassen, die mit der Datenbank +verknüpft werden sollen
Zeile 020 +Name des passenden JDBC-Treibers
Zeile 024 +Name der Datenbank
Zeile 031 +Benutzername für den Zugriff auf die +Datenbank
Zeile 032 +Passwort für den Zugriff auf die Datenbank
Zeile 035 +Gibt an, ob die Tabellen bei Bedarf dynamisch +erstellt werden sollen
Zeile 038 +Gibt an, ob die intern verwendeten SQL-Statements +auf der Kommandozeile ausgegeben werden sollen
+

+Tabelle 45.4: Anpassen der Konfigurationsdatei

+ +

+Nachdem wir die Datei persistence.xml +zusammen mit der Directory-Class +abgelegt haben können wir nun mit dem Java Persistenz API arbeiten +

+ + + + + + + + + +
+ +

+Die vorangegangenen Schritte erscheinen Ihnen vielleicht aufwändiger +als die vermeintlichen Pendants im Kapitel über JDBC. Der Vorteil +des Java Persistenz API liegt jedoch vor allem in der wesentlich einfacheren +Anwendung, mit der wir uns im folgenden Abschnitt beschäftigen +werden. + +

+Die gute Nachricht ist: Nachdem wir die Verknüpfung zwischen +Javaklasse und Datenbank nun konfiguriert haben, können wir nachfolgend +einfach mit der Directory-Klasse +arbeiten, ohne uns weiter um SQL oder Datenbank-Aspekte kümmern +zu müssen.

+ + + + +
 Hinweis 
+
+


+ + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 +
 <<  +  <   +  >   + >>  + API  +© 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de +
+ + + -- cgit v1.2.3