4. Java Persistence API (JPA) -...
Transcript of 4. Java Persistence API (JPA) -...
Prof. Dr. Stephan Kleuker
141Komponentenbasierte Software-Entwicklung
4. Java Persistence API (JPA)
• Problem: OO in relationale DB
• Idee des Persistence Mapper
• Einfache Entity-Klasse
• Lebenslauf eines Entity-Objekts
• Umsetzung von 1:N- und M:N-Relationen
• Geordnete Daten
• Anfragen
• Vererbung
• Validierung
Prof. Dr. Stephan Kleuker
142Komponentenbasierte Software-Entwicklung
Literatur
• JPA 2.0: Sun Microsystem: JSR 317: JavaTM Persistence 2.0 http://jcp.org/en/jsr/summary?id=317 (persistence-2_0_final-spec.pdf ist der Standard; trotzdem sehr gut lesbar!)
Auch für Teile der weiteren Vorlesung
• C. Bauer, G. King, Java Persistence with Hibernate, Manning, Greenwich (USA) 2007
• M. Keith, M. Schincariol, Pro EJB 3 - Java Persistence API, Apress, Berkeley (USA), 2006
Prof. Dr. Stephan Kleuker
143Komponentenbasierte Software-Entwicklung
Klassische Wege zur Verbindung SW und DB
DB werden meist nicht alleine entwickelt, sie müssen mit umgebender SW integriert werden. Es gibt verschiedene Ansätze, die gerade bei der Anbindung von OO-SW relevant sind:
- SW wird (z.B: mit PL/SQL) in der Datenbank entwickelt (hierzu gibt es auch objektorientierte Ansätze), externe SW kann auf Prozeduren und Funktionen zugreifen.
- SQL-Aufrufe werden direkt in die SW eingebettet (Embedded SQL) bzw. Aufrufe werden durch ein einfaches Framework (z.B. JDBC, SQLJ) gekapselt. (Frage: wie bekomme ich Objekte in die DB?)
- DB-Entwicklung und SW-Entwicklung wird eng miteinander verzahnt, hierzu stehen ausgereifte Development-Frameworks zur Verfügung (EJB, .NET)
Prof. Dr. Stephan Kleuker
144Komponentenbasierte Software-Entwicklung
Nutzung relationaler DB in OO-Programmen
• Bisheriger Ansatz: relationale DB vorhanden, wird an OO-Programm angeschlossen.
• Was ist, wenn DB zusammen mit OO-Programm entwickelt wird?
• erster Ansatz: warum nicht genau so vorgehen
relationale Datenbank
DB-Zugriffsschicht
Oberfläche + Geschäftslogik
z.B. JDBC
Prof. Dr. Stephan Kleuker
145Komponentenbasierte Software-Entwicklung
Lagerverwaltung (ein kleines OO-Modell)
Lebensmittel-verfallsdatum : Date
+verlustAm(stichtag : Date) : float
Buch
+verkaufspreis() : float
Lagerraum-nummer : String
+verkaufswertBerechnen() : float
Produkt-name : String-lagermenge : int-preis : float
+Produkt() : Produkt+verfuegbareAnzahl() : int+verkauft(anzahl : int) : void+einlagern(anzahl : int) : void+verkaufspreis() : float
1
beinhaltet-artikel
*1
- artikel bezeichnet eine Collection von Produkten in einem Lagerraum- mit verkaufspreis() wird die Mehrwertsteuer eingerechnet, die bei Büchern anders sein soll.
Prof. Dr. Stephan Kleuker
146Komponentenbasierte Software-Entwicklung
Aufgabe und Ansatz
• Objekte der im Lagerhaltungsmodell vorgestellten Klassen sollen persistent in einer relationalen DB abgespeichert werden
• Bei der Anbindung an die Datenbank sollen möglichst viele OO-Errungenschaften (Kapselung, Vererbung, Polymorphismus) übernommen werden
• Grundidee: Das Klassendiagramm kann ohne Methoden als ER-Diagramm gelesen werden, es beinhaltet eine 1:N und zwei 1:C Beziehungen.
• Anmerkung: Dieser Übersetzungsansatz war ein beliebtes Tummelfeld von Programmierern ☺, es wird nur ein möglicher Ansatz vorgestellt.
Prof. Dr. Stephan Kleuker
147Komponentenbasierte Software-Entwicklung
Umgang mit Kapselung
• Objekte der Klasse Produkt können leicht
in folgende Tabelle übersetzt werden.
• zusätzlicher Primary Key vergeben, falls name nicht eindeutig
• Kapselungsidee wird aufgegeben, da man über die Datenbank immer direkt auf die Attribute zugreifen kann, nur durch Mehraufwand einschränkbar:
– Lösung auf der Zugriffsebene im OO-Programm (umgehbar)
– Spezielle Nutzer und Rechte, Nutzung von Views (Aufwand)
OID name lagermenge preis
Produkt
Produkt-name : String-lagermenge : int-preis : float
+Produkt() : Produkt+verfuegbareAnzahl() : int+verkauft(anzahl : int) : void+einlagern(anzahl : int) : void+verkaufspreis() : float
Prof. Dr. Stephan Kleuker
148Komponentenbasierte Software-Entwicklung
Anmerkungen
• Typischerweise werden Klassenvariablen nicht mit den jeweiligen Objekten abgespeichert, sie müssen explizit behandelt werden
• Es stellt sich generell die Frage, welche zusätzlichen Informationen in welchen Tabellen verwaltet werden sollen
Prof. Dr. Stephan Kleuker
149Komponentenbasierte Software-Entwicklung
Umgang mit Vererbung
• Vererbung kann durch eine zusätzliche Tabelle mit einer Referenz implementiert werden, dabei ist OID Schlüssel und Fremdschlüssel aus Produkt
Lebensmittel-verfallsdatum : Date
+verlustAm(stichtag : Date) : float
Produkt
OID verfallsdatum
• Für jede Vererbungsebene wird eine neue Tabelle benötigt, was den Zugriff aufwändig macht
• Durch die vorgeschlagene Struktur wird die Sichtweise „ein Lebensmittel ist ein Produkt“ unterstützt
Lebensmittel
Prof. Dr. Stephan Kleuker
150Komponentenbasierte Software-Entwicklung
• Wie funktioniert Polymorphismus?public float verkaufswertBerechnen(){public float verkaufswertBerechnen(){public float verkaufswertBerechnen(){public float verkaufswertBerechnen(){float ergebnis=0.0f;float ergebnis=0.0f;float ergebnis=0.0f;float ergebnis=0.0f;for(Produkt tmp:artikel)for(Produkt tmp:artikel)for(Produkt tmp:artikel)for(Produkt tmp:artikel)ergebnis= ergebnis+ ergebnis= ergebnis+ ergebnis= ergebnis+ ergebnis= ergebnis+
tmp.verfuegbareAnzahl()*tmp.verkaufspreis();tmp.verfuegbareAnzahl()*tmp.verkaufspreis();tmp.verfuegbareAnzahl()*tmp.verkaufspreis();tmp.verfuegbareAnzahl()*tmp.verkaufspreis();return ergebnis;return ergebnis;return ergebnis;return ergebnis;
}}}}
• In der bisherigen relationalen Übersetzung muss sichergestellt werden, dass das richtige Objekt geladen wird
• Die genaue Klassendefinition bekommt man im vorgestellten Ansatz nur, wenn man alle zu Unterklassen gehörigen Tabellen untersucht, ob die OID vorkommt
• Alternativ kann man sich die genaue Klassenzugehörigkeit in einem weiteren Attribut der Tabelle Produkt merken
Umgang mit Polymorphismus
Prof. Dr. Stephan Kleuker
151Komponentenbasierte Software-Entwicklung
Umgang mit Objektidentität
• Objektidentität in der Datenbank wird durch den Primary Key garantiert
• Wird das Objekt aus der Datenbank gelesen, ist der Nutzer verantwortlich, dass kein zweites Exemplar des gleichen Objekts geladen wird
– Alternative: Beim ersten Herauslesen wird ein Flag (ein zusätzliches Attribut) gesetzt, dass sich das Exemplar außerhalb der DB befindet (Ansatz fordert viel Programmierdisziplin, insbesondere bei der Programmterminierung)
Prof. Dr. Stephan Kleuker
152Komponentenbasierte Software-Entwicklung
Umgang mit Beziehungen zwischen Objekten
• Exemplarvariablen, die Collections oder andere nicht triviale Objekttypen enthalten, müssen explizit durch eine oder mehrere Relationen oder Erweiterungen von Tabellen modelliert werden (der Ansatz ist vom Übergang vom ER-Diagramm zur Tabellenstruktur bekannt)
• Frage: Warum passt die skizzierte Lösung eigentlich nicht zum UML-Diagramm?
Lagerraum Produkt1
beinhaltet-artikel
*1
OID name lagermenge preis lagerraum_OID
Produkt
Prof. Dr. Stephan Kleuker
153Komponentenbasierte Software-Entwicklung
Bearbeiten von Objekten
• Wir haben gesehen, dass einfache Objekte häufig über mehrere Tabellen verteilt werden, d.h. zum Einlesen und Bearbeiten sind relativ aufwändige SQL-JOINS notwendig
• Weiterhin muss das OO-Programm die eindeutige Referenz eines Objektes in der relationalen DB kennen
• Beispiel: Einlesen eines Lebensmittels, das an eine Variable mit Namen „banane“ gebunden war
SELECT name, lagermenge, preis, verfallsdatumSELECT name, lagermenge, preis, verfallsdatumSELECT name, lagermenge, preis, verfallsdatumSELECT name, lagermenge, preis, verfallsdatum
FROM Identifikation, Lebensmittel, ProduktFROM Identifikation, Lebensmittel, ProduktFROM Identifikation, Lebensmittel, ProduktFROM Identifikation, Lebensmittel, Produkt
WHERE Identifikation.Name = 'banane'WHERE Identifikation.Name = 'banane'WHERE Identifikation.Name = 'banane'WHERE Identifikation.Name = 'banane'
AND Identifikation.OID = Produkt.OIDAND Identifikation.OID = Produkt.OIDAND Identifikation.OID = Produkt.OIDAND Identifikation.OID = Produkt.OID
AND Produkt.OID = Lebensmittel.OID AND Produkt.OID = Lebensmittel.OID AND Produkt.OID = Lebensmittel.OID AND Produkt.OID = Lebensmittel.OID
Prof. Dr. Stephan Kleuker
154Komponentenbasierte Software-Entwicklung
Zwischenfazit
• Selbst bei Beispielen, in denen der Einsatz relationaler Datenbanken sinnvoller Standard ist (Lagerverwaltung), wird die Verknüpfung eines OO-Programms mit relationaler Datenhaltung aufwändig
• Die Nutzung relationaler Datenbanken in OO-Programmen sollte immer über eine DB-Kapselung, die den Zugriff auf die DB regelt, erfolgen
• Für den Kapselungsansatz stehen verschiedene Produkte zur Verfügung (z. B. Hibernate, EclipseLink(TopLink)) , JPA spezifiziert gemeinsames Interface
• Verwandte Ansätze: direkte Nutzung einer OO-Datenbank, Programmierung mit JDO
Prof. Dr. Stephan Kleuker
155Komponentenbasierte Software-Entwicklung
Konzept von Persistence-Mappern
• Persistence-Mapper (PM) muss wissen, welche Objekte persistiert werden sollen -> markiere Klassen, deren Objekte verwaltet werden sollen
• Persistence-Mapper muss Beziehungen zwischen Objekten kennen
• Ablauf: Nutzer benutzt Objekt unter Verwaltung; dann übernimmt PM die Überwachung, führt Änderungen aus, regelt den Zugriff mehrerer Nutzer
• Ablauf: Nutzer erzeugt Objekt und muss PM einmal mitteilen, dieses zu verwalten
• PM kann selbst regeln, wie Aufgaben realisiert werden (Tabellenstruktur, Transaktionssteuerung)
Prof. Dr. Stephan Kleuker
156Komponentenbasierte Software-Entwicklung
package jpa20beispiel1;package jpa20beispiel1;package jpa20beispiel1;package jpa20beispiel1;import javax.persistence.Entity;import javax.persistence.Entity;import javax.persistence.Entity;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Id;import javax.persistence.Id;import javax.persistence.Id;@Entity@Entity@Entity@Entitypublic class Mitarbeiter {public class Mitarbeiter {public class Mitarbeiter {public class Mitarbeiter {@Id private int minr;@Id private int minr;@Id private int minr;@Id private int minr;private String name;private String name;private String name;private String name;
public Mitarbeiter(){} //parameterloser Konstruktor benötigtpublic Mitarbeiter(){} //parameterloser Konstruktor benötigtpublic Mitarbeiter(){} //parameterloser Konstruktor benötigtpublic Mitarbeiter(){} //parameterloser Konstruktor benötigt
public Mitarbeiter(int minr, String name) { //erlaubtpublic Mitarbeiter(int minr, String name) { //erlaubtpublic Mitarbeiter(int minr, String name) { //erlaubtpublic Mitarbeiter(int minr, String name) { //erlaubtthis.minr = minr;this.minr = minr;this.minr = minr;this.minr = minr;this.name = name;this.name = name;this.name = name;this.name = name;
}}}}
public int getMinr() {return minr;}public int getMinr() {return minr;}public int getMinr() {return minr;}public int getMinr() {return minr;}public void setMinr(int minr) {this.minr = minr;}public void setMinr(int minr) {this.minr = minr;}public void setMinr(int minr) {this.minr = minr;}public void setMinr(int minr) {this.minr = minr;}public String getName() {return name;}public String getName() {return name;}public String getName() {return name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void setName(String name) {this.name = name;}public void setName(String name) {this.name = name;}public void setName(String name) {this.name = name;}
}}}}
Beispiel (1/7)
Prof. Dr. Stephan Kleuker
157Komponentenbasierte Software-Entwicklung
Beispiel (2/7)• persistence.xml liegt im Ordner META-INF (projektartabhängig)
• Detaileinstellungen von JPA-Realisierung abhängig (z. B. EclispeLink (basiert auf TopLink), Hibernate, Apache OpenJPA)
<?xml version="1.0" encoding="UTF<?xml version="1.0" encoding="UTF<?xml version="1.0" encoding="UTF<?xml version="1.0" encoding="UTF----8"?>8"?>8"?>8"?><persistence version="2.0" <persistence version="2.0" <persistence version="2.0" <persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns="http://java.sun.com/xml/ns/persistence" xmlns="http://java.sun.com/xml/ns/persistence" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchemaxmlns:xsi="http://www.w3.org/2001/XMLSchemaxmlns:xsi="http://www.w3.org/2001/XMLSchemaxmlns:xsi="http://www.w3.org/2001/XMLSchema----instance" instance" instance" instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence xsi:schemaLocation="http://java.sun.com/xml/ns/persistence xsi:schemaLocation="http://java.sun.com/xml/ns/persistence xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence<persistence<persistence<persistence----unit name="JPA20Beispiel1PU" unit name="JPA20Beispiel1PU" unit name="JPA20Beispiel1PU" unit name="JPA20Beispiel1PU" transactiontransactiontransactiontransaction----type="RESOURCE_LOCAL"> type="RESOURCE_LOCAL"> type="RESOURCE_LOCAL"> type="RESOURCE_LOCAL">
<provider><provider><provider><provider>org.eclipse.persistence.jpa.PersistenceProviderorg.eclipse.persistence.jpa.PersistenceProviderorg.eclipse.persistence.jpa.PersistenceProviderorg.eclipse.persistence.jpa.PersistenceProvider
</provider></provider></provider></provider><class>jpa20beispiel1.Mitarbeiter</class><class>jpa20beispiel1.Mitarbeiter</class><class>jpa20beispiel1.Mitarbeiter</class><class>jpa20beispiel1.Mitarbeiter</class>
Prof. Dr. Stephan Kleuker
158Komponentenbasierte Software-Entwicklung
Beispiel (3/7)<<<<propertiespropertiespropertiesproperties>>>><<<<propertypropertypropertyproperty namenamenamename="javax.persistence.jdbc.url" ="javax.persistence.jdbc.url" ="javax.persistence.jdbc.url" ="javax.persistence.jdbc.url"
valuevaluevaluevalue="="="="jdbc:derbyjdbc:derbyjdbc:derbyjdbc:derby://://://://localhost:1527/Spielerei"/>localhost:1527/Spielerei"/>localhost:1527/Spielerei"/>localhost:1527/Spielerei"/><<<<propertypropertypropertyproperty namenamenamename="="="="javax.persistence.jdbc.passwordjavax.persistence.jdbc.passwordjavax.persistence.jdbc.passwordjavax.persistence.jdbc.password" " " "
valuevaluevaluevalue="="="="kleukerkleukerkleukerkleuker"/>"/>"/>"/><<<<propertypropertypropertyproperty namenamenamename="="="="javax.persistence.jdbc.driverjavax.persistence.jdbc.driverjavax.persistence.jdbc.driverjavax.persistence.jdbc.driver" " " "
valuevaluevaluevalue="="="="org.apache.derby.jdbc.ClientDriverorg.apache.derby.jdbc.ClientDriverorg.apache.derby.jdbc.ClientDriverorg.apache.derby.jdbc.ClientDriver"/>"/>"/>"/><<<<propertypropertypropertyproperty namenamenamename="="="="javax.persistence.jdbc.userjavax.persistence.jdbc.userjavax.persistence.jdbc.userjavax.persistence.jdbc.user" " " "
valuevaluevaluevalue="="="="kleukerkleukerkleukerkleuker"/>"/>"/>"/><<<<propertypropertypropertyproperty namenamenamename="="="="eclipselink.ddleclipselink.ddleclipselink.ddleclipselink.ddl----generation" generation" generation" generation"
valuevaluevaluevalue="="="="dropdropdropdrop----andandandand----createcreatecreatecreate----tablestablestablestables"/>"/>"/>"/></</</</propertiespropertiespropertiesproperties>>>>
</</</</persistencepersistencepersistencepersistence----unit>unit>unit>unit></</</</persistencepersistencepersistencepersistence>>>>
Prof. Dr. Stephan Kleuker
159Komponentenbasierte Software-Entwicklung
Beispiel (4/7)
Prof. Dr. Stephan Kleuker
160Komponentenbasierte Software-Entwicklung
Beispiel (5/7)
packagepackagepackagepackage jpa20beispiel1;jpa20beispiel1;jpa20beispiel1;jpa20beispiel1;importimportimportimport java.util.Listjava.util.Listjava.util.Listjava.util.List;;;;importimportimportimport javax.persistence.EntityManagerjavax.persistence.EntityManagerjavax.persistence.EntityManagerjavax.persistence.EntityManager;;;;importimportimportimport javax.persistence.EntityManagerFactoryjavax.persistence.EntityManagerFactoryjavax.persistence.EntityManagerFactoryjavax.persistence.EntityManagerFactory;;;;importimportimportimport javax.persistence.Persistencejavax.persistence.Persistencejavax.persistence.Persistencejavax.persistence.Persistence;;;;
publicpublicpublicpublic classclassclassclass Main {Main {Main {Main {
private private private private EntityManagerFactoryEntityManagerFactoryEntityManagerFactoryEntityManagerFactory emfemfemfemf = Persistence.= Persistence.= Persistence.= Persistence.createEntityManagerFactorycreateEntityManagerFactorycreateEntityManagerFactorycreateEntityManagerFactory("JPA20Beispiel1PU");("JPA20Beispiel1PU");("JPA20Beispiel1PU");("JPA20Beispiel1PU");
private private private private EntityManagerEntityManagerEntityManagerEntityManager emememem = = = = emf.createEntityManageremf.createEntityManageremf.createEntityManageremf.createEntityManager();();();();
publicpublicpublicpublic void void void void beispieldatenbeispieldatenbeispieldatenbeispieldaten() {() {() {() {String String String String namennamennamennamen[] = {"Egon", "Erwin", "Ute", [] = {"Egon", "Erwin", "Ute", [] = {"Egon", "Erwin", "Ute", [] = {"Egon", "Erwin", "Ute", """"AiseAiseAiseAise"};"};"};"};em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();forforforfor ((((intintintint i=0; i<i=0; i<i=0; i<i=0; i<namen.lengthnamen.lengthnamen.lengthnamen.length; i++); i++); i++); i++)em.persistem.persistem.persistem.persist((((newnewnewnew Mitarbeiter(Mitarbeiter(Mitarbeiter(Mitarbeiter(i,nameni,nameni,nameni,namen[i]));[i]));[i]));[i]));
em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();}}}}
Prof. Dr. Stephan Kleuker
161Komponentenbasierte Software-Entwicklung
Beispiel (6/7)
publicpublicpublicpublic void void void void datenZeigendatenZeigendatenZeigendatenZeigen() {() {() {() {forforforfor (Mitarbeiter m : (Mitarbeiter m : (Mitarbeiter m : (Mitarbeiter m : em.createQueryem.createQueryem.createQueryem.createQuery((((
"SELECT m FROM Mitarbeiter m","SELECT m FROM Mitarbeiter m","SELECT m FROM Mitarbeiter m","SELECT m FROM Mitarbeiter m",Mitarbeiter.classMitarbeiter.classMitarbeiter.classMitarbeiter.class) ) ) ) ....getResultListgetResultListgetResultListgetResultList()) {()) {()) {()) {
System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println((((m.getMinrm.getMinrm.getMinrm.getMinr() + ": " + () + ": " + () + ": " + () + ": " + m.getNamem.getNamem.getNamem.getName());());());());}}}}
}}}}
publicpublicpublicpublic void void void void schliessenschliessenschliessenschliessen() {() {() {() {ifififif ((((emememem != null && != null && != null && != null && em.isOpenem.isOpenem.isOpenem.isOpen()) {()) {()) {()) {em.closeem.closeem.closeem.close();}();}();}();}ifififif ((((emfemfemfemf != null && != null && != null && != null && emf.isOpenemf.isOpenemf.isOpenemf.isOpen()) {()) {()) {()) {emf.closeemf.closeemf.closeemf.close();}();}();}();}
} } } }
publicpublicpublicpublic staticstaticstaticstatic void void void void mainmainmainmain(String[] (String[] (String[] (String[] argsargsargsargs) {) {) {) {Main m = Main m = Main m = Main m = newnewnewnew Main();Main();Main();Main();m.beispieldatenm.beispieldatenm.beispieldatenm.beispieldaten();();();();m.datenZeigenm.datenZeigenm.datenZeigenm.datenZeigen();();();();m.schliessenm.schliessenm.schliessenm.schliessen();();();();
}}}}}}}}
1: Egon1: Egon1: Egon1: Egon
2: Erwin2: Erwin2: Erwin2: Erwin
4: 4: 4: 4: AiseAiseAiseAise
3: Ute3: Ute3: Ute3: Ute
Prof. Dr. Stephan Kleuker
162Komponentenbasierte Software-Entwicklung
Beispiel (7/7)
• Falls noch keine Tabelle Mitarbeiter existiert, wird diese angelegt
Prof. Dr. Stephan Kleuker
163Komponentenbasierte Software-Entwicklung
Suchen und Bearbeiten von einzelnen Objekten
public void namenAendern(){public void namenAendern(){public void namenAendern(){public void namenAendern(){int eingabe=int eingabe=int eingabe=int eingabe=----1;1;1;1;while(eingabe!=0){while(eingabe!=0){while(eingabe!=0){while(eingabe!=0){System.out.print("Welche Nummer (Ende mit 0): ");System.out.print("Welche Nummer (Ende mit 0): ");System.out.print("Welche Nummer (Ende mit 0): ");System.out.print("Welche Nummer (Ende mit 0): ");eingabe=new Scanner(System.in).nextInt();eingabe=new Scanner(System.in).nextInt();eingabe=new Scanner(System.in).nextInt();eingabe=new Scanner(System.in).nextInt();Mitarbeiter m = em.find(Mitarbeiter.class, eingabe);Mitarbeiter m = em.find(Mitarbeiter.class, eingabe);Mitarbeiter m = em.find(Mitarbeiter.class, eingabe);Mitarbeiter m = em.find(Mitarbeiter.class, eingabe);if(m == null)if(m == null)if(m == null)if(m == null)System.out.println("Witzbold");System.out.println("Witzbold");System.out.println("Witzbold");System.out.println("Witzbold");
else{else{else{else{System.out.print("Neuer Name (alt:"+m.getName()+"): ");System.out.print("Neuer Name (alt:"+m.getName()+"): ");System.out.print("Neuer Name (alt:"+m.getName()+"): ");System.out.print("Neuer Name (alt:"+m.getName()+"): ");String name=new Scanner(System.in).next(); String name=new Scanner(System.in).next(); String name=new Scanner(System.in).next(); String name=new Scanner(System.in).next(); EntityTransaction tr = em.getTransaction();EntityTransaction tr = em.getTransaction();EntityTransaction tr = em.getTransaction();EntityTransaction tr = em.getTransaction();tr.begin();tr.begin();tr.begin();tr.begin();m.setName(name);m.setName(name);m.setName(name);m.setName(name);tr.commit();tr.commit();tr.commit();tr.commit();
}}}}}}}}
}}}}
Prof. Dr. Stephan Kleuker
164Komponentenbasierte Software-Entwicklung
Zentrale Klassen
• Aufbau der VerbindungEntityManagerFactory emf = Persistence. EntityManagerFactory emf = Persistence. EntityManagerFactory emf = Persistence. EntityManagerFactory emf = Persistence.
createEntityManagerFactory("JPA20Beispiel1PU");createEntityManagerFactory("JPA20Beispiel1PU");createEntityManagerFactory("JPA20Beispiel1PU");createEntityManagerFactory("JPA20Beispiel1PU");
– Einrichtung sehr aufwändig, selten neu erstellen
• Einrichtung der Verbindung für den NutzerEntityManager em = emf.createEntityManager();EntityManager em = emf.createEntityManager();EntityManager em = emf.createEntityManager();EntityManager em = emf.createEntityManager();
– kostet Zeit, gibt trotzdem meist sinnvoll Objekt häufiger zu erzeugen und zu schließen/löschen
• Nutzung einer TransaktionEntityTransaction tr = em.getTransaction();EntityTransaction tr = em.getTransaction();EntityTransaction tr = em.getTransaction();EntityTransaction tr = em.getTransaction();
– kurzfristig nutzen: Daten vorbereiten, dann DB-Zugriff, dann schließen
• letztendlich immer alles schließen (typisch in finally-Block)
• Generelles Verhalten hängt von DB ab, in Großprojekten immer mit erfahrenem DB-Administrator arbeiten
Prof. Dr. Stephan Kleuker
165Komponentenbasierte Software-Entwicklung
Entity ist POJO
Entity-Klassen-Objekte sind klassische Plain Old Java Objects
• Verpflichtung:
– public (oder protected) Konstruktor ohne Parameter
– Exemplarvariablen private oder protected, Zugriff über get... und set...
– Klasse, Methoden, Exemplarvariablen nicht final
– Serialisierbar [zumindest sehr sinnvoll]
• keine weiteren Einschränkungen
– beliebige weitere Methoden
– Vererbung (auch Entity von Nicht-Entity [aufwändig])
– Nutzung abstrakte Klassen
Prof. Dr. Stephan Kleuker
166Komponentenbasierte Software-Entwicklung
Primary Key
Typisch: Primary Key wird erzeugt
@Id@Id@Id@Id
@GeneratedValue(strategy = GenerationType.AUTO)@GeneratedValue(strategy = GenerationType.AUTO)@GeneratedValue(strategy = GenerationType.AUTO)@GeneratedValue(strategy = GenerationType.AUTO)
private int minr;private int minr;private int minr;private int minr;
folgende Datentypen erlaubt
• primitive Java-Typen (int, long, …)
• Wrapper von primitiven Java-Typen (Integer, Long, …)
• java.lang.String
• java.util.Date
• java.sql.Date
Prof. Dr. Stephan Kleuker
167Komponentenbasierte Software-Entwicklung
Persistierbare Typen/Klassen
• Primitive Typen (byte, char, int, long, float, double, boolean)
• java.lang.String
• Andere serialisierbare Typen:
– Wrapper der primitiven Typen
– java.math.BigInteger
– java.math.BigDecimal
– java.util.Date, java.util.Calendar
– java.sql.Date, java.sql.Time, java.sql.TimeStamp
– Nutzerdefinierte serialisierbare Typen
– byte[], Byte[], char[], Character[]
• Enumeration
• Andere Entities
• Collections von Entities (Collection, Set, List, Map)
Prof. Dr. Stephan Kleuker
168Komponentenbasierte Software-Entwicklung
Persistent Fields / Properties
• Persistent Fields
– @Id private int minr;@Id private int minr;@Id private int minr;@Id private int minr;
– Exemplarvariablen direkt annotiert
– Zugriff des Persistence-Frameworks direkt auf Variablen
– Vorteil: Variable und Annotation stehen direkt zusammen
• Persistent Properties
– @Id public int getMinr{ return this.minr; }@Id public int getMinr{ return this.minr; }@Id public int getMinr{ return this.minr; }@Id public int getMinr{ return this.minr; }
– get-Methode wird annotiert
– Zugriff auf Exemplarvariablen muss immer über Standard get erfolgen (auch in der Klasse selbst)
– Vorteil: Flexibilität, da Methode weitere Funktionalität haben kann
Prof. Dr. Stephan Kleuker
169Komponentenbasierte Software-Entwicklung
Annotationen zur Flexibilisierung / Ergänzung
@Entity@Entity@Entity@Entity
@Table(@Table(@Table(@Table(namenamenamename="Chef")="Chef")="Chef")="Chef")
publicpublicpublicpublic classclassclassclass Mitarbeiter Mitarbeiter Mitarbeiter Mitarbeiter implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable {{{{
private private private private staticstaticstaticstatic final final final final longlonglonglong serialVersionUIDserialVersionUIDserialVersionUIDserialVersionUID = 1L;= 1L;= 1L;= 1L;
@@@@IdIdIdId
@@@@GeneratedValueGeneratedValueGeneratedValueGeneratedValue((((strategystrategystrategystrategy = = = = GenerationType.AUTOGenerationType.AUTOGenerationType.AUTOGenerationType.AUTO))))
private private private private intintintint minrminrminrminr;;;;
@@@@ColumnColumnColumnColumn((((namenamenamename="Leiter", ="Leiter", ="Leiter", ="Leiter", nullablenullablenullablenullable=false,=false,=false,=false,
updatableupdatableupdatableupdatable=true, =true, =true, =true, uniqueuniqueuniqueunique=true)=true)=true)=true)
private String private String private String private String namenamenamename;;;;
............
Prof. Dr. Stephan Kleuker
170Komponentenbasierte Software-Entwicklung
PersistenceContext
• Wird für Objekte vorher festgehaltener Klassen definiert
• Entspricht einem Cache, der MANAGED-Objekte verwaltet
• EntityManager-Objekt für konkreten PersistenceContext
• EntityManager-Operationen arbeiten auf dem Cache
• Man muss EntityManager mitteilen, dass Daten in die DB geschrieben werden müssenem.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();
• Beim Schreiben können wg. der Transaktionssteuerung der DB Exceptions auftreten (abhängig von Steuerungsart)
• Im Zweifel bei Entwicklung immer echte Tabellen anschauen
• Üblich: nur kurz lebende EntityManager (erzeugen, Aktion, schließen)
Prof. Dr. Stephan Kleuker
171Komponentenbasierte Software-Entwicklung
Beispiel für Cache (1/2)
@Entity@Entity@Entity@Entitypublic class Mitarbeiter implements Serializable {public class Mitarbeiter implements Serializable {public class Mitarbeiter implements Serializable {public class Mitarbeiter implements Serializable {
@Id @GeneratedValue@Id @GeneratedValue@Id @GeneratedValue@Id @GeneratedValueprivate int minr;private int minr;private int minr;private int minr;
@Column(length=2) //maximal zwei Zeichen@Column(length=2) //maximal zwei Zeichen@Column(length=2) //maximal zwei Zeichen@Column(length=2) //maximal zwei Zeichenprivate String name;private String name;private String name;private String name;
public Mitarbeiter() {public Mitarbeiter() {public Mitarbeiter() {public Mitarbeiter() {} //parameterloser Konstruktor benötigt} //parameterloser Konstruktor benötigt} //parameterloser Konstruktor benötigt} //parameterloser Konstruktor benötigt
public Mitarbeiter(String name) {public Mitarbeiter(String name) {public Mitarbeiter(String name) {public Mitarbeiter(String name) {this.name = name;this.name = name;this.name = name;this.name = name;
} } } } // get// get// get// get---- und setund setund setund set----Methoden weggelassenMethoden weggelassenMethoden weggelassenMethoden weggelassen
@Override public String toString(){@Override public String toString(){@Override public String toString(){@Override public String toString(){return name+"("+minr+")";return name+"("+minr+")";return name+"("+minr+")";return name+"("+minr+")";
}}}}}}}}
Prof. Dr. Stephan Kleuker
172Komponentenbasierte Software-Entwicklung
Beispiel für Cache (2/2)
public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {EntityManagerFactory emf = EntityManagerFactory emf = EntityManagerFactory emf = EntityManagerFactory emf =
Persistence.createEntityManagerFactory("JPACachePU");Persistence.createEntityManagerFactory("JPACachePU");Persistence.createEntityManagerFactory("JPACachePU");Persistence.createEntityManagerFactory("JPACachePU");EntityManager em=emf.createEntityManager();EntityManager em=emf.createEntityManager();EntityManager em=emf.createEntityManager();EntityManager em=emf.createEntityManager();em.getTransaction().begin();em.getTransaction().begin();em.getTransaction().begin();em.getTransaction().begin();em.persist(new Mitarbeiter("ET"));em.persist(new Mitarbeiter("ET"));em.persist(new Mitarbeiter("ET"));em.persist(new Mitarbeiter("ET"));em.persist(new Mitarbeiter("JFK"));em.persist(new Mitarbeiter("JFK"));em.persist(new Mitarbeiter("JFK"));em.persist(new Mitarbeiter("JFK"));for(int i=1;i<3;i++)for(int i=1;i<3;i++)for(int i=1;i<3;i++)for(int i=1;i<3;i++)System.out.println(em.find(Mitarbeiter.class,i));System.out.println(em.find(Mitarbeiter.class,i));System.out.println(em.find(Mitarbeiter.class,i));System.out.println(em.find(Mitarbeiter.class,i));
em.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();em.close();em.close();em.close();em.close();}}}}
}}}}ET(1)ET(1)ET(1)ET(1)JFK(2)JFK(2)JFK(2)JFK(2)[EL Warning]: 2010[EL Warning]: 2010[EL Warning]: 2010[EL Warning]: 2010----03030303----28 13:12:57.86828 13:12:57.86828 13:12:57.86828 13:12:57.868----UnitOfWork(20290587)UnitOfWork(20290587)UnitOfWork(20290587)UnitOfWork(20290587)----Exception [EclipseLinkException [EclipseLinkException [EclipseLinkException [EclipseLink----4002]: 4002]: 4002]: 4002]: org.eclipse.persistence.exceptions.DatabaseExceptionorg.eclipse.persistence.exceptions.DatabaseExceptionorg.eclipse.persistence.exceptions.DatabaseExceptionorg.eclipse.persistence.exceptions.DatabaseExceptionInternal Exception: java.sql.SQLDataException: Bei dem Internal Exception: java.sql.SQLDataException: Bei dem Internal Exception: java.sql.SQLDataException: Bei dem Internal Exception: java.sql.SQLDataException: Bei dem Versuch, VARCHAR 'JFK' auf die Länge 2 zu kürzen, ist Versuch, VARCHAR 'JFK' auf die Länge 2 zu kürzen, ist Versuch, VARCHAR 'JFK' auf die Länge 2 zu kürzen, ist Versuch, VARCHAR 'JFK' auf die Länge 2 zu kürzen, ist ein Abschneidefehler aufgetreten.ein Abschneidefehler aufgetreten.ein Abschneidefehler aufgetreten.ein Abschneidefehler aufgetreten.
Prof. Dr. Stephan Kleuker
173Komponentenbasierte Software-Entwicklung
Lebenslauf eines Entity-Objekts
NEW -> merge() führt evtl. zur Mehrfachobjekterzeugungrefresh() nur, wenn vorher persistiert
Prof. Dr. Stephan Kleuker
174Komponentenbasierte Software-Entwicklung
Unterschied: Lokal und DB immer beachten
public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {EntityManagerFactory emf = Persistence.EntityManagerFactory emf = Persistence.EntityManagerFactory emf = Persistence.EntityManagerFactory emf = Persistence.
createEntityManagerFactory("JPA20Beispiel1PU");createEntityManagerFactory("JPA20Beispiel1PU");createEntityManagerFactory("JPA20Beispiel1PU");createEntityManagerFactory("JPA20Beispiel1PU");EntityManager em = emf.createEntityManager();EntityManager em = emf.createEntityManager();EntityManager em = emf.createEntityManager();EntityManager em = emf.createEntityManager();Mitarbeiter m1 = new Mitarbeiter("Ford");Mitarbeiter m1 = new Mitarbeiter("Ford");Mitarbeiter m1 = new Mitarbeiter("Ford");Mitarbeiter m1 = new Mitarbeiter("Ford");Mitarbeiter m2 = new Mitarbeiter("Arthur");Mitarbeiter m2 = new Mitarbeiter("Arthur");Mitarbeiter m2 = new Mitarbeiter("Arthur");Mitarbeiter m2 = new Mitarbeiter("Arthur");em.getTransaction().begin();em.getTransaction().begin();em.getTransaction().begin();em.getTransaction().begin();em.persist(m1);em.persist(m1);em.persist(m1);em.persist(m1);em.persist(m2);em.persist(m2);em.persist(m2);em.persist(m2);em.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();m1.setName("Manta");m1.setName("Manta");m1.setName("Manta");m1.setName("Manta");for (Mitarbeiter m : em.createQuery(for (Mitarbeiter m : em.createQuery(for (Mitarbeiter m : em.createQuery(for (Mitarbeiter m : em.createQuery(
"SELECT m FROM Mitarbeiter m", Mitarbeiter.class)"SELECT m FROM Mitarbeiter m", Mitarbeiter.class)"SELECT m FROM Mitarbeiter m", Mitarbeiter.class)"SELECT m FROM Mitarbeiter m", Mitarbeiter.class).getResultList()).getResultList()).getResultList()).getResultList())
System.out.println(m.getMinr() System.out.println(m.getMinr() System.out.println(m.getMinr() System.out.println(m.getMinr() + ": " + m.getName());+ ": " + m.getName());+ ": " + m.getName());+ ": " + m.getName());
em.close();em.close();em.close();em.close();em.refresh(m1);em.refresh(m1);em.refresh(m1);em.refresh(m1);System.out.println(m1);System.out.println(m1);System.out.println(m1);System.out.println(m1);
}}}}
2: Arthur2: Arthur2: Arthur2: Arthur1: Manta1: Manta1: Manta1: MantaFord(1)Ford(1)Ford(1)Ford(1)
Prof. Dr. Stephan Kleuker
175Komponentenbasierte Software-Entwicklung
Sauberes Persistieren
• Auslagerung der Persistierung in eine Methode mit sauberer Exception-Behandlung
• Anmerkung: man muss nicht immer em.close() machenpublicpublicpublicpublic void void void void persistpersistpersistpersist(Object (Object (Object (Object objectobjectobjectobject) {) {) {) {
em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();trytrytrytry {{{{em.persistem.persistem.persistem.persist((((objectobjectobjectobject););););em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();
} catch (Exception e) {} catch (Exception e) {} catch (Exception e) {} catch (Exception e) {ifififif ((((em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().isActiveisActiveisActiveisActive())())())())em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().rollbackrollbackrollbackrollback();();();();
throwthrowthrowthrow e;e;e;e;} } } } finallyfinallyfinallyfinally {{{{
em.closeem.closeem.closeem.close();();();();}}}}
Prof. Dr. Stephan Kleuker
176Komponentenbasierte Software-Entwicklung
Notwendigkeit von merge (1/3)
publicpublicpublicpublic classclassclassclass Main {Main {Main {Main {
private private private private EntityManagerFactoryEntityManagerFactoryEntityManagerFactoryEntityManagerFactory emfemfemfemf ====Persistence.createEntityManagerFactoryPersistence.createEntityManagerFactoryPersistence.createEntityManagerFactoryPersistence.createEntityManagerFactory("("("("JPAMergeJPAMergeJPAMergeJPAMerge");");");");
private private private private EntityManagerEntityManagerEntityManagerEntityManager emememem = = = = emf.createEntityManageremf.createEntityManageremf.createEntityManageremf.createEntityManager();();();();
public static void main(String[] public static void main(String[] public static void main(String[] public static void main(String[] argsargsargsargs) {) {) {) {new Main().mach1();new Main().mach1();new Main().mach1();new Main().mach1();
}}}}
publicpublicpublicpublic voidvoidvoidvoid datenZeigendatenZeigendatenZeigendatenZeigen() {() {() {() {forforforfor (Mitarbeiter m : (Mitarbeiter m : (Mitarbeiter m : (Mitarbeiter m : em.createQueryem.createQueryem.createQueryem.createQuery((((
"SELECT m FROM Mitarbeiter m","SELECT m FROM Mitarbeiter m","SELECT m FROM Mitarbeiter m","SELECT m FROM Mitarbeiter m",Mitarbeiter.classMitarbeiter.classMitarbeiter.classMitarbeiter.class))))....getResultListgetResultListgetResultListgetResultList()) ()) ()) ())
System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println((((m.getIdm.getIdm.getIdm.getId() + ": " + () + ": " + () + ": " + () + ": " + m.getNamem.getNamem.getNamem.getName());());());());}}}}
Prof. Dr. Stephan Kleuker
177Komponentenbasierte Software-Entwicklung
Notwendigkeit von merge (2/3)
publicpublicpublicpublic void mach1() {void mach1() {void mach1() {void mach1() {Mitarbeiter m1 = Mitarbeiter m1 = Mitarbeiter m1 = Mitarbeiter m1 = newnewnewnew Mitarbeiter("Urs");Mitarbeiter("Urs");Mitarbeiter("Urs");Mitarbeiter("Urs");em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();em.persistem.persistem.persistem.persist(m1);(m1);(m1);(m1);em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();datenZeigendatenZeigendatenZeigendatenZeigen();();();();Mitarbeiter m2 = Mitarbeiter m2 = Mitarbeiter m2 = Mitarbeiter m2 = em.findem.findem.findem.find((((Mitarbeiter.classMitarbeiter.classMitarbeiter.classMitarbeiter.class, m1.getId());, m1.getId());, m1.getId());, m1.getId());em.closeem.closeem.closeem.close();();();();mach2(m2);mach2(m2);mach2(m2);mach2(m2);
}}}}
publicpublicpublicpublic void mach2(Mitarbeiter m2) {void mach2(Mitarbeiter m2) {void mach2(Mitarbeiter m2) {void mach2(Mitarbeiter m2) {m2.setName("Ute");m2.setName("Ute");m2.setName("Ute");m2.setName("Ute");emememem = = = = emf.createEntityManageremf.createEntityManageremf.createEntityManageremf.createEntityManager();();();();em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();em.persistem.persistem.persistem.persist(m2);(m2);(m2);(m2);em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();datenZeigendatenZeigendatenZeigendatenZeigen();();();();em.closeem.closeem.closeem.close();();();();
}}}}}}}}
1: Urs1: Urs1: Urs1: UrsInternal Exception: Internal Exception: Internal Exception: Internal Exception: java.sql.SQLIntegrityConsjava.sql.SQLIntegrityConsjava.sql.SQLIntegrityConsjava.sql.SQLIntegrityConstraintViolationException:traintViolationException:traintViolationException:traintViolationException:.. zu einem duplizierten .. zu einem duplizierten .. zu einem duplizierten .. zu einem duplizierten Schlüsselwert geführt Schlüsselwert geführt Schlüsselwert geführt Schlüsselwert geführt hätte.hätte.hätte.hätte.
Prof. Dr. Stephan Kleuker
178Komponentenbasierte Software-Entwicklung
Notwendigkeit von merge (3/3)
publicpublicpublicpublic void mach2(Mitarbeiter m2) {void mach2(Mitarbeiter m2) {void mach2(Mitarbeiter m2) {void mach2(Mitarbeiter m2) {
m2.setName("Ute");m2.setName("Ute");m2.setName("Ute");m2.setName("Ute");
emememem = = = = emf.createEntityManageremf.createEntityManageremf.createEntityManageremf.createEntityManager();();();();
em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();
////////em.persistem.persistem.persistem.persist(m2);(m2);(m2);(m2);
em.mergeem.mergeem.mergeem.merge(m2);(m2);(m2);(m2);
em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();
datenZeigendatenZeigendatenZeigendatenZeigen();();();();
}}}}
• Hinweis: Verzichtet man zwischenzeitlich auf das Schließen des EntityManagers, funktioniert persist() genauso gut
• zur Aktualisierung sollte merge() genutzt werden
1: Urs1: Urs1: Urs1: Urs
1: Ute1: Ute1: Ute1: Ute
Prof. Dr. Stephan Kleuker
179Komponentenbasierte Software-Entwicklung
Klasse oder Tabelle?Bei der Entity-Nutzung offen, ob erst Klassen designt und dann
Tabellen entworfen werden
• Einfach: Tabellen existieren; dann typischerweise zur Tabelle eine Entity-Klassse erstellbar (generierbar)
• Wenn nichts gegeben:
– Entwurf der Entity-Klassen (Daten der Applikation mit ihren Abhängigkeiten)
– Ableitung oder Generierung der Tabellen
• Generierungsansätze:
– Drop and Create: beteiligte Tabellen löschen und neu anlegen (Entwicklung und Test)
– Create: wenn nicht existent, dann anlegen (Realität)
– None: wenn nicht existent, dann Fehler (Realität)
• Hinweis: bei Änderungen neu übersetzen
Prof. Dr. Stephan Kleuker
180Komponentenbasierte Software-Entwicklung
Generelle JEE-Regel
Convention over Configuration
• bedeutet: wenn nichts angegeben wird, wird ein Default-Wert genutzt
• Default-Werte sind zwar sinnvoll, sollte man aber kennen
• Erinnerung: Java-Inkonsistenz
Prof. Dr. Stephan Kleuker
181Komponentenbasierte Software-Entwicklung
Einschub: XML-Konfiguration
• Statt Annotationen zu nutzen, können diese Informationen auch in XML beschrieben werden
• Typisch: eine XML-Datei pro Klasse + zusammenführende XML-Datei
• Vorteil: Verhaltensänderungen ohne Codeänderung
• Nachteil: viele kleine penibel zu pflegende Dateien
• Auch möglich: XML und Annotationen; dabei „schlägt“ XML die Annotationen
Prof. Dr. Stephan Kleuker
182Komponentenbasierte Software-Entwicklung
Kardinalitäten in JPA
• 1:1 zu einem A- Objekt gehört (maximal) ein anderes B-Objekt, die jeweils zu (maximal) einem A-Objekt gehören
• 1:N zu einem A-Objekt gehören beliebig viele B-Objekte, die jeweils zu (maximal) einem A-Objekt gehören (N:1 analog)
• M:N zu einem A-Objekt gehören beliebig viele B-Objekte, die jeweils zu beliebig vielen A-Objekten gehören
• Anders als bei Tabellen haben OO-Assoziationen Leserichtungen
• Unidirektional: nur von einer Seite auf die andere schließbar
• Bidirektional: Abhängigkeit in beide Richtungen manövrierbar (es gibt Besitzer der Beziehung; für Updates wichtig)
A Bx y
Prof. Dr. Stephan Kleuker
183Komponentenbasierte Software-Entwicklung
Umsetzung unidirektional 1:N (1/4)
@Entity@Entity@Entity@Entitypublic class Projektauftrag implements Serializable {public class Projektauftrag implements Serializable {public class Projektauftrag implements Serializable {public class Projektauftrag implements Serializable {
@Id @GeneratedValue private int paid;@Id @GeneratedValue private int paid;@Id @GeneratedValue private int paid;@Id @GeneratedValue private int paid;private String titel;private String titel;private String titel;private String titel;public String getTitel() {public String getTitel() {public String getTitel() {public String getTitel() {return titel;return titel;return titel;return titel;
}}}}
public void setTitel(String titel) {public void setTitel(String titel) {public void setTitel(String titel) {public void setTitel(String titel) {this.titel = titel;this.titel = titel;this.titel = titel;this.titel = titel;
}}}}}}}}
Prof. Dr. Stephan Kleuker
184Komponentenbasierte Software-Entwicklung
Umsetzung unidirektional 1:N (2/4)
@@@@EntityEntityEntityEntity
publicpublicpublicpublic classclassclassclass Projekt Projekt Projekt Projekt implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable {{{{
@@@@IdIdIdId @@@@GeneratedValueGeneratedValueGeneratedValueGeneratedValue
private private private private intintintint projektidprojektidprojektidprojektid;;;;
private String private String private String private String namenamenamename;;;;
@@@@OneToManyOneToManyOneToManyOneToMany((((cascadecascadecascadecascade====CascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSIST))))
private Set<Projektauftrag> private Set<Projektauftrag> private Set<Projektauftrag> private Set<Projektauftrag> auftraegeauftraegeauftraegeauftraege;;;;
publicpublicpublicpublic Projekt(){Projekt(){Projekt(){Projekt(){
auftraegeauftraegeauftraegeauftraege = = = = newnewnewnew HashSetHashSetHashSetHashSet<Projektauftrag>();<Projektauftrag>();<Projektauftrag>();<Projektauftrag>();
}}}}
// fehlen // fehlen // fehlen // fehlen getgetgetget---- und und und und setsetsetset----Methoden (auch Methoden (auch Methoden (auch Methoden (auch addaddaddadd wäre sinnvoll)wäre sinnvoll)wäre sinnvoll)wäre sinnvoll)
Prof. Dr. Stephan Kleuker
185Komponentenbasierte Software-Entwicklung
Umsetzung unidirektional 1:N (3/4)
public void datenAnlegen(){public void datenAnlegen(){public void datenAnlegen(){public void datenAnlegen(){String p[] ={"Hotel", "Noten", "Belegung"};String p[] ={"Hotel", "Noten", "Belegung"};String p[] ={"Hotel", "Noten", "Belegung"};String p[] ={"Hotel", "Noten", "Belegung"};String a[] ={"Analyse", "Modell", "Design"};String a[] ={"Analyse", "Modell", "Design"};String a[] ={"Analyse", "Modell", "Design"};String a[] ={"Analyse", "Modell", "Design"};em.getTransaction().begin();em.getTransaction().begin();em.getTransaction().begin();em.getTransaction().begin();for (int i=0; i<p.length;i++){for (int i=0; i<p.length;i++){for (int i=0; i<p.length;i++){for (int i=0; i<p.length;i++){Projekt pr= new Projekt();Projekt pr= new Projekt();Projekt pr= new Projekt();Projekt pr= new Projekt();pr.setName(p[i]);pr.setName(p[i]);pr.setName(p[i]);pr.setName(p[i]);for (int j=0; j<a.length;j++){for (int j=0; j<a.length;j++){for (int j=0; j<a.length;j++){for (int j=0; j<a.length;j++){Projektauftrag pa= new Projektauftrag();Projektauftrag pa= new Projektauftrag();Projektauftrag pa= new Projektauftrag();Projektauftrag pa= new Projektauftrag();pa.setTitel(a[j]);pa.setTitel(a[j]);pa.setTitel(a[j]);pa.setTitel(a[j]);Set<Projektauftrag> tmp= pr.getAuftraege();Set<Projektauftrag> tmp= pr.getAuftraege();Set<Projektauftrag> tmp= pr.getAuftraege();Set<Projektauftrag> tmp= pr.getAuftraege();tmp.add(pa);tmp.add(pa);tmp.add(pa);tmp.add(pa);
}}}}em.persist(pr);em.persist(pr);em.persist(pr);em.persist(pr);
}}}}em.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();
}}}}
Prof. Dr. Stephan Kleuker
186Komponentenbasierte Software-Entwicklung
Umsetzung unidirektional 1:N (4/4)SELECT PROJEKT.PROJEKTID, PROJEKT.NAME, PROJEKTAUFTRAG.PAID, SELECT PROJEKT.PROJEKTID, PROJEKT.NAME, PROJEKTAUFTRAG.PAID, SELECT PROJEKT.PROJEKTID, PROJEKT.NAME, PROJEKTAUFTRAG.PAID, SELECT PROJEKT.PROJEKTID, PROJEKT.NAME, PROJEKTAUFTRAG.PAID,
PROJEKTAUFTRAG.TITELPROJEKTAUFTRAG.TITELPROJEKTAUFTRAG.TITELPROJEKTAUFTRAG.TITELFROM PROJEKT, PROJEKT_PROJEKTAUFTRAG, PROJEKTAUFTRAGFROM PROJEKT, PROJEKT_PROJEKTAUFTRAG, PROJEKTAUFTRAGFROM PROJEKT, PROJEKT_PROJEKTAUFTRAG, PROJEKTAUFTRAGFROM PROJEKT, PROJEKT_PROJEKTAUFTRAG, PROJEKTAUFTRAGWHERE PROJEKT.PROJEKTID = WHERE PROJEKT.PROJEKTID = WHERE PROJEKT.PROJEKTID = WHERE PROJEKT.PROJEKTID =
PROJEKT_PROJEKTAUFTRAG.PROJEKT_PROJEKTIDPROJEKT_PROJEKTAUFTRAG.PROJEKT_PROJEKTIDPROJEKT_PROJEKTAUFTRAG.PROJEKT_PROJEKTIDPROJEKT_PROJEKTAUFTRAG.PROJEKT_PROJEKTIDAND PROJEKTAUFTRAG.PAID = AND PROJEKTAUFTRAG.PAID = AND PROJEKTAUFTRAG.PAID = AND PROJEKTAUFTRAG.PAID =
PROJEKT_PROJEKTAUFTRAG.AUFTRAEGE_PAID;PROJEKT_PROJEKTAUFTRAG.AUFTRAEGE_PAID;PROJEKT_PROJEKTAUFTRAG.AUFTRAEGE_PAID;PROJEKT_PROJEKTAUFTRAG.AUFTRAEGE_PAID;
Prof. Dr. Stephan Kleuker
187Komponentenbasierte Software-Entwicklung
Cascade-Varianten
@OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE})@OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE})@OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE})@OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE})
• MERGE : merge() implizit für verknüpfte Objekte aufrufen
• PERSIST: persist() implizit für verknüpfte Objekte aufrufen
• REFRESH: refresh() implizit für verknüpfte Objekte aufrufen
• REMOVE: remove() implizit für verknüpfte Objekte aufrufen
• ALL: alle vier genannten Möglichkeiten
• Default-Einstellung: keine der fünf Varianten
• Wichtige Design-Entscheidung, was sinnvoll ist
• REMOVE nur bei @OneToOne und @OneToMany nutzbar
Beispiel, wenn Cascade.PERSIST fehlteSCHWERWIEGEND: Could not synchronize database state with sessionSCHWERWIEGEND: Could not synchronize database state with sessionSCHWERWIEGEND: Could not synchronize database state with sessionSCHWERWIEGEND: Could not synchronize database state with session
org.hibernate.TransientObjectException: object references an unsaved org.hibernate.TransientObjectException: object references an unsaved org.hibernate.TransientObjectException: object references an unsaved org.hibernate.TransientObjectException: object references an unsaved transient instance transient instance transient instance transient instance ---- save the transient instance before flushing: save the transient instance before flushing: save the transient instance before flushing: save the transient instance before flushing: ProjektauftragProjektauftragProjektauftragProjektauftrag
Prof. Dr. Stephan Kleuker
188Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional 1:N (1/5)
- Bidirektionale Relationen haben Eigentümer (owner side) und Abhängigen (inverse side)
- Eigentümer bei 1:N ist N (hier Projektauftrag)
- Abhängiger bekommt mappedBy-Attribut
- Programmierer für Einträge auf beiden Seiten verantwortlich
Prof. Dr. Stephan Kleuker
189Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional 1:N (2/5)
@Entity@Entity@Entity@Entity
public class Projektauftrag implements Serializable {public class Projektauftrag implements Serializable {public class Projektauftrag implements Serializable {public class Projektauftrag implements Serializable {
@Id @GeneratedValue @Id @GeneratedValue @Id @GeneratedValue @Id @GeneratedValue
private int paid;private int paid;private int paid;private int paid;
private String titel;private String titel;private String titel;private String titel;
@ManyToOne(cascade={CascadeType.PERSIST, @ManyToOne(cascade={CascadeType.PERSIST, @ManyToOne(cascade={CascadeType.PERSIST, @ManyToOne(cascade={CascadeType.PERSIST,
CascadeType.MERGE})CascadeType.MERGE})CascadeType.MERGE})CascadeType.MERGE})
private Mitarbeiter bearbeiter;private Mitarbeiter bearbeiter;private Mitarbeiter bearbeiter;private Mitarbeiter bearbeiter;
//...//...//...//...
Prof. Dr. Stephan Kleuker
190Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional 1:N (3/5)
@@@@EntityEntityEntityEntity
publicpublicpublicpublic classclassclassclass Mitarbeiter Mitarbeiter Mitarbeiter Mitarbeiter implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable {{{{
private private private private staticstaticstaticstatic final final final final longlonglonglong serialVersionUIDserialVersionUIDserialVersionUIDserialVersionUID = 1L;= 1L;= 1L;= 1L;
@@@@IdIdIdId
@@@@GeneratedValueGeneratedValueGeneratedValueGeneratedValue((((strategystrategystrategystrategy = = = = GenerationType.AUTOGenerationType.AUTOGenerationType.AUTOGenerationType.AUTO))))
private private private private intintintint minrminrminrminr;;;;
private String private String private String private String namenamenamename;;;;
@@@@OneToManyOneToManyOneToManyOneToMany((((mappedBymappedBymappedBymappedBy="="="="bearbeiterbearbeiterbearbeiterbearbeiter", ", ", ",
cascadecascadecascadecascade={={={={CascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSIST, , , , CascadeType.MERGECascadeType.MERGECascadeType.MERGECascadeType.MERGE})})})})
private Set<Projektauftrag> private Set<Projektauftrag> private Set<Projektauftrag> private Set<Projektauftrag> auftraegeauftraegeauftraegeauftraege = = = =
newnewnewnew HashSetHashSetHashSetHashSet<Projektauftrag>();<Projektauftrag>();<Projektauftrag>();<Projektauftrag>();
publicpublicpublicpublic voidvoidvoidvoid auftragHinzuauftragHinzuauftragHinzuauftragHinzu(Projektauftrag (Projektauftrag (Projektauftrag (Projektauftrag papapapa){){){){
auftraege.addauftraege.addauftraege.addauftraege.add((((papapapa););););
} // ...} // ...} // ...} // ...
Prof. Dr. Stephan Kleuker
191Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional 1:N (4/5)publicpublicpublicpublic void void void void mitarbeiterZuordnenmitarbeiterZuordnenmitarbeiterZuordnenmitarbeiterZuordnen(){(){(){(){Mitarbeiter m[]= {Mitarbeiter m[]= {Mitarbeiter m[]= {Mitarbeiter m[]= {newnewnewnew Mitarbeiter("Egon"), Mitarbeiter("Egon"), Mitarbeiter("Egon"), Mitarbeiter("Egon"),
newnewnewnew MitarbeiterMitarbeiterMitarbeiterMitarbeiter("("("("AiseAiseAiseAise"), "), "), "), newnewnewnew Mitarbeiter("Urs")};Mitarbeiter("Urs")};Mitarbeiter("Urs")};Mitarbeiter("Urs")};em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();forforforfor ((((intintintint i=0; i<i=0; i<i=0; i<i=0; i<m.lengthm.lengthm.lengthm.length; i++); i++); i++); i++)
em.persistem.persistem.persistem.persist(m[i]);(m[i]);(m[i]);(m[i]);forforforfor (Projektauftrag p : (List<Projektauftrag>) (Projektauftrag p : (List<Projektauftrag>) (Projektauftrag p : (List<Projektauftrag>) (Projektauftrag p : (List<Projektauftrag>) emememem....
createQuerycreateQuerycreateQuerycreateQuery("SELECT p FROM Projektauftrag p").("SELECT p FROM Projektauftrag p").("SELECT p FROM Projektauftrag p").("SELECT p FROM Projektauftrag p").getResultListgetResultListgetResultListgetResultList())())())())
ifififif((((p.getTitelp.getTitelp.getTitelp.getTitel().().().().equalsequalsequalsequals("Analyse")){("Analyse")){("Analyse")){("Analyse")){m[0].m[0].m[0].m[0].auftragHinzuauftragHinzuauftragHinzuauftragHinzu(p);(p);(p);(p);p.setBearbeiterp.setBearbeiterp.setBearbeiterp.setBearbeiter(m[0]);(m[0]);(m[0]);(m[0]);
}}}}elseelseelseelse{{{{m[1].m[1].m[1].m[1].auftragHinzuauftragHinzuauftragHinzuauftragHinzu(p);(p);(p);(p);p.setBearbeiterp.setBearbeiterp.setBearbeiterp.setBearbeiter(m[1]);(m[1]);(m[1]);(m[1]);
} } } } em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();}}}}
JPA 1.0-Variante der
Anfrage
Prof. Dr. Stephan Kleuker
192Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional 1:N (5/5)SELECT MITARBEITER.NAME, MITARBEITER.MINR, SELECT MITARBEITER.NAME, MITARBEITER.MINR, SELECT MITARBEITER.NAME, MITARBEITER.MINR, SELECT MITARBEITER.NAME, MITARBEITER.MINR,
PROJEKTAUFTRAG.TITEL, PROJEKTAUFTRAG.PAIDPROJEKTAUFTRAG.TITEL, PROJEKTAUFTRAG.PAIDPROJEKTAUFTRAG.TITEL, PROJEKTAUFTRAG.PAIDPROJEKTAUFTRAG.TITEL, PROJEKTAUFTRAG.PAID
FROM MITARBEITER LEFT JOIN PROJEKTAUFTRAGFROM MITARBEITER LEFT JOIN PROJEKTAUFTRAGFROM MITARBEITER LEFT JOIN PROJEKTAUFTRAGFROM MITARBEITER LEFT JOIN PROJEKTAUFTRAG
ON (MITARBEITER.MINR=PROJEKTAUFTRAG.BEARBEITER_MINR) ;ON (MITARBEITER.MINR=PROJEKTAUFTRAG.BEARBEITER_MINR) ;ON (MITARBEITER.MINR=PROJEKTAUFTRAG.BEARBEITER_MINR) ;ON (MITARBEITER.MINR=PROJEKTAUFTRAG.BEARBEITER_MINR) ;
Prof. Dr. Stephan Kleuker
193Komponentenbasierte Software-Entwicklung
Umsetzung ist OR-Mapper freigestellt
Man sieht, dass bei bidirektionalen Beziehungen in EclipseLink keine neuen Tabellen angelegt werden, bei
unidirektionalen schon
Prof. Dr. Stephan Kleuker
194Komponentenbasierte Software-Entwicklung
Wichtige Annotationen in Großprojekten
@Version @Version @Version @Version intintintint versionversionversionversion
• Attribut wird für das optimistische Locking genutzt; erst beim Schreiben geschaut, ob sich Versionsnummer geändert hat
• performant, wenn Objekte nicht häufig geändert werden
• Einfach als zusätzliches Attribut ergänzen@Basic(@Basic(@Basic(@Basic(fetchfetchfetchfetch====FetchType.LAZYFetchType.LAZYFetchType.LAZYFetchType.LAZY))))
private private private private Set<Projektauftrag> Set<Projektauftrag> Set<Projektauftrag> Set<Projektauftrag> auftraegeauftraegeauftraegeauftraege
• EAGER: Alle Daten des Attributs werden bei Objektnutzung sofort in Hauptspeicher geladen (default)
• LAZY: Daten werden erst geladen, wenn benötigt
• Längere Listen oder komplexe Daten möglichst immer LAZY (versteckte Konsistenzprobleme möglich)
• Wenn eine Info sofort benötigt, ist Kette zur Info EAGER
Prof. Dr. Stephan Kleuker
195Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional M:N (1/6)
Prof. Dr. Stephan Kleuker
196Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional M:N (2/6)
@Entity@Entity@Entity@Entity
public class Projektauftrag implements Serializable {public class Projektauftrag implements Serializable {public class Projektauftrag implements Serializable {public class Projektauftrag implements Serializable {
@Id @GeneratedValue @Id @GeneratedValue @Id @GeneratedValue @Id @GeneratedValue
private int paid;private int paid;private int paid;private int paid;
private String titel;private String titel;private String titel;private String titel;
@ManyToOne(cascade={CascadeType.PERSIST, @ManyToOne(cascade={CascadeType.PERSIST, @ManyToOne(cascade={CascadeType.PERSIST, @ManyToOne(cascade={CascadeType.PERSIST,
CascadeType.MERGE})CascadeType.MERGE})CascadeType.MERGE})CascadeType.MERGE})
private Mitarbeiter bearbeiter;private Mitarbeiter bearbeiter;private Mitarbeiter bearbeiter;private Mitarbeiter bearbeiter;
@ManyToOne(cascade={CascadeType.PERSIST, @ManyToOne(cascade={CascadeType.PERSIST, @ManyToOne(cascade={CascadeType.PERSIST, @ManyToOne(cascade={CascadeType.PERSIST,
CascadeType.MERGE})CascadeType.MERGE})CascadeType.MERGE})CascadeType.MERGE})
private Rolle rolle;private Rolle rolle;private Rolle rolle;private Rolle rolle;
@Version@Version@Version@Version
private int version;private int version;private int version;private int version;
Prof. Dr. Stephan Kleuker
197Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional M:N (3/6)
@@@@EntityEntityEntityEntitypublicpublicpublicpublic classclassclassclass Rolle Rolle Rolle Rolle implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable {{{{
@ID @@ID @@ID @@ID @GeneratedValueGeneratedValueGeneratedValueGeneratedValue private private private private intintintint ridridridrid;;;;private String private String private String private String namenamenamename;;;;private private private private intintintint tagessatztagessatztagessatztagessatz;;;;
@@@@ManyToManyManyToManyManyToManyManyToMany((((cascadecascadecascadecascade = {= {= {= {CascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSIST, , , , CascadeType.MERGECascadeType.MERGECascadeType.MERGECascadeType.MERGE})})})})
@Basic(@Basic(@Basic(@Basic(fetchfetchfetchfetch = = = = FetchType.LAZYFetchType.LAZYFetchType.LAZYFetchType.LAZY))))private List<Mitarbeiter> private List<Mitarbeiter> private List<Mitarbeiter> private List<Mitarbeiter> mitarbeitermitarbeitermitarbeitermitarbeiter;;;;
@Version private @Version private @Version private @Version private intintintint versionversionversionversion;;;;
publicpublicpublicpublic voidvoidvoidvoid mitarbeiterHinzumitarbeiterHinzumitarbeiterHinzumitarbeiterHinzu(Mitarbeiter m) {(Mitarbeiter m) {(Mitarbeiter m) {(Mitarbeiter m) {mitarbeiter.addmitarbeiter.addmitarbeiter.addmitarbeiter.add(m);(m);(m);(m);
}}}}
Prof. Dr. Stephan Kleuker
198Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional M:N (4/6)
@@@@EntityEntityEntityEntitypublicpublicpublicpublic classclassclassclass Mitarbeiter Mitarbeiter Mitarbeiter Mitarbeiter implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable {{{{
@@@@IdIdIdId @@@@GeneratedValueGeneratedValueGeneratedValueGeneratedValue((((strategystrategystrategystrategy = = = = GenerationType.AUTOGenerationType.AUTOGenerationType.AUTOGenerationType.AUTO))))private private private private intintintint minrminrminrminr;;;;private String private String private String private String namenamenamename;;;;
@@@@OneToManyOneToManyOneToManyOneToMany((((mappedBymappedBymappedBymappedBy = "= "= "= "bearbeiterbearbeiterbearbeiterbearbeiter", ", ", ", cascadecascadecascadecascade = {= {= {= {CascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSIST, , , , CascadeType.MERGECascadeType.MERGECascadeType.MERGECascadeType.MERGE})})})})
@Basic(@Basic(@Basic(@Basic(fetchfetchfetchfetch = = = = FetchType.LAZYFetchType.LAZYFetchType.LAZYFetchType.LAZY))))private Set<Projektauftrag> private Set<Projektauftrag> private Set<Projektauftrag> private Set<Projektauftrag> auftraegeauftraegeauftraegeauftraege;;;;
@@@@ManyToManyManyToManyManyToManyManyToMany((((mappedBymappedBymappedBymappedBy = "= "= "= "mitarbeitermitarbeitermitarbeitermitarbeiter", ", ", ", cascadecascadecascadecascade = {= {= {= {CascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSIST, , , , CascadeType.MERGECascadeType.MERGECascadeType.MERGECascadeType.MERGE})})})})
@Basic(@Basic(@Basic(@Basic(fetchfetchfetchfetch = = = = FetchType.LAZYFetchType.LAZYFetchType.LAZYFetchType.LAZY))))private Set<Rolle> rollen = private Set<Rolle> rollen = private Set<Rolle> rollen = private Set<Rolle> rollen = newnewnewnew HashSetHashSetHashSetHashSet<Rolle<Rolle<Rolle<Rolle>();>();>();>();
@Version private @Version private @Version private @Version private intintintint versionversionversionversion;;;;
publicpublicpublicpublic voidvoidvoidvoid rolleHinzurolleHinzurolleHinzurolleHinzu(Rolle r) {(Rolle r) {(Rolle r) {(Rolle r) {rollen.addrollen.addrollen.addrollen.add(r(r(r(r););););
}}}}
Prof. Dr. Stephan Kleuker
199Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional M:N (5/6)
publicpublicpublicpublic void void void void mitarbeiterZuordnenmitarbeiterZuordnenmitarbeiterZuordnenmitarbeiterZuordnen() {() {() {() {Mitarbeiter m[] = {Mitarbeiter m[] = {Mitarbeiter m[] = {Mitarbeiter m[] = {newnewnewnew Mitarbeiter("Egon"), Mitarbeiter("Egon"), Mitarbeiter("Egon"), Mitarbeiter("Egon"),
newnewnewnew MitarbeiterMitarbeiterMitarbeiterMitarbeiter("("("("AiseAiseAiseAise"), "), "), "), newnewnewnew Mitarbeiter("Urs")};Mitarbeiter("Urs")};Mitarbeiter("Urs")};Mitarbeiter("Urs")};em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();forforforfor ((((intintintint i = 0; i < i = 0; i < i = 0; i < i = 0; i < m.lengthm.lengthm.lengthm.length; i++) ; i++) ; i++) ; i++)
em.persistem.persistem.persistem.persist(m[i]);(m[i]);(m[i]);(m[i]);Rolle r[] = {Rolle r[] = {Rolle r[] = {Rolle r[] = {newnewnewnew Rolle("OOAD",80), Rolle("OOAD",80), Rolle("OOAD",80), Rolle("OOAD",80), newnewnewnew Rolle("SVN",60), Rolle("SVN",60), Rolle("SVN",60), Rolle("SVN",60),
newnewnewnew Rolle("QS",100)};Rolle("QS",100)};Rolle("QS",100)};Rolle("QS",100)};forforforfor ((((intintintint i = 0; i < i = 0; i < i = 0; i < i = 0; i < r.lengthr.lengthr.lengthr.length; i++) {; i++) {; i++) {; i++) {
forforforfor((((intintintint j = 0; j<j = 0; j<j = 0; j<j = 0; j<m.lengthm.lengthm.lengthm.length; ; ; ; j++j++j++j++))))ifififif(r[i].(r[i].(r[i].(r[i].getNamegetNamegetNamegetName().().().().lengthlengthlengthlength()<m[j].()<m[j].()<m[j].()<m[j].getNamegetNamegetNamegetName().().().().lengthlengthlengthlength()){()){()){()){r[i].r[i].r[i].r[i].mitarbeiterHinzumitarbeiterHinzumitarbeiterHinzumitarbeiterHinzu(m[j]);(m[j]);(m[j]);(m[j]);m[j].m[j].m[j].m[j].rolleHinzurolleHinzurolleHinzurolleHinzu(r[i]);(r[i]);(r[i]);(r[i]);
}}}}em.persistem.persistem.persistem.persist(r[i]);(r[i]);(r[i]);(r[i]);
}}}}// Rollenzuordnung wie bei 1:N // Rollenzuordnung wie bei 1:N // Rollenzuordnung wie bei 1:N // Rollenzuordnung wie bei 1:N mitarbeiterZuordnenmitarbeiterZuordnenmitarbeiterZuordnenmitarbeiterZuordnen()()()()em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();
}}}}
Prof. Dr. Stephan Kleuker
200Komponentenbasierte Software-Entwicklung
Umsetzung bidirektional M:N (6/6)
Prof. Dr. Stephan Kleuker
201Komponentenbasierte Software-Entwicklung
Tabellenstruktur
Prof. Dr. Stephan Kleuker
202Komponentenbasierte Software-Entwicklung
Ungeordnete Daten (1/4)
@Entity@Entity@Entity@Entitypublic class Punkt implements Serializable{public class Punkt implements Serializable{public class Punkt implements Serializable{public class Punkt implements Serializable{@Id @GeneratedValue@Id @GeneratedValue@Id @GeneratedValue@Id @GeneratedValueprivate int id;private int id;private int id;private int id;private int x;private int x;private int x;private int x;private int y;private int y;private int y;private int y;@Version@Version@Version@Versionprivate int version;private int version;private int version;private int version;
public Punkt(int x, int y) {public Punkt(int x, int y) {public Punkt(int x, int y) {public Punkt(int x, int y) {this.x = x;this.x = x;this.x = x;this.x = x;this.y = y;this.y = y;this.y = y;this.y = y;
}}}}
public Punkt(){}public Punkt(){}public Punkt(){}public Punkt(){}
@Override@Override@Override@Overridepublic String toString(){public String toString(){public String toString(){public String toString(){return "["+x+","+y+"]";return "["+x+","+y+"]";return "["+x+","+y+"]";return "["+x+","+y+"]";
}}}}// get// get// get// get---- und setund setund setund set----Methoden für ExemplarvariablenMethoden für ExemplarvariablenMethoden für ExemplarvariablenMethoden für Exemplarvariablen
Problem: Auch Listen werden ungeordnet gespeichert
Prof. Dr. Stephan Kleuker
203Komponentenbasierte Software-Entwicklung
Ungeordnete Daten (2/4)
@Entity@Entity@Entity@Entitypublicpublicpublicpublic classclassclassclass Polygon Polygon Polygon Polygon implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable{{{{@@@@IdIdIdId @@@@GeneratedValueGeneratedValueGeneratedValueGeneratedValueprivate private private private intintintint idididid;;;;@@@@OneToManyOneToManyOneToManyOneToMany((((cascadecascadecascadecascade = {= {= {= {CascadeType.ALLCascadeType.ALLCascadeType.ALLCascadeType.ALL})})})})private List<Punkt> punkte= private List<Punkt> punkte= private List<Punkt> punkte= private List<Punkt> punkte= newnewnewnew ArrayListArrayListArrayListArrayList<Punkt>();<Punkt>();<Punkt>();<Punkt>();@Version private @Version private @Version private @Version private intintintint versionversionversionversion;;;;
publicpublicpublicpublic Polygon(){} //Polygon(){} //Polygon(){} //Polygon(){} //getgetgetget und und und und setsetsetset für Exemplarvariablenfür Exemplarvariablenfür Exemplarvariablenfür Exemplarvariablen
publicpublicpublicpublic void void void void punkteHinzupunkteHinzupunkteHinzupunkteHinzu(Punkt... (Punkt... (Punkt... (Punkt... pktepktepktepkte){){){){forforforfor(Punkt p:pkte)(Punkt p:pkte)(Punkt p:pkte)(Punkt p:pkte)punkte.addpunkte.addpunkte.addpunkte.add(p);(p);(p);(p);
}}}}
@@@@OverrideOverrideOverrideOverride publicpublicpublicpublic String String String String toStringtoStringtoStringtoString(){(){(){(){StringBufferStringBufferStringBufferStringBuffer ergergergerg====newnewnewnew StringBufferStringBufferStringBufferStringBuffer("<");("<");("<");("<");forforforfor(Punkt p:punkte)(Punkt p:punkte)(Punkt p:punkte)(Punkt p:punkte)erg.appenderg.appenderg.appenderg.append((((p.toStringp.toStringp.toStringp.toString());());());());
returnreturnreturnreturn erg.appenderg.appenderg.appenderg.append(">").(">").(">").(">").toStringtoStringtoStringtoString();();();();}}}}
Prof. Dr. Stephan Kleuker
204Komponentenbasierte Software-Entwicklung
Ungeordnete Daten (3/4)
publicpublicpublicpublic classclassclassclass Main {Main {Main {Main {private private private private EntityManagerFactoryEntityManagerFactoryEntityManagerFactoryEntityManagerFactory emfemfemfemf ====Persistence.createEntityManagerFactoryPersistence.createEntityManagerFactoryPersistence.createEntityManagerFactoryPersistence.createEntityManagerFactory("JPA20NeueFeaturesPU");("JPA20NeueFeaturesPU");("JPA20NeueFeaturesPU");("JPA20NeueFeaturesPU");private private private private EntityManagerEntityManagerEntityManagerEntityManager emememem = = = = emf.createEntityManageremf.createEntityManageremf.createEntityManageremf.createEntityManager();();();();
publicpublicpublicpublic voidvoidvoidvoid objekteErzeugenobjekteErzeugenobjekteErzeugenobjekteErzeugen(){(){(){(){Punkt[] Punkt[] Punkt[] Punkt[] pktpktpktpkt={={={={newnewnewnew Punkt(0,0), Punkt(0,0), Punkt(0,0), Punkt(0,0), newnewnewnew Punkt(5,3), Punkt(5,3), Punkt(5,3), Punkt(5,3),
newnewnewnew Punkt(3,3), Punkt(3,3), Punkt(3,3), Punkt(3,3), newnewnewnew Punkt(3,0)};Punkt(3,0)};Punkt(3,0)};Punkt(3,0)};em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();forforforfor(Punkt p:pkt)(Punkt p:pkt)(Punkt p:pkt)(Punkt p:pkt)em.persistem.persistem.persistem.persist(p);(p);(p);(p);
em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();Polygon p1 = Polygon p1 = Polygon p1 = Polygon p1 = newnewnewnew Polygon();Polygon();Polygon();Polygon();p1.punkteHinzu(p1.punkteHinzu(p1.punkteHinzu(p1.punkteHinzu(pktpktpktpkt[0],[0],[0],[0],pktpktpktpkt[1],[1],[1],[1],pktpktpktpkt[2]);[2]);[2]);[2]);Polygon p2 = Polygon p2 = Polygon p2 = Polygon p2 = newnewnewnew Polygon();Polygon();Polygon();Polygon();p2.punkteHinzu(p2.punkteHinzu(p2.punkteHinzu(p2.punkteHinzu(pktpktpktpkt[3],[3],[3],[3],pktpktpktpkt[2],[2],[2],[2],pktpktpktpkt[1]);[1]);[1]);[1]);em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();em.persistem.persistem.persistem.persist(p1);(p1);(p1);(p1);em.persistem.persistem.persistem.persist(p2(p2(p2(p2););););em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();
}}}}
Prof. Dr. Stephan Kleuker
205Komponentenbasierte Software-Entwicklung
Ungeordnete Daten (4/4)
publicpublicpublicpublic voidvoidvoidvoid zeigePolygonezeigePolygonezeigePolygonezeigePolygone(){(){(){(){List<Polygon> List<Polygon> List<Polygon> List<Polygon> plplplpl = = = = em.createQueryem.createQueryem.createQueryem.createQuery(((("SELECT p FROM Polygon p","SELECT p FROM Polygon p","SELECT p FROM Polygon p","SELECT p FROM Polygon p",Polygon.classPolygon.classPolygon.classPolygon.class).).).).getResultListgetResultListgetResultListgetResultList();();();();
forforforfor(Polygon (Polygon (Polygon (Polygon po:plpo:plpo:plpo:pl))))System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println((((popopopo););););
}}}}
publicpublicpublicpublic voidvoidvoidvoid schliessenschliessenschliessenschliessen() {() {() {() {ifififif ((((emememem != null && != null && != null && != null && em.isOpenem.isOpenem.isOpenem.isOpen()) ()) ()) ()) em.closeem.closeem.closeem.close();();();();ifififif ((((emfemfemfemf != null && != null && != null && != null && emf.isOpenemf.isOpenemf.isOpenemf.isOpen()) ()) ()) ()) emf.closeemf.closeemf.closeemf.close();();();();
}}}}
publicpublicpublicpublic staticstaticstaticstatic voidvoidvoidvoid mainmainmainmain(String[] (String[] (String[] (String[] argsargsargsargs) {) {) {) {Main m= Main m= Main m= Main m= newnewnewnew Main();Main();Main();Main();m.objekteErzeugenm.objekteErzeugenm.objekteErzeugenm.objekteErzeugen();();();();m.zeigePolygonem.zeigePolygonem.zeigePolygonem.zeigePolygone();();();();m.schliessenm.schliessenm.schliessenm.schliessen();();();();System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println("("("("----------------");");");");m= m= m= m= newnewnewnew Main();Main();Main();Main();m.zeigePolygonem.zeigePolygonem.zeigePolygonem.zeigePolygone();();();();m.schliessenm.schliessenm.schliessenm.schliessen();();();();
}}}}}}}}
<[0,0][5,3][3,3]> <[0,0][5,3][3,3]> <[0,0][5,3][3,3]> <[0,0][5,3][3,3]> <[3,0][3,3][5,3]><[3,0][3,3][5,3]><[3,0][3,3][5,3]><[3,0][3,3][5,3]>
----------------<[0,0][5,3][3,3]> <[0,0][5,3][3,3]> <[0,0][5,3][3,3]> <[0,0][5,3][3,3]> <[5,3][3,3][3,0]><[5,3][3,3][3,0]><[5,3][3,3][3,0]><[5,3][3,3][3,0]>
Prof. Dr. Stephan Kleuker
206Komponentenbasierte Software-Entwicklung
Ordnung beibehalten
@Entity@Entity@Entity@Entitypublicpublicpublicpublic classclassclassclass Polygon Polygon Polygon Polygon implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable{{{{@@@@IdIdIdId @@@@GeneratedValueGeneratedValueGeneratedValueGeneratedValueprivate private private private intintintint idididid;;;;@@@@OneToManyOneToManyOneToManyOneToMany((((cascadecascadecascadecascade = {= {= {= {CascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSIST, , , , CascadeType.MERGECascadeType.MERGECascadeType.MERGECascadeType.MERGE})})})})@@@@OrderColumnOrderColumnOrderColumnOrderColumn((((namenamenamename="="="="OrdOrdOrdOrd")")")")private List<Punkt> punkte= private List<Punkt> punkte= private List<Punkt> punkte= private List<Punkt> punkte= newnewnewnew ArrayListArrayListArrayListArrayList<Punkt>();<Punkt>();<Punkt>();<Punkt>();@Version@Version@Version@Versionprivate private private private intintintint versionversionversionversion;;;;
Hinweis: persistence.xml mit create
<[3,0][3,3][5,3]><[3,0][3,3][5,3]><[3,0][3,3][5,3]><[3,0][3,3][5,3]><[0,0][5,3][3,3]><[0,0][5,3][3,3]><[0,0][5,3][3,3]><[0,0][5,3][3,3]>----------------<[3,0][3,3][5,3]><[3,0][3,3][5,3]><[3,0][3,3][5,3]><[3,0][3,3][5,3]><[0,0][5,3][3,3]><[0,0][5,3][3,3]><[0,0][5,3][3,3]><[0,0][5,3][3,3]>
Prof. Dr. Stephan Kleuker
207Komponentenbasierte Software-Entwicklung
Standard: keine Löschfortsetzung (1/2)
publicpublicpublicpublic void void void void objekteErzeugenobjekteErzeugenobjekteErzeugenobjekteErzeugen() {() {() {() {Punkt[] Punkt[] Punkt[] Punkt[] pktpktpktpkt = {= {= {= {newnewnewnew Punkt(0, 0), Punkt(0, 0), Punkt(0, 0), Punkt(0, 0), newnewnewnew Punkt(5, 3), Punkt(5, 3), Punkt(5, 3), Punkt(5, 3),
newnewnewnew Punkt(3, 3)};Punkt(3, 3)};Punkt(3, 3)};Punkt(3, 3)};Polygon p1 = Polygon p1 = Polygon p1 = Polygon p1 = newnewnewnew Polygon();Polygon();Polygon();Polygon();p1.punkteHinzu(p1.punkteHinzu(p1.punkteHinzu(p1.punkteHinzu(pktpktpktpkt[0], [0], [0], [0], pktpktpktpkt[1], [1], [1], [1], pktpktpktpkt[2]);[2]);[2]);[2]);em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();em.persistem.persistem.persistem.persist(p1);(p1);(p1);(p1);em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();
}}}}
publicpublicpublicpublic void void void void objekteBearbeitenobjekteBearbeitenobjekteBearbeitenobjekteBearbeiten() {() {() {() {Polygon Polygon Polygon Polygon plplplpl = = = = em.createQueryem.createQueryem.createQueryem.createQuery("SELECT p FROM Polygon p", ("SELECT p FROM Polygon p", ("SELECT p FROM Polygon p", ("SELECT p FROM Polygon p",
Polygon.classPolygon.classPolygon.classPolygon.class).).).).getResultListgetResultListgetResultListgetResultList().().().().getgetgetget(0);(0);(0);(0);pl.getPunktepl.getPunktepl.getPunktepl.getPunkte().().().().removeremoveremoveremove(1);(1);(1);(1);em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();em.persistem.persistem.persistem.persist((((plplplpl););););em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();
}}}}
Prof. Dr. Stephan Kleuker
208Komponentenbasierte Software-Entwicklung
Standard: keine Löschfortsetzung (2/2)
publicpublicpublicpublic void void void void zeigePolygoneUndPunktezeigePolygoneUndPunktezeigePolygoneUndPunktezeigePolygoneUndPunkte() {() {() {() {forforforfor (Polygon (Polygon (Polygon (Polygon popopopo : : : : em.createQueryem.createQueryem.createQueryem.createQuery("SELECT p FROM Polygon p", ("SELECT p FROM Polygon p", ("SELECT p FROM Polygon p", ("SELECT p FROM Polygon p",
Polygon.classPolygon.classPolygon.classPolygon.class).).).).getResultListgetResultListgetResultListgetResultList())())())())System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println((((popopopo););););
System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println("("("("----------------");");");");forforforfor (Punkt (Punkt (Punkt (Punkt pupupupu : : : : em.createQueryem.createQueryem.createQueryem.createQuery("SELECT p FROM Punkt p", ("SELECT p FROM Punkt p", ("SELECT p FROM Punkt p", ("SELECT p FROM Punkt p",
Punkt.classPunkt.classPunkt.classPunkt.class).).).).getResultListgetResultListgetResultListgetResultList()) ()) ()) ()) System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println((((pupupupu););););
}}}}
publicpublicpublicpublic staticstaticstaticstatic void void void void mainmainmainmain(String[] (String[] (String[] (String[] argsargsargsargs) {) {) {) {Main m = Main m = Main m = Main m = newnewnewnew Main();Main();Main();Main();m.objekteErzeugenm.objekteErzeugenm.objekteErzeugenm.objekteErzeugen();();();();m.objekteBearbeitenm.objekteBearbeitenm.objekteBearbeitenm.objekteBearbeiten();();();();m.zeigePolygoneUndPunktem.zeigePolygoneUndPunktem.zeigePolygoneUndPunktem.zeigePolygoneUndPunkte();();();();m.schliessenm.schliessenm.schliessenm.schliessen();();();();
}}}}
<[0,0][3,3]><[0,0][3,3]><[0,0][3,3]><[0,0][3,3]>----------------[0,0][0,0][0,0][0,0][5,3][5,3][5,3][5,3][3,3][3,3][3,3][3,3]
Prof. Dr. Stephan Kleuker
209Komponentenbasierte Software-Entwicklung
Löschfortsetzung
• Anmerkung: auch keine Löschung alleine durch CASCADETYPE.ALLCASCADETYPE.ALLCASCADETYPE.ALLCASCADETYPE.ALL
in Polygon, aber durch folgende Ergänzung
@@@@OneToManyOneToManyOneToManyOneToMany((((cascadecascadecascadecascade = {= {= {= {CascadeType.ALLCascadeType.ALLCascadeType.ALLCascadeType.ALL}, }, }, },
orphanRemovalorphanRemovalorphanRemovalorphanRemoval====truetruetruetrue))))
@@@@OrderColumnOrderColumnOrderColumnOrderColumn((((namenamenamename="="="="OrdOrdOrdOrd")")")")
private List<Punkt> punkte = private List<Punkt> punkte = private List<Punkt> punkte = private List<Punkt> punkte =
newnewnewnew ArrayListArrayListArrayListArrayList<Punkt>();<Punkt>();<Punkt>();<Punkt>();
• Was passiert, wenn mehrere Objekte Punkt referenzieren (widerspricht der Eigentümerschaft)?
Exception Exception Exception Exception in thread "main“ in thread "main“ in thread "main“ in thread "main“ javax.persistence.RollbackExceptionjavax.persistence.RollbackExceptionjavax.persistence.RollbackExceptionjavax.persistence.RollbackException
CausedCausedCausedCaused bybybyby: : : : java.sql.SQLIntegrityConstraintViolationExceptionjava.sql.SQLIntegrityConstraintViolationExceptionjava.sql.SQLIntegrityConstraintViolationExceptionjava.sql.SQLIntegrityConstraintViolationException: : : : DELETE in Tabelle 'PUNKT' hat für Schlüssel (3) die DELETE in Tabelle 'PUNKT' hat für Schlüssel (3) die DELETE in Tabelle 'PUNKT' hat für Schlüssel (3) die DELETE in Tabelle 'PUNKT' hat für Schlüssel (3) die Integritätsbedingung 'PLYGONPUNKTPNKTEID' für Fremdschlüssel Integritätsbedingung 'PLYGONPUNKTPNKTEID' für Fremdschlüssel Integritätsbedingung 'PLYGONPUNKTPNKTEID' für Fremdschlüssel Integritätsbedingung 'PLYGONPUNKTPNKTEID' für Fremdschlüssel verletzt.verletzt.verletzt.verletzt.
<[0,0][3,3]><[0,0][3,3]><[0,0][3,3]><[0,0][3,3]>----------------[0,0][0,0][0,0][0,0][3,3][3,3][3,3][3,3]
Prof. Dr. Stephan Kleuker
210Komponentenbasierte Software-Entwicklung
Beispieldaten (in DB-Notation)
Mitarbeiter
Projekt
Rolle
Projektauftrag
Projekt_Projektauftrag
Prof. Dr. Stephan Kleuker
211Komponentenbasierte Software-Entwicklung
Anfragen
• Anfragesprache soll möglichst Entity-Objekte liefern
• Anfragesprache soll DB-unabhängig sein (SQL-Detailproblem)
• Antwort: Java Persistence QL (JPQL)
– Ermöglicht direkte Zurückgabe von Entitätsobjektlisten
– Ermöglicht auch direkte Ausführung von SQL-Anfragen
• Anmerkung: Vorgänger JDO unterstützte OO-Features in JDO-QL (Methodennutzung); dies ist nicht mehr möglich
• Typische Struktur:
– SELECT p FROM Projekt p WHERE <Bed>SELECT p FROM Projekt p WHERE <Bed>SELECT p FROM Projekt p WHERE <Bed>SELECT p FROM Projekt p WHERE <Bed>
– Übersetzung: Wähle aus der Menge Projekt der gemanageten Objekte die Elemente p mit Eigenschaft <Bed>
Prof. Dr. Stephan Kleuker
212Komponentenbasierte Software-Entwicklung
Anfrageausführung
• Setzt ordentliches toString() voraus
• ist nicht typsicherpublicpublicpublicpublic voidvoidvoidvoid anfragen(String anfragen(String anfragen(String anfragen(String qlqlqlql) {) {) {) {
trytrytrytry {{{{
Query Query Query Query queryqueryqueryquery = = = = em.createQueryem.createQueryem.createQueryem.createQuery((((qlqlqlql););););
CollectionCollectionCollectionCollection ergergergerg = = = = query.getResultListquery.getResultListquery.getResultListquery.getResultList();();();();
forforforfor ((((IteratorIteratorIteratorIterator itititit = = = = erg.iteratorerg.iteratorerg.iteratorerg.iterator(); (); (); (); it.hasNextit.hasNextit.hasNextit.hasNext();) {();) {();) {();) {
System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println((((it.nextit.nextit.nextit.next());());());());
}}}}
} catch (Exception e) {} catch (Exception e) {} catch (Exception e) {} catch (Exception e) {
System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println("Anfrage gescheitert: " ("Anfrage gescheitert: " ("Anfrage gescheitert: " ("Anfrage gescheitert: "
+ + + + e.getMessagee.getMessagee.getMessagee.getMessage());());());());
}}}}
}}}}
Prof. Dr. Stephan Kleuker
213Komponentenbasierte Software-Entwicklung
Einfache Beispiele
Vorbemerkung: In FROM-Zeilen stehen Klassen und Attributnamen; bei diesen muss Groß- und Kleinschreibung beachtet werden!
SELECT p FROM Projekt pSELECT p FROM Projekt pSELECT p FROM Projekt pSELECT p FROM Projekt p
• Projekt Projekt Projekt Projekt BonitaetBonitaetBonitaetBonitaet ((((5555) ) ) ) [Konten Historie Raten ][Konten Historie Raten ][Konten Historie Raten ][Konten Historie Raten ]
• Projekt Bremse Projekt Bremse Projekt Bremse Projekt Bremse (11) (11) (11) (11) [Display Sensoren Fusion ][Display Sensoren Fusion ][Display Sensoren Fusion ][Display Sensoren Fusion ]
Direkter Zugriff auf Attribute
SELECT p.name FROM Projekt pSELECT p.name FROM Projekt pSELECT p.name FROM Projekt pSELECT p.name FROM Projekt p
• BonitaetBonitaetBonitaetBonitaet
• BremseBremseBremseBremse
Prof. Dr. Stephan Kleuker
214Komponentenbasierte Software-Entwicklung
Nutzung mehrwertiger Relationen (1/2)
SELECT SELECT SELECT SELECT p.auftraegep.auftraegep.auftraegep.auftraege FROM Projekt pFROM Projekt pFROM Projekt pFROM Projekt p
• Aufgabe Raten Aufgabe Raten Aufgabe Raten Aufgabe Raten (10) (10) (10) (10) durch Ivan als Javadurch Ivan als Javadurch Ivan als Javadurch Ivan als Java
• Aufgabe Konten Aufgabe Konten Aufgabe Konten Aufgabe Konten ((((6666) ) ) ) durch Fatma als Coboldurch Fatma als Coboldurch Fatma als Coboldurch Fatma als Cobol
• Aufgabe Historie Aufgabe Historie Aufgabe Historie Aufgabe Historie ((((8888) ) ) ) durch Urs als Javadurch Urs als Javadurch Urs als Javadurch Urs als Java
• Aufgabe Sensoren Aufgabe Sensoren Aufgabe Sensoren Aufgabe Sensoren (12) (12) (12) (12) durch Ivan als Cdurch Ivan als Cdurch Ivan als Cdurch Ivan als C
• Aufgabe Display Aufgabe Display Aufgabe Display Aufgabe Display (14) (14) (14) (14) durch Fatma als Javadurch Fatma als Javadurch Fatma als Javadurch Fatma als Java
• Aufgabe Fusion Aufgabe Fusion Aufgabe Fusion Aufgabe Fusion (15) (15) (15) (15) durch Ivan als Cdurch Ivan als Cdurch Ivan als Cdurch Ivan als C
Nicht erlaubt:
SELECT SELECT SELECT SELECT p.auftraege.bearbeiterp.auftraege.bearbeiterp.auftraege.bearbeiterp.auftraege.bearbeiter FROM Projekt pFROM Projekt pFROM Projekt pFROM Projekt p
• An exception occurred while creating a query in An exception occurred while creating a query in An exception occurred while creating a query in An exception occurred while creating a query in EntityManagerEntityManagerEntityManagerEntityManager::::
Exception Exception Exception Exception Description: Error compiling the query [SELECT Description: Error compiling the query [SELECT Description: Error compiling the query [SELECT Description: Error compiling the query [SELECT p.auftraege.bearbeiterp.auftraege.bearbeiterp.auftraege.bearbeiterp.auftraege.bearbeiter FROM FROM FROM FROM ProjektProjektProjektProjekt p], line 1, column 9: p], line 1, column 9: p], line 1, column 9: p], line 1, column 9: invalid navigation expression [invalid navigation expression [invalid navigation expression [invalid navigation expression [p.auftraege.bearbeiterp.auftraege.bearbeiterp.auftraege.bearbeiterp.auftraege.bearbeiter], cannot ], cannot ], cannot ], cannot navigate collection valued association field [navigate collection valued association field [navigate collection valued association field [navigate collection valued association field [auftraegeauftraegeauftraegeauftraege].].].].
Prof. Dr. Stephan Kleuker
215Komponentenbasierte Software-Entwicklung
Nutzung mehrwertiger Relationen (2/2)
SELECT SELECT SELECT SELECT pa.bearbeiterpa.bearbeiterpa.bearbeiterpa.bearbeiter FROM Projektauftrag FROM Projektauftrag FROM Projektauftrag FROM Projektauftrag papapapa
1: Ivan 1: Ivan 1: Ivan 1: Ivan AuftraegeAuftraegeAuftraegeAuftraege=[ Sensoren Fusion Raten ]=[ Sensoren Fusion Raten ]=[ Sensoren Fusion Raten ]=[ Sensoren Fusion Raten ]
Rollen=[ C Java ]Rollen=[ C Java ]Rollen=[ C Java ]Rollen=[ C Java ]
1: Ivan 1: Ivan 1: Ivan 1: Ivan AuftraegeAuftraegeAuftraegeAuftraege=[ Sensoren Fusion Raten ]=[ Sensoren Fusion Raten ]=[ Sensoren Fusion Raten ]=[ Sensoren Fusion Raten ]
Rollen=[ C Java ]Rollen=[ C Java ]Rollen=[ C Java ]Rollen=[ C Java ]
1: Ivan 1: Ivan 1: Ivan 1: Ivan AuftraegeAuftraegeAuftraegeAuftraege=[ Sensoren Fusion Raten ]=[ Sensoren Fusion Raten ]=[ Sensoren Fusion Raten ]=[ Sensoren Fusion Raten ]
Rollen=[ C Java ]Rollen=[ C Java ]Rollen=[ C Java ]Rollen=[ C Java ]
2222: : : : Fatma Fatma Fatma Fatma AuftraegeAuftraegeAuftraegeAuftraege=[ Konten Display ]=[ Konten Display ]=[ Konten Display ]=[ Konten Display ]
Rollen=[ Cobol Java ]Rollen=[ Cobol Java ]Rollen=[ Cobol Java ]Rollen=[ Cobol Java ]
2222: : : : Fatma Fatma Fatma Fatma AuftraegeAuftraegeAuftraegeAuftraege=[ Konten Display ]=[ Konten Display ]=[ Konten Display ]=[ Konten Display ]
Rollen=[ Cobol Java ]Rollen=[ Cobol Java ]Rollen=[ Cobol Java ]Rollen=[ Cobol Java ]
3333: : : : Urs Urs Urs Urs AuftraegeAuftraegeAuftraegeAuftraege=[ Historie ]=[ Historie ]=[ Historie ]=[ Historie ]
Rollen=[ Java ]Rollen=[ Java ]Rollen=[ Java ]Rollen=[ Java ]
Prof. Dr. Stephan Kleuker
216Komponentenbasierte Software-Entwicklung
Neu zusammengesetzte Ergebnisse
• Folgende Folie zeigt woher Details der Ausgabe kommen
SELECT r.name, SELECT r.name, SELECT r.name, SELECT r.name, r.tagessatzr.tagessatzr.tagessatzr.tagessatz FROM Rolle rFROM Rolle rFROM Rolle rFROM Rolle r
• [[[[Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;@1db5ec :: [;@1db5ec :: [;@1db5ec :: [;@1db5ec :: [Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;;;;
CCCC
50505050
• [[[[Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;@92b1a1 :: [;@92b1a1 :: [;@92b1a1 :: [;@92b1a1 :: [Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;;;;
JavaJavaJavaJava
60606060
• [[[[Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;@cbf9bd :: [;@cbf9bd :: [;@cbf9bd :: [;@cbf9bd :: [Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;;;;
CobolCobolCobolCobol
70707070
Prof. Dr. Stephan Kleuker
217Komponentenbasierte Software-Entwicklung
Ausgabe mit detaillierterer Analyse
public void anfragen2(String ql) {public void anfragen2(String ql) {public void anfragen2(String ql) {public void anfragen2(String ql) {System.out.println(ql);System.out.println(ql);System.out.println(ql);System.out.println(ql);try {try {try {try {Query query = em.createQuery(ql);Query query = em.createQuery(ql);Query query = em.createQuery(ql);Query query = em.createQuery(ql);Collection erg = query.getResultList();Collection erg = query.getResultList();Collection erg = query.getResultList();Collection erg = query.getResultList();for (Iterator it = erg.iterator(); it.hasNext();) {for (Iterator it = erg.iterator(); it.hasNext();) {for (Iterator it = erg.iterator(); it.hasNext();) {for (Iterator it = erg.iterator(); it.hasNext();) {Object o = it.next();Object o = it.next();Object o = it.next();Object o = it.next();System.out.println(o+" :: "+ o.getClass().getName());System.out.println(o+" :: "+ o.getClass().getName());System.out.println(o+" :: "+ o.getClass().getName());System.out.println(o+" :: "+ o.getClass().getName());if(o.getClass().getName().equals("[Ljava.lang.Object;")){if(o.getClass().getName().equals("[Ljava.lang.Object;")){if(o.getClass().getName().equals("[Ljava.lang.Object;")){if(o.getClass().getName().equals("[Ljava.lang.Object;")){Object oa[]= (Object[]) o;Object oa[]= (Object[]) o;Object oa[]= (Object[]) o;Object oa[]= (Object[]) o;for(int i=0;i<oa.length;i++)for(int i=0;i<oa.length;i++)for(int i=0;i<oa.length;i++)for(int i=0;i<oa.length;i++)System.out.println(" "+oa[i]);System.out.println(" "+oa[i]);System.out.println(" "+oa[i]);System.out.println(" "+oa[i]);
}}}}}}}}
} catch (Exception e) {} catch (Exception e) {} catch (Exception e) {} catch (Exception e) {System.out.println("Anfragefehler: " + e.getMessage());System.out.println("Anfragefehler: " + e.getMessage());System.out.println("Anfragefehler: " + e.getMessage());System.out.println("Anfragefehler: " + e.getMessage());
}}}}}}}}
Prof. Dr. Stephan Kleuker
218Komponentenbasierte Software-Entwicklung
JOIN-Varianten
SELECT m.name SELECT m.name SELECT m.name SELECT m.name
FROM Projektauftrag FROM Projektauftrag FROM Projektauftrag FROM Projektauftrag papapapa, Mitarbeiter m , Mitarbeiter m , Mitarbeiter m , Mitarbeiter m
WHERE WHERE WHERE WHERE pa.bearbeiterpa.bearbeiterpa.bearbeiterpa.bearbeiter=m =m =m =m
AND AND AND AND pa.titelpa.titelpa.titelpa.titel='Sensoren'='Sensoren'='Sensoren'='Sensoren'
SELECT m.name SELECT m.name SELECT m.name SELECT m.name
FROM Projektauftrag FROM Projektauftrag FROM Projektauftrag FROM Projektauftrag papapapa JOIN JOIN JOIN JOIN pa.bearbeiterpa.bearbeiterpa.bearbeiterpa.bearbeiter m m m m
WHERE WHERE WHERE WHERE pa.titelpa.titelpa.titelpa.titel='Sensoren'='Sensoren'='Sensoren'='Sensoren'
• IvanIvanIvanIvan
SELECT DISTINCT(pa.bearbeiter.name) SELECT DISTINCT(pa.bearbeiter.name) SELECT DISTINCT(pa.bearbeiter.name) SELECT DISTINCT(pa.bearbeiter.name)
FROM Projekt p JOIN FROM Projekt p JOIN FROM Projekt p JOIN FROM Projekt p JOIN p.auftraegep.auftraegep.auftraegep.auftraege papapapa
WHERE p.name='Bremse'WHERE p.name='Bremse'WHERE p.name='Bremse'WHERE p.name='Bremse'
• FatmaFatmaFatmaFatma
• IvanIvanIvanIvan
Prof. Dr. Stephan Kleuker
219Komponentenbasierte Software-Entwicklung
Vordefinierte Anfragen + typisches Problem
private static final String PROJEKT_VON=private static final String PROJEKT_VON=private static final String PROJEKT_VON=private static final String PROJEKT_VON="SELECT DISTINCT(p.name) " "SELECT DISTINCT(p.name) " "SELECT DISTINCT(p.name) " "SELECT DISTINCT(p.name) " +"FROM Projekt p JOIN p.auftraege pa " +"FROM Projekt p JOIN p.auftraege pa " +"FROM Projekt p JOIN p.auftraege pa " +"FROM Projekt p JOIN p.auftraege pa " +"WHERE pa.bearbeiter.name= :mname";+"WHERE pa.bearbeiter.name= :mname";+"WHERE pa.bearbeiter.name= :mname";+"WHERE pa.bearbeiter.name= :mname";
public void projektVon(String name){public void projektVon(String name){public void projektVon(String name){public void projektVon(String name){Query query = em.createQuery(PROJEKT_VON).Query query = em.createQuery(PROJEKT_VON).Query query = em.createQuery(PROJEKT_VON).Query query = em.createQuery(PROJEKT_VON).
setParameter("mname", name);setParameter("mname", name);setParameter("mname", name);setParameter("mname", name);Collection erg = query.getResultList();Collection erg = query.getResultList();Collection erg = query.getResultList();Collection erg = query.getResultList();for (Iterator it = erg.iterator(); it.hasNext();) {for (Iterator it = erg.iterator(); it.hasNext();) {for (Iterator it = erg.iterator(); it.hasNext();) {for (Iterator it = erg.iterator(); it.hasNext();) {System.out.println(it.next());System.out.println(it.next());System.out.println(it.next());System.out.println(it.next());
}}}}}}}}
projektVon("Urs' OR NOT(p.name='bla') OR p.name='bla")projektVon("Urs' OR NOT(p.name='bla') OR p.name='bla")projektVon("Urs' OR NOT(p.name='bla') OR p.name='bla")projektVon("Urs' OR NOT(p.name='bla') OR p.name='bla")• BremseBremseBremseBremse• BonitaetBonitaetBonitaetBonitaet
Prof. Dr. Stephan Kleuker
220Komponentenbasierte Software-Entwicklung
echte Standardkonformität?
• gerade bei Anfragen häufig keine 100%-Kompatibilität
• Hibernate meist etwas mächtiger als EclipseLink
• Beispiel: Zeige alle C-Programmierer
• geht:
SELECT SELECT SELECT SELECT m FROM m FROM m FROM m FROM RolleRolleRolleRolle r JOIN r JOIN r JOIN r JOIN r.mitarbeiterr.mitarbeiterr.mitarbeiterr.mitarbeiter m WHERE r.name='C‘m WHERE r.name='C‘m WHERE r.name='C‘m WHERE r.name='C‘
[[[[1: Ivan...1: Ivan...1: Ivan...1: Ivan...
• ging lange Zeit nicht in EclipseLink:
SELECT SELECT SELECT SELECT m FROM m FROM m FROM m FROM MitarbeiterMitarbeiterMitarbeiterMitarbeiter m JOIN m JOIN m JOIN m JOIN m.rollenm.rollenm.rollenm.rollen r WHERE r.name='C'r WHERE r.name='C'r WHERE r.name='C'r WHERE r.name='C'
invalid invalid invalid invalid navigation expression [r.name], cannot navigate navigation expression [r.name], cannot navigate navigation expression [r.name], cannot navigate navigation expression [r.name], cannot navigate expression [r] of type [expression [r] of type [expression [r] of type [expression [r] of type [java.util.Listjava.util.Listjava.util.Listjava.util.List] inside a query.] inside a query.] inside a query.] inside a query.
• trotzdem: Immer sinnvoll Objektauswahlen in Anfragesprache durchzuführen, nicht alle Objekte aus DB lutschen und dann verarbeiten
Prof. Dr. Stephan Kleuker
221Komponentenbasierte Software-Entwicklung
Klassische SQL-Operatoren
SELECT p.name, COUNT(SELECT p.name, COUNT(SELECT p.name, COUNT(SELECT p.name, COUNT(pa.titelpa.titelpa.titelpa.titel) ) ) )
FROM Projekt p JOIN FROM Projekt p JOIN FROM Projekt p JOIN FROM Projekt p JOIN p.auftraegep.auftraegep.auftraegep.auftraege papapapa
GROUP BY p.nameGROUP BY p.nameGROUP BY p.nameGROUP BY p.name
• [[[[Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;@4a9a7d :: [;@4a9a7d :: [;@4a9a7d :: [;@4a9a7d :: [Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;;;;
BonitaetBonitaetBonitaetBonitaet
3333
• [[[[Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;@1e4a47e :: [;@1e4a47e :: [;@1e4a47e :: [;@1e4a47e :: [Ljava.lang.ObjectLjava.lang.ObjectLjava.lang.ObjectLjava.lang.Object;;;;
BremseBremseBremseBremse
3333
• Erinnerung AVG, SUM, MIN, MAX
Prof. Dr. Stephan Kleuker
222Komponentenbasierte Software-Entwicklung
Named Queries
@@@@NamedQueriesNamedQueriesNamedQueriesNamedQueries({ //in Mitarbeiter ({ //in Mitarbeiter ({ //in Mitarbeiter ({ //in Mitarbeiter (@(@(@(@NamedQueryNamedQueryNamedQueryNamedQuery((((namenamenamename="="="="Mitarbeiter.primaryKeyMitarbeiter.primaryKeyMitarbeiter.primaryKeyMitarbeiter.primaryKey",",",",
queryqueryqueryquery="SELECT m FROM Mitarbeiter m WHERE ="SELECT m FROM Mitarbeiter m WHERE ="SELECT m FROM Mitarbeiter m WHERE ="SELECT m FROM Mitarbeiter m WHERE m.minrm.minrm.minrm.minr= := := := :minrminrminrminr"),"),"),"),@@@@NamedQueryNamedQueryNamedQueryNamedQuery((((namenamenamename="="="="Mitarbeiter.mitFaehigkeitMitarbeiter.mitFaehigkeitMitarbeiter.mitFaehigkeitMitarbeiter.mitFaehigkeit",",",",
queryqueryqueryquery="SELECT m FROM Rolle r JOIN ="SELECT m FROM Rolle r JOIN ="SELECT m FROM Rolle r JOIN ="SELECT m FROM Rolle r JOIN r.mitarbeiterr.mitarbeiterr.mitarbeiterr.mitarbeiter m"m"m"m"+" WHERE r.name = :+" WHERE r.name = :+" WHERE r.name = :+" WHERE r.name = :namenamenamename")")")")
})})})})
// z. B. in Main mit lokalen Variablen // z. B. in Main mit lokalen Variablen // z. B. in Main mit lokalen Variablen // z. B. in Main mit lokalen Variablen minrminrminrminr und und und und faehigkeitfaehigkeitfaehigkeitfaehigkeitMitarbeiter m= Mitarbeiter m= Mitarbeiter m= Mitarbeiter m= emememem
....createNamedQuerycreateNamedQuerycreateNamedQuerycreateNamedQuery("("("("Mitarbeiter.primaryKeyMitarbeiter.primaryKeyMitarbeiter.primaryKeyMitarbeiter.primaryKey"""",,,,Mitarbeiter.classMitarbeiter.classMitarbeiter.classMitarbeiter.class))))
....setParametersetParametersetParametersetParameter("("("("minrminrminrminr", ", ", ", minrminrminrminr))))
....getSingleResultgetSingleResultgetSingleResultgetSingleResult();();();();
forforforfor( Mitarbeiter ( Mitarbeiter ( Mitarbeiter ( Mitarbeiter m:em // m:em // m:em // m:em // EclipseLinkEclipseLinkEclipseLinkEclipseLink Object m:emObject m:emObject m:emObject m:em....createNamedQuerycreateNamedQuerycreateNamedQuerycreateNamedQuery("("("("Mitarbeiter.mitFaehigkeitMitarbeiter.mitFaehigkeitMitarbeiter.mitFaehigkeitMitarbeiter.mitFaehigkeit""""
,,,,Mitarbeiter.classMitarbeiter.classMitarbeiter.classMitarbeiter.class))))....setParametersetParametersetParametersetParameter("("("("namenamenamename", ", ", ", faehigkeitfaehigkeitfaehigkeitfaehigkeit))))....getResultListgetResultListgetResultListgetResultList())())())())
System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println(m);(m);(m);(m);
Prof. Dr. Stephan Kleuker
223Komponentenbasierte Software-Entwicklung
Flexiblere Anfragenkonstruktion (Ausblick)
public void ooartigeAnfragekonstruktion(){public void ooartigeAnfragekonstruktion(){public void ooartigeAnfragekonstruktion(){public void ooartigeAnfragekonstruktion(){
CriteriaBuilder qB = em.getCriteriaBuilder();CriteriaBuilder qB = em.getCriteriaBuilder();CriteriaBuilder qB = em.getCriteriaBuilder();CriteriaBuilder qB = em.getCriteriaBuilder();
CriteriaQuery<Mitarbeiter> cQ =CriteriaQuery<Mitarbeiter> cQ =CriteriaQuery<Mitarbeiter> cQ =CriteriaQuery<Mitarbeiter> cQ =
qB.createQuery(Mitarbeiter.class);qB.createQuery(Mitarbeiter.class);qB.createQuery(Mitarbeiter.class);qB.createQuery(Mitarbeiter.class);
Root<Mitarbeiter> mAlias= cQ.from(Mitarbeiter.class);Root<Mitarbeiter> mAlias= cQ.from(Mitarbeiter.class);Root<Mitarbeiter> mAlias= cQ.from(Mitarbeiter.class);Root<Mitarbeiter> mAlias= cQ.from(Mitarbeiter.class);
cQ.where(qB.notEqual(mAlias.get("name"), "Urs"));cQ.where(qB.notEqual(mAlias.get("name"), "Urs"));cQ.where(qB.notEqual(mAlias.get("name"), "Urs"));cQ.where(qB.notEqual(mAlias.get("name"), "Urs"));
TypedQuery<Mitarbeiter> tq=em.createQuery(cQ);TypedQuery<Mitarbeiter> tq=em.createQuery(cQ);TypedQuery<Mitarbeiter> tq=em.createQuery(cQ);TypedQuery<Mitarbeiter> tq=em.createQuery(cQ);
for(Mitarbeiter m:tq.getResultList())for(Mitarbeiter m:tq.getResultList())for(Mitarbeiter m:tq.getResultList())for(Mitarbeiter m:tq.getResultList())
System.out.println(m.getName());System.out.println(m.getName());System.out.println(m.getName());System.out.println(m.getName());
}}}}
IvanIvanIvanIvanFatmaFatmaFatmaFatmaHeinzHeinzHeinzHeinz
Prof. Dr. Stephan Kleuker
224Komponentenbasierte Software-Entwicklung
Vererbung – eine Tabelle (1/3)
@Entity@Entity@Entity@Entitypublic class Produkt implements Serializable {public class Produkt implements Serializable {public class Produkt implements Serializable {public class Produkt implements Serializable {@Id @GeneratedValue private int prnr;@Id @GeneratedValue private int prnr;@Id @GeneratedValue private int prnr;@Id @GeneratedValue private int prnr;private String name;private String name;private String name;private String name;private int lagermenge;private int lagermenge;private int lagermenge;private int lagermenge;private float preis;private float preis;private float preis;private float preis;@Version private int version; ...}@Version private int version; ...}@Version private int version; ...}@Version private int version; ...}
@Entity@Entity@Entity@Entitypublic class Lebensmittel extends Produkt implements public class Lebensmittel extends Produkt implements public class Lebensmittel extends Produkt implements public class Lebensmittel extends Produkt implements
Serializable{Serializable{Serializable{Serializable{@Temporal(javax.persistence.TemporalType.DATE)@Temporal(javax.persistence.TemporalType.DATE)@Temporal(javax.persistence.TemporalType.DATE)@Temporal(javax.persistence.TemporalType.DATE)private Date verfallsdatum; ...}private Date verfallsdatum; ...}private Date verfallsdatum; ...}private Date verfallsdatum; ...}
@Entity@Entity@Entity@Entitypublic class Buch extends Produkt{ ...}public class Buch extends Produkt{ ...}public class Buch extends Produkt{ ...}public class Buch extends Produkt{ ...}
Prof. Dr. Stephan Kleuker
225Komponentenbasierte Software-Entwicklung
Vererbung – eine Tabelle (2/3)
public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {
EntityManagerFactory eMF =Persistence.EntityManagerFactory eMF =Persistence.EntityManagerFactory eMF =Persistence.EntityManagerFactory eMF =Persistence.
createEntityManagerFactory("JPAVererbungPU");createEntityManagerFactory("JPAVererbungPU");createEntityManagerFactory("JPAVererbungPU");createEntityManagerFactory("JPAVererbungPU");
EntityManager em=eMF.createEntityManager();EntityManager em=eMF.createEntityManager();EntityManager em=eMF.createEntityManager();EntityManager em=eMF.createEntityManager();
em.getTransaction().begin();em.getTransaction().begin();em.getTransaction().begin();em.getTransaction().begin();
em.persist(new Buch("JPA", 2, 39.99f));em.persist(new Buch("JPA", 2, 39.99f));em.persist(new Buch("JPA", 2, 39.99f));em.persist(new Buch("JPA", 2, 39.99f));
em.persist(new Produkt("Maus", 4, 7.99f));em.persist(new Produkt("Maus", 4, 7.99f));em.persist(new Produkt("Maus", 4, 7.99f));em.persist(new Produkt("Maus", 4, 7.99f));
em.persist(new Lebensmittel("Tofu", 7, 0.69f,new Date()));em.persist(new Lebensmittel("Tofu", 7, 0.69f,new Date()));em.persist(new Lebensmittel("Tofu", 7, 0.69f,new Date()));em.persist(new Lebensmittel("Tofu", 7, 0.69f,new Date()));
em.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();em.getTransaction().commit();
for(Produkt p:(List<Produkt>)em.for(Produkt p:(List<Produkt>)em.for(Produkt p:(List<Produkt>)em.for(Produkt p:(List<Produkt>)em.
createQuery("SELECT p FROM Produkt p").getResultList())createQuery("SELECT p FROM Produkt p").getResultList())createQuery("SELECT p FROM Produkt p").getResultList())createQuery("SELECT p FROM Produkt p").getResultList())
System.out.println(p);System.out.println(p);System.out.println(p);System.out.println(p);
}}}}1:JPA Menge:2 Preis:39.99 Buch1:JPA Menge:2 Preis:39.99 Buch1:JPA Menge:2 Preis:39.99 Buch1:JPA Menge:2 Preis:39.99 Buch2:Maus Menge:4 Preis:7.992:Maus Menge:4 Preis:7.992:Maus Menge:4 Preis:7.992:Maus Menge:4 Preis:7.993:Tofu Menge:7 Preis:0.69 Verfall:Thu Oct 15 16:22:14 CEST 20093:Tofu Menge:7 Preis:0.69 Verfall:Thu Oct 15 16:22:14 CEST 20093:Tofu Menge:7 Preis:0.69 Verfall:Thu Oct 15 16:22:14 CEST 20093:Tofu Menge:7 Preis:0.69 Verfall:Thu Oct 15 16:22:14 CEST 2009
Prof. Dr. Stephan Kleuker
226Komponentenbasierte Software-Entwicklung
Vererbung – eine Tabelle (3/3)
SELECT * FROM ProduktSELECT * FROM ProduktSELECT * FROM ProduktSELECT * FROM Produkt
• Abbildung in eine Tabelle ist Default-Einstellung
• Ansatz meist am performantesten
• (float ungeeignet für Geldbeträge)
Prof. Dr. Stephan Kleuker
227Komponentenbasierte Software-Entwicklung
Vererbung – getrennte verknüpfte Tabellen
@Entity@Entity@Entity@Entity
@@@@InheritanceInheritanceInheritanceInheritance((((strategystrategystrategystrategy====InheritanceType.JOINEDInheritanceType.JOINEDInheritanceType.JOINEDInheritanceType.JOINED))))
publicpublicpublicpublic classclassclassclass Produkt Produkt Produkt Produkt implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable { { { { ...}...}...}...}
SELECT * FROM ProduktSELECT * FROM ProduktSELECT * FROM ProduktSELECT * FROM Produkt
SELECT * FROM LebensmittelSELECT * FROM LebensmittelSELECT * FROM LebensmittelSELECT * FROM Lebensmittel
SELECT * FROM BuchSELECT * FROM BuchSELECT * FROM BuchSELECT * FROM Buch
Prof. Dr. Stephan Kleuker
228Komponentenbasierte Software-Entwicklung
Vererbung – getrennte Tabellen
@Entity@Entity@Entity@Entity
@@@@InheritanceInheritanceInheritanceInheritance((((strategystrategystrategystrategy====InheritanceType.TABLE_PER_CLASSInheritanceType.TABLE_PER_CLASSInheritanceType.TABLE_PER_CLASSInheritanceType.TABLE_PER_CLASS))))
publicpublicpublicpublic classclassclassclass Produkt Produkt Produkt Produkt implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable { { { { ...}...}...}...}
SELECT * FROM ProduktSELECT * FROM ProduktSELECT * FROM ProduktSELECT * FROM Produkt
SELECT * FROM LebensmittelSELECT * FROM LebensmittelSELECT * FROM LebensmittelSELECT * FROM Lebensmittel
SELECT * FROM BuchSELECT * FROM BuchSELECT * FROM BuchSELECT * FROM Buch
Prof. Dr. Stephan Kleuker
229Komponentenbasierte Software-Entwicklung
Software-Architektur
• sinnvoll: Datenzugriff kapseln
• typisch mehrere DAO-Klassen
• entsteht Datenzugriffs-komponente
Prof. Dr. Stephan Kleuker
230Komponentenbasierte Software-Entwicklung
Einbindung von Bean-Validation
• Annotationen wie @Column ermöglichen bereits Angabe bestimmter Randbedingungen
• klarerer Ansatz: Trennung von Beschreibung des Objektgraphen (wer mit wem) von Validierung
• Bean-Validation kann zusammen mit JPA genutzt werden; Anwesenheit von Validatoren wird von EntityManagern genutzt
• Ansatz: Wenn Daten in DB persistiert werden sollen, werden alle Validierungsregeln geprüft (nicht eher); bei Fehler wird Exception geworfen
• Zukunft: Standards werden noch enger verknüpft
• Beispiel: externe Programmierernamen beginnen mit „X“, müssen vorgegebene Sprachen können
Prof. Dr. Stephan Kleuker
231Komponentenbasierte Software-Entwicklung
Beispiel: JPA mit Bean-Validation (1/5)
@Entity @Entity @Entity @Entity @@@@MrXProgrammerMrXProgrammerMrXProgrammerMrXProgrammer(sprachen={"(sprachen={"(sprachen={"(sprachen={"Java","EJava","EJava","EJava","E"},"},"},"},messagemessagemessagemessage="aktuelle Sprachen")="aktuelle Sprachen")="aktuelle Sprachen")="aktuelle Sprachen")publicpublicpublicpublic classclassclassclass Mitarbeiter Mitarbeiter Mitarbeiter Mitarbeiter implementsimplementsimplementsimplements SerializableSerializableSerializableSerializable {{{{
@@@@IdIdIdId @@@@GeneratedValueGeneratedValueGeneratedValueGeneratedValue((((strategystrategystrategystrategy = = = = GenerationType.AUTOGenerationType.AUTOGenerationType.AUTOGenerationType.AUTO))))private private private private intintintint minrminrminrminr;;;;@@@@NotNullNotNullNotNullNotNull @Size(min=2, @Size(min=2, @Size(min=2, @Size(min=2, messagemessagemessagemessage="echter Nachname")="echter Nachname")="echter Nachname")="echter Nachname")private String private String private String private String namenamenamename;;;;@@@@OneToManyOneToManyOneToManyOneToMany((((mappedBymappedBymappedBymappedBy = "= "= "= "bearbeiterbearbeiterbearbeiterbearbeiter",",",",
cascadecascadecascadecascade = {= {= {= {CascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSIST, , , , CascadeType.MERGECascadeType.MERGECascadeType.MERGECascadeType.MERGE})})})})@Basic(@Basic(@Basic(@Basic(fetchfetchfetchfetch = = = = FetchType.EAGERFetchType.EAGERFetchType.EAGERFetchType.EAGER))))@Size(@Size(@Size(@Size(maxmaxmaxmax=3, =3, =3, =3, messagemessagemessagemessage="="="="maxmaxmaxmax 3 3 3 3 AuftraegeAuftraegeAuftraegeAuftraege")")")")private Set<Projektauftrag> private Set<Projektauftrag> private Set<Projektauftrag> private Set<Projektauftrag> auftraegeauftraegeauftraegeauftraege = = = = newnewnewnew HashSetHashSetHashSetHashSet<>();<>();<>();<>();@@@@ManyToManyManyToManyManyToManyManyToMany((((mappedBymappedBymappedBymappedBy = "= "= "= "mitarbeitermitarbeitermitarbeitermitarbeiter",",",",
cascadecascadecascadecascade = {= {= {= {CascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSISTCascadeType.PERSIST, , , , CascadeType.MERGECascadeType.MERGECascadeType.MERGECascadeType.MERGE})})})})@Basic(@Basic(@Basic(@Basic(fetchfetchfetchfetch = = = = FetchType.EAGERFetchType.EAGERFetchType.EAGERFetchType.EAGER))))@Size(@Size(@Size(@Size(maxmaxmaxmax=2, =2, =2, =2, messagemessagemessagemessage="="="="maxmaxmaxmax 2 Rollen")2 Rollen")2 Rollen")2 Rollen")private List<Rolle> rollen = private List<Rolle> rollen = private List<Rolle> rollen = private List<Rolle> rollen = newnewnewnew ArrayListArrayListArrayListArrayList<>();<>();<>();<>();// ...// ...// ...// ...
Prof. Dr. Stephan Kleuker
232Komponentenbasierte Software-Entwicklung
Beispiel: JPA mit Bean-Validation (2/5)
@Target({ElementType.TYPE})@Target({ElementType.TYPE})@Target({ElementType.TYPE})@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)@Retention(RetentionPolicy.RUNTIME)@Retention(RetentionPolicy.RUNTIME)@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MrXValidator.class)@Constraint(validatedBy = MrXValidator.class)@Constraint(validatedBy = MrXValidator.class)@Constraint(validatedBy = MrXValidator.class)
@Documented@Documented@Documented@Documented
public @interface MrXProgrammer {public @interface MrXProgrammer {public @interface MrXProgrammer {public @interface MrXProgrammer {
String message() default "Moduleintrag kaputt";String message() default "Moduleintrag kaputt";String message() default "Moduleintrag kaputt";String message() default "Moduleintrag kaputt";
Class<?>[] groups() default {};Class<?>[] groups() default {};Class<?>[] groups() default {};Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};Class<? extends Payload>[] payload() default {};Class<? extends Payload>[] payload() default {};Class<? extends Payload>[] payload() default {};
String[] sprachen() default {};String[] sprachen() default {};String[] sprachen() default {};String[] sprachen() default {};
}}}}
Prof. Dr. Stephan Kleuker
233Komponentenbasierte Software-Entwicklung
Beispiel: JPA mit Bean-Validation (3/5)
public class MrXValidator implementspublic class MrXValidator implementspublic class MrXValidator implementspublic class MrXValidator implementsConstraintValidator<MrXProgrammer, Mitarbeiter> {ConstraintValidator<MrXProgrammer, Mitarbeiter> {ConstraintValidator<MrXProgrammer, Mitarbeiter> {ConstraintValidator<MrXProgrammer, Mitarbeiter> {
private String[] muss;private String[] muss;private String[] muss;private String[] muss;
public void initialize(MrXProgrammer a) {public void initialize(MrXProgrammer a) {public void initialize(MrXProgrammer a) {public void initialize(MrXProgrammer a) {muss = a.sprachen();muss = a.sprachen();muss = a.sprachen();muss = a.sprachen();
}}}}
public boolean isValid(Mitarbeiter t, public boolean isValid(Mitarbeiter t, public boolean isValid(Mitarbeiter t, public boolean isValid(Mitarbeiter t, ConstraintValidatorContext cvc) {ConstraintValidatorContext cvc) {ConstraintValidatorContext cvc) {ConstraintValidatorContext cvc) {
System.out.println("Pruefe fuer "+t.getName());System.out.println("Pruefe fuer "+t.getName());System.out.println("Pruefe fuer "+t.getName());System.out.println("Pruefe fuer "+t.getName());if(!t.getName().startsWith("X"))if(!t.getName().startsWith("X"))if(!t.getName().startsWith("X"))if(!t.getName().startsWith("X"))return true;return true;return true;return true;
List<Rolle> rollen = t.getRollen();List<Rolle> rollen = t.getRollen();List<Rolle> rollen = t.getRollen();List<Rolle> rollen = t.getRollen();for (Rolle r : rollen)for (Rolle r : rollen)for (Rolle r : rollen)for (Rolle r : rollen)for (String s : muss)for (String s : muss)for (String s : muss)for (String s : muss)if (r.getName().equals(s))if (r.getName().equals(s))if (r.getName().equals(s))if (r.getName().equals(s))return true;return true;return true;return true;
return false;return false;return false;return false;}}}}
}}}}
Prof. Dr. Stephan Kleuker
234Komponentenbasierte Software-Entwicklung
Beispiel: JPA mit Bean-Validation (4/5)publicpublicpublicpublic void void void void beispieldatenbeispieldatenbeispieldatenbeispieldaten(){(){(){(){
Mitarbeiter m1 = Mitarbeiter m1 = Mitarbeiter m1 = Mitarbeiter m1 = newnewnewnew Mitarbeiter("Mitarbeiter("Mitarbeiter("Mitarbeiter("XUrsXUrsXUrsXUrs");");");");Rolle[] r= { Rolle[] r= { Rolle[] r= { Rolle[] r= { newnewnewnew Rolle("Java", 60),Rolle("Java", 60),Rolle("Java", 60),Rolle("Java", 60),newnewnewnew Rolle("C", 50)};Rolle("C", 50)};Rolle("C", 50)};Rolle("C", 50)};forforforfor((((intintintint i=0;i<i=0;i<i=0;i<i=0;i<r.length;ir.length;ir.length;ir.length;i++) m1.rolleHinzu(r[i]);++) m1.rolleHinzu(r[i]);++) m1.rolleHinzu(r[i]);++) m1.rolleHinzu(r[i]);System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println(m1);(m1);(m1);(m1);trytrytrytry {{{{em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();em.persistem.persistem.persistem.persist(m1);(m1);(m1);(m1);em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();
} catch (} catch (} catch (} catch (ConstraintViolationExceptionConstraintViolationExceptionConstraintViolationExceptionConstraintViolationException e) {e) {e) {e) {System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println((((e.getMessagee.getMessagee.getMessagee.getMessage());());());());forforforfor((((ConstraintViolationConstraintViolationConstraintViolationConstraintViolation c:e.getConstraintViolations())c:e.getConstraintViolations())c:e.getConstraintViolations())c:e.getConstraintViolations())
System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println((((c.getMessagec.getMessagec.getMessagec.getMessage());());());());ifififif ((((em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().isActiveisActiveisActiveisActive())())())())em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().rollbackrollbackrollbackrollback();();();();
}}}}}}}} 0: XUrs Auftraege=[ ]0: XUrs Auftraege=[ ]0: XUrs Auftraege=[ ]0: XUrs Auftraege=[ ]
Rollen=[ Java C ]Rollen=[ Java C ]Rollen=[ Java C ]Rollen=[ Java C ]Pruefe fuer XUrsPruefe fuer XUrsPruefe fuer XUrsPruefe fuer XUrs
Prof. Dr. Stephan Kleuker
235Komponentenbasierte Software-Entwicklung
Beispiel: JPA mit Bean-Validation (5/5)
publicpublicpublicpublic void void void void beispieldatenbeispieldatenbeispieldatenbeispieldaten(){(){(){(){Mitarbeiter m1 = Mitarbeiter m1 = Mitarbeiter m1 = Mitarbeiter m1 = newnewnewnew Mitarbeiter("X");Mitarbeiter("X");Mitarbeiter("X");Mitarbeiter("X");Rolle[] r= { Rolle[] r= { Rolle[] r= { Rolle[] r= { newnewnewnew Rolle("C++", 60),Rolle("C++", 60),Rolle("C++", 60),Rolle("C++", 60),newnewnewnew Rolle("C", 50),Rolle("C", 50),Rolle("C", 50),Rolle("C", 50),
newnewnewnew Rolle("Cobol", 70)};Rolle("Cobol", 70)};Rolle("Cobol", 70)};Rolle("Cobol", 70)};forforforfor((((intintintint i=0;i<i=0;i<i=0;i<i=0;i<r.length;ir.length;ir.length;ir.length;i++) m1.rolleHinzu(r[i]);++) m1.rolleHinzu(r[i]);++) m1.rolleHinzu(r[i]);++) m1.rolleHinzu(r[i]);System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println(m1);(m1);(m1);(m1);trytrytrytry {{{{em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().beginbeginbeginbegin();();();();em.persistem.persistem.persistem.persist(m1);(m1);(m1);(m1);em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().commitcommitcommitcommit();();();();
} catch (} catch (} catch (} catch (ConstraintViolationExceptionConstraintViolationExceptionConstraintViolationExceptionConstraintViolationException e) {e) {e) {e) {forforforfor((((ConstraintViolationConstraintViolationConstraintViolationConstraintViolation c:e.getConstraintViolations())c:e.getConstraintViolations())c:e.getConstraintViolations())c:e.getConstraintViolations())System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println((((c.getMessagec.getMessagec.getMessagec.getMessage());());());());
ifififif ((((em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().isActiveisActiveisActiveisActive())())())())em.getTransactionem.getTransactionem.getTransactionem.getTransaction().().().().rollbackrollbackrollbackrollback();();();();
}}}}}}}}
0: X Auftraege=[ ]0: X Auftraege=[ ]0: X Auftraege=[ ]0: X Auftraege=[ ]Rollen=[ C++ C Cobol ]Rollen=[ C++ C Cobol ]Rollen=[ C++ C Cobol ]Rollen=[ C++ C Cobol ]
Pruefe fuer XPruefe fuer XPruefe fuer XPruefe fuer Xechter Nachnameechter Nachnameechter Nachnameechter Nachnameaktuelle Sprachenaktuelle Sprachenaktuelle Sprachenaktuelle Sprachenmax 2 Rollenmax 2 Rollenmax 2 Rollenmax 2 Rollen
TODO: Exception tritt erst bei DB-Nutzungauf, sinnvoll früher
Prof. Dr. Stephan Kleuker
236
Technischer Hinweis
• Beispiele zeigen, dass die Version 4.2 und 4.3 der Bean Validation nicht mit EclipseLink 2.3.2 zusammenarbeiten
• Lösung: Bean Validation 5.0.0.Alpha1 (wie vorher)
Komponentenbasierte Software-Entwicklung
Prof. Dr. Stephan Kleuker
237Komponentenbasierte Software-Entwicklung
Interessante weitere Features in JPA
• in Anfrage-Sprache– Funktionen auf Datentypen z. B.
SUBSTRING(String,Start,Ende)– UPDATE und DELETE in Querys
• immer vor/nach Persistierung ausgeführte Methoden• Compound Primary Keys , zusammengesetzte Schlüssel über
Hilfsklassen nutzbar• Verschiedene Sperrvarianten
@Lob @Column(name="PIC")@Lob @Column(name="PIC")@Lob @Column(name="PIC")@Lob @Column(name="PIC")private byte[] picture;private byte[] picture;private byte[] picture;private byte[] picture;
@ManyToMany@ManyToMany@ManyToMany@ManyToMany@JoinTable(name="PROJEKTROLLEN",@JoinTable(name="PROJEKTROLLEN",@JoinTable(name="PROJEKTROLLEN",@JoinTable(name="PROJEKTROLLEN",joinColumns=@JoinColumn(name=„ROLLEN_ID"),joinColumns=@JoinColumn(name=„ROLLEN_ID"),joinColumns=@JoinColumn(name=„ROLLEN_ID"),joinColumns=@JoinColumn(name=„ROLLEN_ID"),inverseJoinColumns=@JoinColumn(name="PROJ_ID"))inverseJoinColumns=@JoinColumn(name="PROJ_ID"))inverseJoinColumns=@JoinColumn(name="PROJ_ID"))inverseJoinColumns=@JoinColumn(name="PROJ_ID"))
Prof. Dr. Stephan Kleuker
238
• Datenbank als zentrale Kommunikationsplattform
• Ansatz 1: alle Komponenten kennen Entitäten-Modell
• Ansatz 2: Datenzugriffsschicht kapselt Datenbank
Komponentenbasierte Software-Entwicklung
Erinnerung: Eine Komponentenarchitektur-Variante
Prof. Dr. Stephan Kleuker
239
Ansatz 1: Alle kennen Entitäten-Modell (1/2)
• Datenbank als zentrale Kommunikationsplattform
• Entitäten sind bekannt, jede Komponente kann zugreifen
• Benötigt Komponente weitere Eigenschaft einer Entität wird keine Spalte sondern Tabelle ergänzt (auch 1:1, 1:C, nutzt Primärschlüssel)
• Sehr einfache Architektur
• Sehr gut Komponenten an- und ausschaltbar
• Keine Benachrichtigung bei Änderungen (sichtbar beim nächsten Lesen)
• Stark eingeschränkte Wiederverwendbarkeit
• Keine echte Informationskapselung
• Wartbarkeit nimmt mit Systemgröße enorm ab
Komponentenbasierte Software-Entwicklung
Prof. Dr. Stephan Kleuker
240
Ansatz 1: Alle kennen Entitäten-Modell (2/2)
• Beispiel: Komponenten Produktverwaltung, Bestellsystem (sieht neue Produkte und Änderungen bei nächsten Aufruf)
Komponentenbasierte Software-Entwicklung
Prof. Dr. Stephan Kleuker
241
Ansatz 2: Kapselung mit Datenzugriffsschicht (1/2)
• Kein direkter Zugriff auf Tabellen
• Ermöglicht auch Benachrichtigungen (Observer)
• Zerlegung in wiederverwendbare Komponenten
• Unterschiedliche Varianten von Kommunikationen möglich
– Nutzung einer zentralen Zugriffskomponente, die DB kapselt und Observer verwaltet
– Nur Data Access Objects können miteinander reden
– Komponentenschnittstellen unabhängig von der DB
– Selbst gemeinsame Datenbank ist optional
Komponentenbasierte Software-Entwicklung
Prof. Dr. Stephan Kleuker
242
Ansatz 2: Kapselung mit Datenzugriffsschicht (2/2)
Komponentenbasierte Software-Entwicklung
Prof. Dr. Stephan Kleuker
243
Überwachungsmethoden (1/3)
@@@@EntityEntityEntityEntity
publicpublicpublicpublic classclassclassclass Mitarbeiter Mitarbeiter Mitarbeiter Mitarbeiter {{{{
@@@@IdIdIdId @@@@GeneratedValueGeneratedValueGeneratedValueGeneratedValue((((strategystrategystrategystrategy====GenerationType.AUTOGenerationType.AUTOGenerationType.AUTOGenerationType.AUTO))))
private private private private intintintint minrminrminrminr;;;;
private private private private String String String String namenamenamename;;;;
private void p(String s){private void p(String s){private void p(String s){private void p(String s){System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println(s);}(s);}(s);}(s);}
@@@@PrePersistPrePersistPrePersistPrePersist publicpublicpublicpublic voidvoidvoidvoid prePersitprePersitprePersitprePersit() () () () {p("{p("{p("{p("prePersistprePersistprePersistprePersist");}");}");}");}
@@@@PostPersistPostPersistPostPersistPostPersist publicpublicpublicpublic voidvoidvoidvoid postPersistpostPersistpostPersistpostPersist() () () () {p("{p("{p("{p("postPersistpostPersistpostPersistpostPersist");}");}");}");}
@@@@PreRemovePreRemovePreRemovePreRemove publicpublicpublicpublic voidvoidvoidvoid preRemovepreRemovepreRemovepreRemove() () () () {p("{p("{p("{p("preRemovepreRemovepreRemovepreRemove");}");}");}");}
@@@@PostRemovePostRemovePostRemovePostRemove publicpublicpublicpublic voidvoidvoidvoid postRemovepostRemovepostRemovepostRemove() () () () {p("{p("{p("{p("postRemovepostRemovepostRemovepostRemove");}");}");}");}
@@@@PreUpdatePreUpdatePreUpdatePreUpdate publicpublicpublicpublic voidvoidvoidvoid preUpdatepreUpdatepreUpdatepreUpdate() () () () {p("{p("{p("{p("preUpdatepreUpdatepreUpdatepreUpdate");}");}");}");}
@@@@PostUpdatePostUpdatePostUpdatePostUpdate publicpublicpublicpublic voidvoidvoidvoid postUpdatepostUpdatepostUpdatepostUpdate() () () () {p("{p("{p("{p("postUpdatepostUpdatepostUpdatepostUpdate");}");}");}");}
@@@@PostLoadPostLoadPostLoadPostLoad publicpublicpublicpublic voidvoidvoidvoid postLoadpostLoadpostLoadpostLoad() () () () {p("{p("{p("{p("postLoadpostLoadpostLoadpostLoad");}");}");}");}
// Hinweis: Rollback bei einer // Hinweis: Rollback bei einer // Hinweis: Rollback bei einer // Hinweis: Rollback bei einer RuntimeRuntimeRuntimeRuntime ExceptionExceptionExceptionException
............Komponentenbasierte Software-
Entwicklung
Prof. Dr. Stephan Kleuker
244
Überwachungsmethoden (2/3)
publicpublicpublicpublic staticstaticstaticstatic voidvoidvoidvoid mainmainmainmain(String[] (String[] (String[] (String[] argsargsargsargs) {) {) {) {EntityManagerFactoryEntityManagerFactoryEntityManagerFactoryEntityManagerFactory emfemfemfemf = = = = PersistencePersistencePersistencePersistence
....createEntityManagerFactorycreateEntityManagerFactorycreateEntityManagerFactorycreateEntityManagerFactory("("("("PrePostPUPrePostPUPrePostPUPrePostPU");");");");EntityManagerEntityManagerEntityManagerEntityManager emememem = = = = emf.createEntityManageremf.createEntityManageremf.createEntityManageremf.createEntityManager();();();();Mitarbeiter Mitarbeiter Mitarbeiter Mitarbeiter m = m = m = m = newnewnewnew Mitarbeiter("Olga");Mitarbeiter("Olga");Mitarbeiter("Olga");Mitarbeiter("Olga");Mitarbeiter Mitarbeiter Mitarbeiter Mitarbeiter m2 = m2 = m2 = m2 = newnewnewnew Mitarbeiter("Otto");Mitarbeiter("Otto");Mitarbeiter("Otto");Mitarbeiter("Otto");EntityTransactionEntityTransactionEntityTransactionEntityTransaction tatatata = = = = em.getTransactionem.getTransactionem.getTransactionem.getTransaction();();();();ta.beginta.beginta.beginta.begin();();();();em.persistem.persistem.persistem.persist(m(m(m(m););););em.persistem.persistem.persistem.persist(m2(m2(m2(m2););););em.persistem.persistem.persistem.persist((((newnewnewnew Mitarbeiter("Urs"));Mitarbeiter("Urs"));Mitarbeiter("Urs"));Mitarbeiter("Urs"));ta.committa.committa.committa.commit();();();();ta.beginta.beginta.beginta.begin();();();();Mitarbeiter Mitarbeiter Mitarbeiter Mitarbeiter mm = mm = mm = mm = em.findem.findem.findem.find((((Mitarbeiter.classMitarbeiter.classMitarbeiter.classMitarbeiter.class, , , , m.getMinrm.getMinrm.getMinrm.getMinr());());());());mm.setNamemm.setNamemm.setNamemm.setName("Anna");("Anna");("Anna");("Anna");em.persistem.persistem.persistem.persist(mm(mm(mm(mm););););ta.committa.committa.committa.commit();();();();
Komponentenbasierte Software-Entwicklung
prePersistprePersistprePersistprePersistprePersistprePersistprePersistprePersistprePersistprePersistprePersistprePersistpostPersistpostPersistpostPersistpostPersistpostPersistpostPersistpostPersistpostPersistpostPersistpostPersistpostPersistpostPersistpreUpdatepreUpdatepreUpdatepreUpdatepostUpdatepostUpdatepostUpdatepostUpdate
Prof. Dr. Stephan Kleuker
245
Überwachungsmethoden (3/3)
ta.beginta.beginta.beginta.begin();();();();
em.removeem.removeem.removeem.remove(m(m(m(m););););
ta.committa.committa.committa.commit();();();();
em.closeem.closeem.closeem.close(); // notwendig für neuen Kontext(); // notwendig für neuen Kontext(); // notwendig für neuen Kontext(); // notwendig für neuen Kontext
emememem = = = = emf.createEntityManageremf.createEntityManageremf.createEntityManageremf.createEntityManager();();();();
forforforfor (Mitarbeiter m3 : (Mitarbeiter m3 : (Mitarbeiter m3 : (Mitarbeiter m3 : em.createQueryem.createQueryem.createQueryem.createQuery((((
""""SELECT m FROM Mitarbeiter SELECT m FROM Mitarbeiter SELECT m FROM Mitarbeiter SELECT m FROM Mitarbeiter m"m"m"m"
, , , , Mitarbeiter.classMitarbeiter.classMitarbeiter.classMitarbeiter.class))))
....getResultListgetResultListgetResultListgetResultList()) ()) ()) ())
System.out.printlnSystem.out.printlnSystem.out.printlnSystem.out.println(m3.getMinr(m3.getMinr(m3.getMinr(m3.getMinr() () () ()
+ + + + ": " + m3.getName": " + m3.getName": " + m3.getName": " + m3.getName());());());());
em.closeem.closeem.closeem.close();();();();
emf.closeemf.closeemf.closeemf.close();();();();
}}}}
Komponentenbasierte Software-Entwicklung
preRemovepreRemovepreRemovepreRemovepostRemovepostRemovepostRemovepostRemovepostLoadpostLoadpostLoadpostLoadpostLoadpostLoadpostLoadpostLoad2: Otto2: Otto2: Otto2: Otto3: 3: 3: 3: UrsUrsUrsUrs