| Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 6. Auflage |
| << | < | > | >> | API | Kapitel 45 - Objektorientierte Persistenz |
Die voranstehenden Abschnitte haben Ihnen gezeigt, wie Sie einfache Tabellen der Datenbank mit Hilfe von Java Beans abbilden und Datensätze über den EntityManager anlegen, manipulieren und löschen können. Hierbei wurde die Tabelle eins zu eins als Java-Objekt abgebildet, ohne auf die objektorientierte Struktur der verknüpften Datensätze einzugehen. Werfen wir noch einmal einen Blick auf das E/R-Diagramm der Datenbank aus Abschnitt 42.3.
Abbildung 45.2: E/R-Diagramm für DirDB
Wie in Abbildung 45.2 zu sehen ist, besitzt ein Verzeichnis zunächst nur eine Id did und einen Namen dname. Der in Listing 45.2 modellierte Schlüssel fatherdid verweist hingegen auf einen übergeordneten Datensatz, also ein Elternverzeichnis und statt lediglich die Anzahl der Verzeichniseinträge entries abzubilden, wäre es schön wenn wir stattdessen gleich Zugriff auf die entsprechenden Objekte hätten. Dies wollen wir im zweiten Teil dieses Kapitels mit Hilfe der JPA realisieren.
Als Erstes wollen wir uns dem Abbilden von Datenbanktabellen noch einmal von der objektorientierten Herangehensweise annähern. Dabei besteht ein Directory-Objekt zunächst einmal aus einem Namen und einer Id. Während Ersterer vom Anwender selbst vergeben werden muss und damit ein Pflichtattribut darstellt, handelt es sich bei der Id um einen technischen Schlüssel der Datenbank, den der Anwender zwar auslesen, jedoch nicht wahllos ändern kann. Listing 45.9 zeigt die Java Bean im Ausgangsstadium.
001 /* Listing4509.java */
002
003 import javax.persistence.*;
004
005 /**
006 * Diese Klasse repräsentiert die Tabelle 'dir' der 'DirDB'
007 * Jede Instanz der Klasse repräsentiert wiederum einen
008 * Datensatz
009 */
010 public class Directory {
011
012 private Integer id;
013
014 private String name;
015
016 /**
017 * Geschützter Minimalkonstruktor zur Verwendung von Hibernate
018 */
019 protected Directory() {
020 }
021
022 /**
023 * Öffentlicher Konstruktor zur Verwendung durch den Entwickler.
024 * Dieser Konstruktor definiert alle Pflichtfelder der JavaBean.
025 * @param name - Name des Verzeichniseintrags
026 */
027 public Directory(String name)
028 {
029 this.name = name;
030 }
031
032 public Integer getId()
033 {
034 return id;
035 }
036 protected void setId(Integer id)
037 {
038 this.id = id;
039 }
040
041 public String getName()
042 {
043 return name;
044 }
045 public void setName(String name)
046 {
047 this.name = name;
048 }
049
050 public boolean equals(Object o)
051 {
052 if (this == o) return true;
053 if (o == null || getClass() != o.getClass()) return false;
054
055 Directory dir = (Directory) o;
056 return !(id != null ? !id.equals(dir.id) : dir.id != null);
057 }
058
059 public int hashCode()
060 {
061 return id != null ? id.hashCode() : 0;
062 }
063
064 public String toString()
065 {
066 return "Directory[id:"+ id + ", name:" + name + "]";
067 }
068 }
|
Listing4509.java |
Die Klasse Directory in Listing 45.9 bildet zunächst nur die beiden Attribute id in Zeile 012 und name in Zeile 014 ab. Die Namen der Attribute orientieren sich hierbei an den Java-Konventionen und berücksichtigen in keiner Weise die möglichen Vorgaben der Datenbank. Des Weiteren wird darauf geachtet, dass der öffentliche Konstruktor das Pflichtfeld name übernimmt, so dass kein namenloses Verzeichnis erstellt werden kann.
Der parameterlose Konstruktor in Zeile 019 ist dem Persistenz-Framework geschuldet, das zwingend einen Standardkonstruktor benötigt. Um dessen Verwendung in der Anwendung jedoch einzuschränken wird die Sichtbarkeit über den Modifier protected eingeschränkt.
Da die Id des Datensatzes in diesem Beispiel ausnahmslos von der Persistenzschicht verwaltet werden soll, ist in Zeile 036 auch der Zugriff auf dieses Attribut eingeschränkt.
Eine weitere Neuerung gegenüber Listing 45.2 findet sich schließlich in der Verwendung des Objekttyps Integer statt des Basistyps int für die Id des Datensatzes. Der Objekttyp hat gegenüber den Basistypen den Vorteil, dass er auf null belassen werden und damit einen nicht definierten Zustand abbilden kann. Dies ist beispielsweise dann der Fall, wenn die Instanz zwar über einen Konstruktor erzeugt, aber noch nicht in der Datenbank gespeichert wurde.
Abschließend wird die Klasse Directory um die Methoden equals und hashCode aus Abschnitt 8.1.2 erweitert, um die Identität eines Datensatzes überprüfen zu können. Diese Methoden stellen sicher, dass Hibernate einen in der Datenbank eindeutig referenzierten Datensatz über dessen Id auch javaseitig identifizieren und beispielsweise das doppelte Laden einer logisch identischen Instanz vermeiden kann.
Als Nächstes versehen wir die Java Bean mit den für die Persistenzschicht notwendigen Metainformationen und verknüpfen diese so mit der im Hintergrund arbeitenden Datenbank. Als Alternative zu Listing 45.2 werden wir die Annotationen diesmal direkt an den Attributen, statt an den zugehörigen Gettern anbringen.
001 /* Listing4510.java */
002
003 import javax.persistence.*;
004
005 /**
006 * Diese Klasse repräsentiert die Tabelle 'dir' der 'DirDB'
007 * Jede Instanz der Klasse repräsentiert wiederum einen
008 * Datensatz
009 */
010 @Entity
011 @Table( name = "dir" )
012 public class Directory {
013
014 @Id
015 @GeneratedValue
016 @Column(name = "did")
017 private Integer id;
018
019 @Column(name = "dname")
020 private String name;
021
022 /**
023 * Geschützter Minimalkonstruktor zur Verwendung von Hibernate
024 */
025 protected Directory() {
026 }
027
028 /**
029 * Öffentlicher Konstruktor zur Verwendung durch den Entwickler.
030 * Dieser Konstruktor definiert alle Pflichtfelder der JavaBean.
031 * @param name - Name des Verzeichniseintrags
032 */
033 public Directory(String name)
034 {
035 this.name = name;
036 }
037
038 public Integer getId()
039 {
040 return id;
041 }
042 protected void setId(Integer id)
043 {
044 this.id = id;
045 }
046
047 public String getName()
048 {
049 return name;
050 }
051 public void setName(String name)
052 {
053 this.name = name;
054 }
055
056 public boolean equals(Object o)
057 {
058 if (this == o) return true;
059 if (o == null || getClass() != o.getClass()) return false;
060
061 Directory dir = (Directory) o;
062 return !(id != null ? !id.equals(dir.id) : dir.id != null);
063 }
064
065 public int hashCode()
066 {
067 return id != null ? id.hashCode() : 0;
068 }
069
070 public String toString()
071 {
072 return "Directory[id:"+ id + ", name:" + name + "]";
073 }
074 }
|
Listing4510.java |
Die Annotationen @Entity, @Table, @Id und Column sind ja bereits mit Listing 45.2 eingeführt worden. Neu hinzugekommen ist nun die Annotation @GeneratedValue in Zeile 015. Diese zeigt der Persistenzschicht an, dass der Wert des Attributs automatisch erzeugt und nicht vom Benutzer gesetzt werden soll.
Nun können wir ganz analog zur Klasse Directory die Klasse File mit dem Pflichtattribut name definieren. Dabei bilden wir der Einfachheit halber das Änderungsdatum einer Datei über ein einzelnes Attribut mit Namen date ab.
001 /* Listing4511.java */
002
003 import javax.persistence.*;
004 import java.util.Date;
005
006 /**
007 * Diese Klasse repräsentiert die Tabelle 'file' der 'DirDB'
008 * Jede Instanz der Klasse repräsentiert wiederum einen
009 * Datensatz
010 */
011
012 @Entity
013 @Table( name = "file" )
014 public class File {
015
016 @Id
017 @GeneratedValue
018 @Column(name = "fid")
019 private Integer id;
020
021 @Column(name = "fname")
022 private String name;
023
024 @Column(name = "dsize")
025 private Integer size;
026
027 @Column(name = "fdate")
028 private Date date;
029
030 /**
031 * Geschützter Minimalkonstruktor zur Verwendung durch
032 * die Persistenzschicht
033 */
034 protected File() {
035 }
036
037 /**
038 * Öffentlicher Konstruktor zur Verwendung durch den Entwickler.
039 * Dieser Konstruktor definiert alle Pflichtfelder der JavaBean.
040 * @param name - Name der Datei
041 */
042 public File(String name)
043 {
044 this.name = name;
045 }
046
047 public Integer getId()
048 {
049 return id;
050 }
051 protected void setId(Integer id)
052 {
053 this.id = id;
054 }
055
056 public String getName()
057 {
058 return name;
059 }
060 public void setName(String name)
061 {
062 this.name = name;
063 }
064
065 public Integer getSize()
066 {
067 return size;
068 }
069 public void setSize(Integer size)
070 {
071 this.size = size;
072 }
073
074 public Date getDate()
075 {
076 return date;
077 }
078 public void setDate(Date date)
079 {
080 this.date = date;
081 }
082
083 public boolean equals(Object o)
084 {
085 if (this == o) return true;
086 if (o == null || getClass() != o.getClass()) return false;
087
088 File file = (File) o;
089 return !(id != null ? !id.equals(file.id) : file.id != null);
090 }
091
092 public int hashCode()
093 {
094 return id != null ? id.hashCode() : 0;
095 }
096
097 public String toString()
098 {
099 return "File[id:"+ id + ", name:" + name + "]";
100 }
101 }
|
Listing4511.java |
Um auch das File-Objekt über den EntityManager der Persistenzschicht verwalten zu können, müssen wir die Klasse noch im Persistence Deskriptor (persistence.xml) angeben. Hierfür erweitern wir Listing 45.3 wie in Zeile 015 gezeigt.
001 <?xml version="1.0" encoding="ISO-8859-1"?> 002 003 <!-- Persistence 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 <class>File</class> 016 017 <!-- Konfiguration der Hibernate Implementierung --> 018 <properties> 019 <!-- Name des intern verwendeten JDBC-Treibers --> 020 <property name="hibernate.connection.driver_class" 021 value="org.hsqldb.jdbcDriver"/> 022 023 <!-- URL der zu verwendenden Datenbank --> 024 <property name="hibernate.connection.url" 025 value="jdbc:hsqldb:hsqldbtest"/> 026 027 <!-- SQL-Dialect, den Hibernate verwenden soll --> 028 <property name="hibernate.dialect" 029 value="org.hibernate.dialect.HSQLDialect"/> 030 031 <!-- Benutzername und Passwort; Standardwerte der HSQLDB --> 032 <property name="hibernate.connection.username" value="SA"/> 033 <property name="hibernate.connection.password" value=""/> 034 035 <!-- Flag, ob Tabellen automatisch erzeugt werden sollen --> 036 <property name="hibernate.hbm2ddl.auto" value="create"/> 037 038 <!-- Flag, ob SQL-Statements ausgegeben werden sollen --> 039 <property name="hibernate.show_sql" value="true"/> 040 041 <!-- Flag, ob SQL-Statements formatiert werden sollen --> 042 <property name="hibernate.format_sql" value="true"/> 043 </properties> 044 </persistence-unit> 045 </persistence> |
persistence.xml.ext |
Das Speichern, Manipulieren und Löschen der Persistenz Beans erfolgt ganz analog zum ersten Beispiel in Listing 45.6. Der einzige Unterschied ist, dass wir die Id des Datensatzes nicht mehr selbst bestimmen, sondern von der Persistenzschicht verwalten lassen.
001 /* Listing4513.java */
002
003 import javax.persistence.*;
004
005 public class Listing4513
006 {
007 public static void main(String[] args)
008 {
009 //Erzeugen einer EntityManagerFactory mit Hilfe des symbolischen
010 //Namens aus dem Persistence Descriptor (persistence.xml)
011 EntityManagerFactory emf =
012 Persistence.createEntityManagerFactory("persistenceExample");
013
014 //Erzeugen eines EntityManagers für den Zugriff auf
015 //die Datenbank
016 EntityManager manager = emf.createEntityManager();
017
018 //Beginn einer neuen Transanktion
019 EntityTransaction tx = manager.getTransaction();
020 tx.begin();
021
022 //Erzeugen eines neuen Java-Objekts
023 Directory dir = new Directory("temp");
024
025 //Speichern des Java-Objekts mit Hilfe des EntityManagers
026 manager.persist(dir);
027
028 //Abschluss der Transaktion mit einem Commit
029 tx.commit();
030
031 // Ausgabe der Id des Datensatzes
032 System.out.println(dir.toString());
033
034 //Freigabe der Ressourcen des EntityManagers
035 manager.close();
036
037 //Schließen der EntityManagerFactory und Freigeben der
038 //belegten Ressourcen
039 emf.close();
040 }
041 }
|
Listing4513.java |
Das Directory-Objekt wird in
Zeile 023 nur noch
mit einem Namen initialisiert und erhält seine Id erst mit dem
Speichern in Zeile 026.
Die Ausgabe in Zeile 032
führt anschließend zu folgendem Ergebnis:
Directory[id:1, name:temp]
Nachdem Abschnitt 45.4.1 auf die automatische Verwaltung der Datenbankschlüssel durch die Persistenzschicht eingegangen ist zeigt dieser Abschnitt, wie die referentielle Integrität von Datenbanken objektorientiert modelliert werden kann.
Relationale Datenbanken verknüpfen Datensätze über Fremdschlüssel aus anderen Tabellen, um so die Zugehörigkeit eines Datensatzes anzuzeigen. In unserem Beispiel speichert jeder file-Datensatz die Id des zugehörigen dir-Datensatzes um eindeutig anzuzeigen, zu welchem Verzeichnis die jeweilige Datei gehört.
Solche Referenzen können in unterschiedlichen Kardinalitäten vorliegen, die in Tabelle 45.5 beschrieben werden. Beim Beispiel der Datei handelt es sich natürlich um eine N:1-Beziehung, da mehrere Dateien zu genau einem Verzeichniseintrag gehören können. Aus Sicht des Directory-Objekts würde es sich dann um eine 1:N-Beziehung handeln.
| Kurzform | Name | Bedeutung |
| 1:1 | Eins-zu-Eins | Jeder Datensatz einer Tabelle ist höchstens einem Datensatz in der anderen Tabelle zugeordnet |
| 1:N | Eins-zu-N | Dem Datensatz dieser Tabelle können mehrere Datensätze einer anderen Tabelle zugordnet sein |
| N:1 | N-zu-Eins | Mehrere Datensätze dieser Tabelle können auf ein und denselben Datensatz einer anderen Tabelle verweisen |
| M:N | M-zu-N | Der Datensatz kann von verschiedenen Datensätzen referenziert werden und gleichzeitig auf mehrere Datensätze verweisen |
Tabelle 45.5: Kardinalitäten für Datenbankbeziehungen
Diese Referenzen lassen sich auch mit der Persistenzschicht abbilden, wobei in diesem Fall eine Persistenz Bean auf eine oder mehrere andere verweist. In Listing 45.14 wird das Directory-Objekt nun um eine Liste von File-Objekten erweitert, um die zum Verzeichnis gehörenden Dateien aufzunehmen.
001 /* Listing4514.java */
002
003 import javax.persistence.*;
004 import java.util.List;
005 import java.util.LinkedList;
006
007 /**
008 * Diese Klasse repräsentiert die Tabelle 'dir' der 'DirDB'
009 * Jede Instanz der Klasse repräsentiert wiederum einen
010 * Datensatz
011 */
012 @Entity
013 @Table( name = "dir" )
014 public class Directory {
015
016 @Id
017 @GeneratedValue
018 @Column(name = "did")
019 private Integer id;
020
021 @Column(name = "dname")
022 private String name;
023
024 @OneToMany(cascade = CascadeType.ALL)
025 @OrderBy(value = "name")
026 private List<File> files;
027
028 /**
029 * Geschützter Minimalkonstruktor zur Verwendung von Hibernate
030 */
031 protected Directory() {
032 }
033
034 /**
035 * Öffentlicher Konstruktor zur Verwendung durch den Entwickler.
036 * Dieser Konstruktor definiert alle Pflichtfelder der JavaBean.
037 * @param name - Name des Verzeichniseintrags
038 */
039 public Directory(String name)
040 {
041 this.name = name;
042 this.files = new LinkedList<File>();
043 }
044
045 public Integer getId()
046 {
047 return id;
048 }
049 protected void setId(Integer id)
050 {
051 this.id = id;
052 }
053
054 public String getName()
055 {
056 return name;
057 }
058 public void setName(String name)
059 {
060 this.name = name;
061 }
062
063 public List<File> getFiles()
064 {
065 return files;
066 }
067 public void setFiles(List<File> files)
068 {
069 this.files = files;
070 }
071
072 public boolean equals(Object o)
073 {
074 if (this == o) return true;
075 if (o == null || getClass() != o.getClass()) return false;
076
077 Directory dir = (Directory) o;
078 return !(id != null ? !id.equals(dir.id) : dir.id != null);
079 }
080
081 public int hashCode()
082 {
083 return id != null ? id.hashCode() : 0;
084 }
085
086 public String toString()
087 {
088 return "Directory[id:"+ id + ", name:" + name + "]";
089 }
090 }
|
Listing4514.java |
Genau wie die Basisattribute einer Tabelle werden auch die referenzierten Datensätze über Annotationen mit den notwendigen Metainformationen verknüpft. Für eine 1:N-Relation genügt dabei prinzipiell die Angabe von @OneToMany in Zeile 024, wenn der referenzierte Typ File ebenfalls eine Persistenz Bean ist. Das Attribut cascade gestattet es das Persistenz-Framework anzuweisen, bestimmte Datenbankoperationen, wie beispielsweise das Löschen eines Directory auch auf die referenzierten Datensätze anzuwenden. Über den Parameter CascadeType.ALL in Listing 45.14 weisen wir das Framework an, alle Datenbankoperationen auf Verzeichnisebene auch auf die anhängenden Dateien anzuwenden.
Da die Dateiobjekte zu einem Verzeichnis jedoch nicht als ungeordnetes java.util.Set, sondern als nach Namen geordnete Liste ausgelesen werden sollen, fügen wir in Zeile 025 noch eine zweite Annotation @OrderBy hinzu. Diese bewirkt, dass die Datensätze nach dem Namen der referenzierten Java Bean sortiert werden. Die Bezeichnung der Datenbankspalte unter der der Name einer Datei abgespeichert wird, spielt hier keine Rolle, es zählt einzig der Name des Attributs in der Java Bean File.
Abschließend sollten wir noch verhindern, dass es bei einem Zugriff auf die File-Objekte eines Directory aufgrund einer nicht initialisierten Liste zu einer unschönen NullPointerException kommt, weshalb wir den öffentlichen Konstruktor erweitern und die Liste in Zeile 042 initialisieren. Bemerkenswert an dieser Stelle ist, dass wir den vom Persistenz-Framework verwendeten Minimalkonstruktor in Zeile 031 nicht entsprechend erweitern müssen: Auch wenn zu einem Verzeichnis keine Dateien existieren, wird das Persistenz-Framework refenzierende Collections stets leer initialisieren.
| Annotation | Beschreibung |
| @OneToMany | Modelliert eine 1:N-Relation |
| @ManyToOne | Modelliert eine N:1-Relation |
| @OneToOne | Modelliert eine 1:1-Relation |
| @ManyToMany | Modelliert eine M:N-Relation |
Tabelle 45.6: Annotationen zur Modellierung von Datenbankreferenzen
Alle Annotationen aus Tabelle 45.6 können über eine Reihe von Attributen konfiguriert werden, die in Tabelle 45.7 aufgeführt sind:
| Attribut | Beschreibung |
| cascade | Welche Datenbankoperationen sollen auch auf das referenzierte Objekt angewendet werden |
| fetch | Wann sollen die referenzierten Datensätze geladen werden FetchType.EAGER lädt die Datensätze sofort, FetchType.LAZY lädt die Datensätze nur bei Bedarf nach. |
| mappedBy | Name des Attributs im referenzierten Datensatz, das die inverse Relation abbildet. Wird nur benötigt, wenn mehrere Rückreferenzen in Frage kommen. |
| targetEntity | Typ des referenzierten Datensatzes. Wird nur benötigt, wenn dies nicht aus der typisierten Liste hervorgeht. |
Tabelle 45.7: Attribute der Annotationen für Datenbankreferenzen
Wir können auch die inverse Relation von einer Datei auf das zugehörige Verzeichnis abbilden. In diesem Fall handelt es sich um eine @ManyToOne-Beziehung, wie in Listing 45.15 gezeigt:
001 /* Listing4515.java */
002
003 import javax.persistence.*;
004 import java.util.Date;
005
006 /**
007 * Diese Klasse repräsentiert die Tabelle 'file' der 'DirDB'
008 * Jede Instanz der Klasse repräsentiert wiederum einen
009 * Datensatz
010 */
011
012 @Entity
013 @Table( name = "file" )
014 public class File {
015
016 @Id
017 @GeneratedValue
018 @Column(name = "fid")
019 private Integer id;
020
021 @Column(name = "fname")
022 private String name;
023
024 @Column(name = "dsize")
025 private Integer size;
026
027 @Column(name = "fdate")
028 private Date date;
029
030 @ManyToOne
031 @JoinColumn(name = "did")
032 private Directory directory;
033
034 /**
035 * Geschützter Minimalkonstruktor zur Verwendung von Hibernate
036 */
037 protected File() {
038 }
039
040 /**
041 * Öffentlicher Konstruktor zur Verwendung durch den Entwickler.
042 * Dieser Konstruktor definiert alle Pflichtfelder der JavaBean.
043 * @param name - Name der Datei
044 */
045 public File(String name)
046 {
047 this.name = name;
048 }
049
050 public Integer getId()
051 {
052 return id;
053 }
054 protected void setId(Integer id)
055 {
056 this.id = id;
057 }
058
059 public String getName()
060 {
061 return name;
062 }
063 public void setName(String name)
064 {
065 this.name = name;
066 }
067
068 public Integer getSize()
069 {
070 return size;
071 }
072 public void setSize(Integer size)
073 {
074 this.size = size;
075 }
076
077 public Date getDate()
078 {
079 return date;
080 }
081 public void setDate(Date date)
082 {
083 this.date = date;
084 }
085
086 public Directory getDirectory()
087 {
088 return directory;
089 }
090 public void setDirectory(Directory directory)
091 {
092 this.directory = directory;
093 }
094
095 public boolean equals(Object o)
096 {
097 if (this == o) return true;
098 if (o == null || getClass() != o.getClass()) return false;
099
100 File file = (File) o;
101 return !(id != null ? !id.equals(file.id) : file.id != null);
102 }
103
104 public int hashCode()
105 {
106 return id != null ? id.hashCode() : 0;
107 }
108
109 public String toString()
110 {
111 return "File[id:"+ id + ", name:" + name + "]";
112 }
113 }
|
Listing4515.java |
Nun sind die beiden Persistenz Beans Directory und File miteinander verknüpft und referenzieren sich in beide Richtungen. Aus Sicht der Java-Objekte können wir jetzt auf einfache Weise die Dateien eines Verzeichnisses ausgeben oder das Elternverzeichnis einer Datei ermitteln. Dank der Annotationen des Persistenz-Frameworks können wir uns ganz auf die objektorientierte Sichtweise konzentrieren und die Abbildung über Fremdschlüssel auf Seiten der Datenbank vollständig vergessen.
Listing 45.16 zeigt, wie die miteinander verknüpften Datensätze mit Hilfe des EntityManager gespeichert werden können. Hierbei machen wir uns das Attribut cascade aus Listing 45.14 zu nutze, das den Aufruf von persist auch auf die referenzierten File-Objekte anwendet.
001 /* Listing4516.java */
002
003 import javax.persistence.*;
004
005 public class Listing4516
006 {
007 public static void main(String[] args)
008 {
009 //Erzeugen einer EntityManagerFactory mit Hilfe des symbolischen
010 //Namens aus dem Persistence Descriptor (persistence.xml)
011 EntityManagerFactory emf =
012 Persistence.createEntityManagerFactory("persistenceExample");
013
014 //Erzeugen eines EntityManagers für den Zugriff auf
015 //die Datenbank
016 EntityManager manager = emf.createEntityManager();
017
018 //Beginn einer neuen Transanktion
019 EntityTransaction tx = manager.getTransaction();
020 tx.begin();
021
022 //Erzeugen und Verknüpfen der Java-Objekte
023 Directory dir = new Directory("temp");
024
025 File fileTest = new File("test.txt");
026 dir.getFiles().add(fileTest);
027 fileTest.setDirectory(dir);
028
029 File fileInfo = new File("info.txt");
030 dir.getFiles().add(fileInfo);
031 fileInfo.setDirectory(dir);
032
033 //Speichern des Verzeichnisses und der anhängenden Objekte
034 manager.persist(dir);
035
036 //Abschluss der Transaktion mit einem Commit
037 tx.commit();
038
039 //Freigabe der Ressourcen des EntityManagers
040 manager.close();
041
042 //Schließen der EntityManagerFactory und Freigeben der
043 //belegten Ressourcen
044 emf.close();
045 }
046 }
|
Listing4516.java |
| Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 6. Auflage, Addison Wesley, Version 6.0 |
| << | < | > | >> | API | © 1998, 2009 Guido Krüger & Thomas Stark, http://www.javabuch.de |