objektrelationales mapping mit jpa 2.0
DESCRIPTION
Objektrelationales Mapping mit JPA 2.0. Jonas Bandi Simon Martinelli. Simon Martinelli. email: [email protected] blog : http://simonmartinelli.blogspot.com/ Geschäftsführer der simas GmbH Nebenamtdozent an der Berner Fachhochschule (SWS und Medical Technology Center) - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/1.jpg)
Objektrelationales Mapping mit JPA 2.0
Jonas BandiSimon Martinelli
![Page 2: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/2.jpg)
Simon Martinelli
email: [email protected] blog: http://simonmartinelli.blogspot.com/ Geschäftsführer der simas GmbH Nebenamtdozent an der Berner Fachhochschule
(SWS und Medical Technology Center) Software Architekt, Entwickler, Berater und
Trainer im Java EE Umfeld mit mehr als 15 Jahren Erfahrung in der Software Entwicklung
![Page 3: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/3.jpg)
Jonas Bandi
email: [email protected] blog: http://blog.jonasbandi.net Studium der Elektrotechnik und
Informationstechnologie an der ETH Zürich Angestellt bei TechTalk Software AG in Zürich Seit 10 Jahren in verschiedenen Bereichen der
Softwareentwicklung tätig Mein besonderes Interesse gilt dem Einsatz von
modernen Technologien und Methodiken in der Entwicklung von Enterprise Applikationen.
![Page 4: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/4.jpg)
Kursziele
Einführung in Objekt-Relationales Mapping Einführung in JPA Fortgeschrittene Themen beim Einsatz von JPA Unterschiede JPA / JPA2 Wir versuchen möglichst neutral bezüglich des
verwendeten JPA Providers zu sein Übungen: EclipseLink, Maven Kursunterlagen:
http://code.google.com/p/jpaworkshop/
![Page 5: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/5.jpg)
Über euch
Wer setzt Objekt-Relationales Mapping ein?
Wer arbeitet mit JPA? Wer setzt Hibernate ein? Was setzten die andern ein? Ist JPA 2 ein Thema? Erwartungen an diesen Workshop? Wer hat die Übungen angeschaut?
![Page 6: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/6.jpg)
Einführung ORM & JPA
Objektrelationales Mapping mit JPA 2.0
![Page 7: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/7.jpg)
Silver Bullet oder unnötiger Overhead?
Objektrelationales Mapping ist ein umstrittenes Thema, das immer wieder Anlass für hitzige Diskussionen bietet.
Hier zwei Beispiele...
![Page 8: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/8.jpg)
Flame Wars
“The Best ORM is No ORM” “The database is an object.” “ORM is, for the most part,
solving the wrong problem. In fact the problem does not really exist.”
Hibernate should be to programmers what cake mixes are to bakers: beneath their dignity. [...] As professional programmers, we should be more sceptical of generic frameworks like hibernate.
![Page 9: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/9.jpg)
The Vietnam of Computer Science
Ted Neward: “Object/Relational Mapping is the Vietnam of Computer Science” (Juni 2006).Original Blog Post: http://tinyurl.com/heapfPDF: http://www.odbms.org/about_news_20070212.html
“Law of Diminishing Returns” Schnelle anfängliche Erfolge führen zu
grossen Erwartungen Mit dem Fortschreiten des Unterfangens
werden die Erfolge aber immer spärlicher und die dafür notwendigen Investitionen immer grösser
Schlussendlich werden die Investitionen nicht mehr durch den Gewinn gerechtfertigt. Aber es gibt keinen Weg zurück...
![Page 10: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/10.jpg)
Anwendung von bewährten OO-Techniken für die Implementation der Geschäftslogik:Kapselung, Vererbung, Polymorphie, Design Patterns ...
OO verspricht:• bessere Skalierung bei zunehmender Komplexität
• bessere Erweiterbarkeit• bessere Wartbarkeit• weniger Redundanz
Ausgangslage Domain Model
![Page 11: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/11.jpg)
Ausgangslage: Relationale Datenbanken
Vorherrschende Technologie zum Speichern von Daten im Enterprise-Umfeld.
Gründe: Grosse Investitionen Bewährte, ausgereifte Technologie Flexibilität, Applikationsunabhängigkeit Daten leben länger als Applikationen Optimierte Konzepte zum Speichern
von Daten
![Page 12: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/12.jpg)
Ausgangslage: Der Konflikt
De facto Standard-Konstellation für Enterprise-Applikationen:
OO-Technologie für die Applikations-entwicklung
Relationale Datenbanken für die Persistenz der Daten
An dieser Ausgangslage wird sich mittelfristig kaum etwas ändern.
Der OO-Ansatz und der relationale Ansatz weisen grundsätzliche Unterschiede auf
Aus diesen Unterschieden resultiert der sog. Object-Relational-Mismatch
![Page 13: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/13.jpg)
Der O/R-Mismatch
Technische Ausprägungen des O/R-Mismatch: Typen-Systeme
Null Datum/Zeit
Abbildung von Beziehungen Richtung Mehrfachbeziehungen
Vererbung Identität
Objekte haben eine implizite Identität Relationen haben eine explizite Identität (Primary Key)
Transaktionen
![Page 14: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/14.jpg)
DB OO
Designziele • Speichern und Abfragen von Daten
• Speicherung unabhängig von konkreten Business-Problemen
• Vereinigung von Zustand und Verhalten
• Kapselung, Modularisierung, Abstraktion
• Modellierung konkreter Business-Probleme
Architektur-ansätze
• Client/Server: verteiltes System
• Objekte sind lokal und nicht verteilt
Abfrage/Zugriff
• Deklarative Abfragesprache
• Beziehungen zwischen Daten müssen nicht explizit definiert sein
• Imperative Navigation entlang von Referenzen
• Beziehungen zwischen Objekten müssen explizit definiert sein
Der O/R-Mismatch
![Page 15: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/15.jpg)
Der O/R-Mismatch
In heutigen Enterprise Umfeldern ist der O/R-Mismatch ein Fakt.
Der O/R-Mismatch folgt aus konzeptionellen Unterschieden der zugrundeliegenden Technologien.
Es gibt viele verschiedene Möglichkeiten den O/R-Mismatch zu überwinden.
O/R-Mapping resp. O/R-Mapping Frameworks sind ein möglicher Lösungsansatz.
![Page 16: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/16.jpg)
History
Konzepte zum Überbrücken des O/R-Mismatch existieren seit es OO gibt. Unterschiedliche Ansätze wie der O/R-Mismatch
überwunden werden soll Bekannteste Java Frameworks
Hibernate TopLink, TopLink Essentials, EclipseLink KODO, OpenJPA JPOX , DataNucleus
Java Standardisierung: EJB2, JDO, JPA
![Page 17: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/17.jpg)
Versprechen von O/R-Mapping
Die Applikation wird von der DB entkoppelt Applikationsentwickler muss kein SQL beherrschen Das relationale Modell der Datenbank hat keinen Einfluss auf
das OO-Design
Automatische Persistenz Automatisierte Abbildung der Objekte in die relationalen
Strukturen Der Applikationsentwickler muss sich nicht um die “low-level”-
Details des CLI (z.B. connections) kümmern.
Transparente Persistenz / Persistence Ignorance Die Klassen des Domain-Models wissen nicht dass sie
persistiert und geladen werden können und haben keine Abhängigkeit zur Persistenz-Infrastruktur.
![Page 18: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/18.jpg)
Versprechen von O/R-Mapping
Abstraktion Abstraktion ist eines der wichtigsten
Werkzeuge um Komplexität zu bewältigen Separation of Concerns
Bei der Applikationsentwicklung kann man sich ausschliesslich auf die Geschäftsprobleme konzentrieren
Infrastruktur-Probleme können separat gelöst werden und beeinflussen das Design und die Implementation der Geschäftslogik nicht.
![Page 19: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/19.jpg)
Versprechen von O/R-Mapping Frameworks
Umsetzung der Versprechen von O/R-Mapping
Einsatz von bewährten Patterns und Konzepten
Einsparungen von viel Code Manuell codierter DataAccess-Layer kann einen
grossen Code-Anteil ausmachen Referenzbeispiele zeigen Einsparungen um
Faktor 7 Strukturierung / Layerung des Codes
vorgegeben
![Page 20: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/20.jpg)
Pitfalls von O/R-Mapping Frameworks
O/R-Mapping-Frameworks sind komplex und bieten viel Funktionalität. Hibernate Core: 765k LOC, 206 Personen-Jahre, $11 Mio
(Source: Ohloh.net)
O/R-Mapping-Frameworks sind keine Rapid-Application-Development-Tools
Der Einsatz eines O/R-Mapping-Frameworks hat Einfluss auf die Architektur und den Design der gesamten Applikation
Die zugrundeliegenden Konzepte sollten verstanden sein.
Gründliche Auseinandersetzung ist Voraussetzung für den erfolgreichen Einsatz eines O/R-Mapping-Frameworks
![Page 21: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/21.jpg)
Konzeptionelle Probleme beim O/R-Mapping
Folgende konzeptionelle Probleme sollten beim O/R-Mapping beachtet werden:
Location Transparency Optimiertes SQL Mengen-Manipulationen Relationale Suche / Reports /
OLAP
![Page 22: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/22.jpg)
Location Transparencey
Alle Daten immer verfügbar Für die Applikation sollte es keinen
Unterschied machen, ob die sich Daten im lokalen Speicher oder auf der entfernten Datenbank befinden.
Wieviele Daten werden geladen? Zuviele: Speicher, Bandbreite -> Ladezeit! Zuwenige: Konstantes Nachladen -> Ladezeit! Stichworte: Lazy-Loading / Eager-Loading
![Page 23: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/23.jpg)
Dynamisch Generiertes SQL
SQL ist nicht so performant wie handgeschriebens, getuntes SQL Assembler anybody? Dynamisch generiertes SQL muss auch nicht
gewartet werden! Ausgereifte Frameworks generieren gut
optimiertes SQL (torpedo-group.org) Performance
Stored Procedures sind nicht performanter als dynamisches SQL!
![Page 24: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/24.jpg)
Nutzung von relationalen Konzepten, die keine Entsprechung in der OO-Welt haben Unproblematische
Abfragen:
– Alle Personen, welche einen schwarzen Mantel bestellen.
– Alle Personen, welche einen schwarzen Mantel bestellen mit all ihren Bestellungen und allen Bestell-Posten
Relationale Suche / Reports
![Page 25: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/25.jpg)
Problematische Abfrage: Alle Tupel bestehend aus Vorname, Nachname
und Produktname
FirstName LastName ProductName
Thomas Anderson Beretta 92FS 9mm
Thomas Anderson Black Coat
Thomas Anderson Cool Sunglasses
Tyler Durden Perfumed Soap
Relationale Suche / Reports
![Page 26: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/26.jpg)
Relationale Suche / Reports
Probleme: Karthesisches Produkt
In der DB sehr effizient umgesetzt In der OO-Welt keine Entsprechung
Die Struktur des Resultats der Anfrage existiert nicht in der OO-Welt Es gibt keinen Typ mit den Attributen (Vorname, Nachname,
Produktname) Die relationale Welt erlaubt flexible (untypisierte) Sichten auf die Daten
(Deklarative ad-hoc formulierte Anfragen) Resultat einer Anfrage kann völlig entkoppelt sein von der Struktur wie
die Daten gespeichert werden. Die OO-Welt verlangt definierte, stark typisierte Strukturen
Das ‚Flachdrücken‘ / ‚Denormalisieren‘ muss in der OO-Welt manuell ausgeführt werden
Alle beteiligten Objekte müssen geladen werden (Performance!)
![Page 27: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/27.jpg)
JPA – Java Persistence API JPA ist eine Bestrebung OR-Mapping mit Java zu
standardisieren JPA ist ein Teil der EJB 3 Spezifikation welche vom JCP
erarbeitet wurde JSR 220, final release: 2.5.2006 TopLink Essentials ist die Referenzimplementation
Es gibt verschiedene JPA Implementationen, diese werden auch JPA Providers genannt
JPA 2 ist eine eigenständge Spezifikation, welche auf JPA aufbaut und etliche zusätzliche Features bietet JSR 317, final release: 10.12.2009 EclipseLink ist die Referenzimplementation Die bekannten JPA Providers unterstützen alle JPA2
![Page 28: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/28.jpg)
Session Beans / Java Applikation
Java Persistence API
Java Persistence API Implementation
JDBC - Driver
JDBC API
JPA Spezifikation
JDBC 4.0
RDB
SQL SQL 2003 oder Dialekte
Java 5+
Herstellerspezifisch
EclipseLink (TopLink), Hibernate, OpenJPA etc.
Technologiestack
![Page 29: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/29.jpg)
Packagesjavax.persistencejavax.persistence.spi
ClassesPersistence
InterfacesEntityManagerFactoryEntityManagerEntityTransactionQuery
Runtime Exceptions ( ~8 )RollbackException
Annotations ( ~64 )EntityIdOneToOneOneToMany
Enumerations ( ~10 )InheritanceTypeCascadeTypeFetchType
Java API
![Page 30: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/30.jpg)
JPA Providers
Die bekanntesten JPA Providers sind: Hibernate Toplink / TopLink Essentials / EclipseLink KODO / OpenJPA JPOX / DataNucleus
Weniger bekannt sind: Apache Cayenne Resin Amber CocoBase
![Page 31: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/31.jpg)
Getting Started
Objektrelationales Mapping mit JPA 2.0
![Page 32: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/32.jpg)
Entity Überblick
Eine Entity ist persistierbar. Der Zustand kann in einer Datenbank abgespeichert und später wieder darauf zugegriffen werden
Wie jedes andere Java Objekt hat eine Entity eine Objektidentität. Zusätzlich besitzt sie eine Datenbankidentität (Primary Key)
In Zusammenhang mit der Datenbank werden die Entities transaktional verwendet. Die Erstellung, Änderung und das Löschen wird in einer Transaktion durchgeführt
32
![Page 33: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/33.jpg)
Entity Metadata
Kennzeichnung mit Annotation @Entity oder Mapping mit XML Klasse kann Basisklasse oder abgeleitet sein Klasse kann abstrakt oder konkret sein Serialisierbarkeit ist bezüglich Persistenz nicht erforderlich Anforderungen:
Standardkonstrukutor muss vorhanden sein. Klasse darf nicht final, kein Interface und keine Enumeration sein und keine
final-Methoden enthalten Felder müssen private oder protected sein. Zugriff von Clients auf Felder nur über get/set- oder Business-Methoden erlaubt. Jede Entity muss einen Primärschlüssel (@Id) haben
Configuration by Exception / Conventions over Configuration
33
![Page 34: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/34.jpg)
Entity, Beispiel
@Entitypublic class Employee {
@Id protected int id; protected String name; protected long salary;
public Employee(int id) { } ...}
34
![Page 35: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/35.jpg)
Entity Manager, Überblick
Persistence
«interface»EntityManagerFactory
«interface»EntityManager
Persistence Unit
Persistence Context
1
-Erstellt*
1
-Erstellt*
-Konfiguriert durch
1 1
-Manages
1 *
35
![Page 36: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/36.jpg)
Entity Manager, Beispiel
Entity Manager erstellen
Entity persistieren
Entitiy suchen
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa.emp.2008");EntityManager em = emf.createEntityManager();
Employee emp = new Employee(158);em.persist(emp);
Employee emp = em.find(Employee.class, 158);
36
![Page 37: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/37.jpg)
Entity Manager, Beispiel
Entity verändern
Entity löschen
Queries
em.getTransaction().begin();emp.setSalary(emp.getSalary() + 1000);em.getTransaction().commit();
em.getTransaction().begin();em.remove(emp);em.getTransaction().commit();
Query q = em.createQuery("SELECT e FROM Employee e");Collection emps = q.getResultList();
37
![Page 38: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/38.jpg)
Persitence Unit
Eine Persistence Unit ist eine logische Einheit von Entities. Sie wird beschrieben durch: Einen Namen Die zu dieser Unit gehörenden Entity-Klassen Angaben zum Persistence Provider Angabe zum Transaktionstyp Angaben zur Datenquelle Weitere Properties Namen von XML O/R-Mapping Files
Technisch wird die Beschreibung einer Persistence Unit in der Datei META-INF/persistence.xml abgelegt.
Persitence Archive = JAR
38
![Page 39: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/39.jpg)
Persistence Unit, Beispiel
META-INF/persistence.xml
39
<persistence> <persistence-unit name="emp" transaction-type="RESOURCE_LOCAL"> <provider>oracle.toplink.essentials.PersistenceProvider</provider> <class>examples.model.Employee</class> <properties> <property name="toplink.jdbc.driver" value="oracle.jdbc.driver.OracleDriver" /> <property name="toplink.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:xe" /> <property name="toplink.jdbc.user" value="emp3" /> <property name="toplink.jdbc.password" value="emp3" /> </properties> </persistence-unit></persistence>
![Page 40: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/40.jpg)
Entity Mapping
Objektrelationales Mapping mit JPA 2.0
![Page 41: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/41.jpg)
Access Typ
Für das Persistenz-Framework existieren zwei Zugriffspunkte auf die Daten einer Klasse
41
// Field Access@Entity public class Employee { @Id private int id;}
//Property Access@Entity public class Employee { protected int id; @Id public int getId() { return id; }}
![Page 42: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/42.jpg)
Access Typ Options (JPA 2.0)
Verschiedene Access Types pro Klasse möglich Mischen von Acces Types in einer
Vererbungshierarchie
42
@Entity @Access(FIELD)public class Vehicle {... @Transient double fuelEfficiency; @Access(PROPERTY) protected double getDbFuelEfficiency() {
return convertToImperial(fuelEfficiency); }...}
![Page 43: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/43.jpg)
Mapping
Es wird immer vom Defaultverhalten ausgegangen
Das Defaultverhalten kann übersteuert werden
43
@Entity@Table(name = "EMP")public class Employee { @Id @Column(name = "EMP_ID") ...}
![Page 44: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/44.jpg)
Persistente Datentypen
Erlaubt: Alle primitiven Typen, String Alle Wrapperklassen und serialisierbaren Typen
(z.B. Integer, BigDecimal, Date, Calendar) byte[], Byte[], char[], Character[] Enumerations Beliebige weitere Entity-Klassen Collections von Entities, welche als Collection<>, List<>, Set<> oder
Map<> deklariert sind.
Nicht erlaubt: Alle Arten von Arrays ausser die obgenannten Collections von etwas anderem als Entities, also z.B. Wrapperklassen
und andere serialiserbare Typen.
44
![Page 45: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/45.jpg)
Java / SQL Type Mapping
Implizit durch JDBC “Data Type Conversion Table“ definiert
Explizit durch die @Column Annotation, z.B.
Produktspezifisch durch JPA-Implementation oder im JDBC-Driver für die jeweilige Datenbank
45
@Column(name = "sender")protected String sender;
![Page 46: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/46.jpg)
Lazy Fetching und Large Objects
Lazy Field Loading
Large Objects
46
@Basic(fetch = FetchType.LAZY)private String comments;
@Basic(fetch = FetchType.LAZY)@Lobprivate byte[] picture;
![Page 47: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/47.jpg)
Enumerations
Enumerations können persistent sein. In der Datenbank wird entweder der Ordinalwert (Position) oder der Stringwert (Name der Konstante) abgelegt.
Vorsicht bei Änderungen an der Enumeration
47
// Variante Ordinal@Enumerated(EnumType.ORDINAL) protected MessageStatus status;
// Variante String@Enumerated(EnumType.STRING)protected MessageStatus status;
![Page 48: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/48.jpg)
Temporale Typen
Erlaubte Zeittypen: java.sql.Date, java.sql.Time, java.sql.Timestamp java.util.Date, java.util.Calendar
java.sql Typen brauchen keine weitere Definition
Bei java.util Typen muss der JDBC Typ angegeben werden:
Mögliche Typen: TemporalType.DATE, TemporalType.TIME, TemporalType.TIMESTAMP
48
@Temporal(TemporalType.DATE)private Calendar dob;
![Page 49: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/49.jpg)
Transiente Attribute
Attribute können von der Persistierung ausgeschlossen werden
Entweder mittels transient:
oder wenn das Attribut serialisiert werden soll mittels Annotation:
49
transient private String translatedName;
@Transientprivate String translatedName;
![Page 50: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/50.jpg)
Entity Identity - Primärschlüssel
Jede Entity-Klasse muss einen mit @Id bezeichneten Primärschlüssel besitzen.
Eine Id kann von folgenden Typen sein: Primitive Java Typen: byte, int, short, long, char Wrapper Klassen: Byte, Integer, Short, Long, Character Array von primitiven Typen oder Wrapper Klassen java.lang.String java.math.BigInteger Zeittypen: java.util.Date, java.sql.Date
Floating Point Typen sind ebenfalls erlaubt, aber sind aufgrund der möglichen Rundungsfehler nicht zu empfehlen
50
![Page 51: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/51.jpg)
Primärschlüssel Generierung
Primärschlüssel können in Zusammenarbeit mit der Datenbank generiert werden. Beispiel:
Strategien sind Identity, Table, Sequence und Auto
51
@Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer id;}
![Page 52: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/52.jpg)
GenerationType.TABLE
52
public class Employee {
@TableGenerator(name = "Emp_Gen", table = "ID_GEN", pkColumnName = "GEN_NAME", valueColumnName = "GEN_VAL") @Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "Emp_Gen") private int id; ...}
ID_GEN
PK GEN_NAME
GEN_VAL
![Page 53: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/53.jpg)
Beziehungen
Objektrelationales Mapping mit JPA 2.0
![Page 54: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/54.jpg)
Eine Parent-Child Beziehung
Wie sieht das Klassen-Modell aus? Employee hat eine Referenz auf Department Department hat eine Collection von Employee
Referenzen Beides: Bidirektionale Beziehung
Unabhängig davon ist das zugrundeliegende DB-Schema:
![Page 55: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/55.jpg)
Eine Parent-Child Beziehung
Mapping des Klassenmodells auf das DB-Schema mittels JPA: Metadata ist erforderlich. Je nach Klassenmodell wird entweder eine many-
to-one Beziehung oder eine one-to-many Beziehung gemappt
Falls beide Richtungen gemappt werden sollen, so muss definiert werden, dass für beide derselbe Foreign-Key zugrunde liegt.
![Page 56: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/56.jpg)
Eine Parent-Child Beziehung@Entitypublic class Employee { … @ManyToOne private Department department; …
@Entitypublic class Department { … @OneToMany @JoinColumn (name=”department_id”) private Set<Employee> employees =
new HashSet<Employee>(); …
@Entitypublic class Department { … @OneToMany (mappedBy = “department“) private Set<Employee> employees =
new HashSet<Employee>(); …
Mapping der one-to-many Beziehung• Field/Property muss ein Interface
sein• Achtung:– Unidirektionales one-to-many ohne
Beziehungstabelle wird erst ab JPA2 unterstützt
Mapping der many-to-one Beziehung
Mapping der bidirektionalen Beziehung
• JPA muss wissen, dass nur ein Foreign-Key für beide Richtungen existiert.
![Page 57: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/57.jpg)
Collection Types• Richtung
– Unidirektional
– Bidirektional
• Kardinalität
– One-to-one
– Many-to-one
– One-to-many
– many-to-many
Employee Project
Employee Address
Source Target
Employee Department
* 1
Employee Project* *
Employee Address1 1
Employee Phone1 *
![Page 58: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/58.jpg)
one-to-one, unidirektional
Employee
@OneToOneprivate Address address;
entspricht:
@OneToOne@JoinColumn(name="address_id", referencedColumnName = "id")private Address address;
(JPA2 unterstützt auch one-to-one mit einer zusätzlichen Zwischentabelle)
-id : int-name : String-salary : long
Employee
-id : int-street : String-city : String-state : String-zip : String
Address
0..1
ADDRESS
ID
CITY (O) STATE (O) STREET (O) ZIP (O)
EMPLOYEE
ID
NAME (O) SALARY (O) STARTDATE (O) DEPARTMENT_ID (O) (FK)MANAGER_ID (O) (FK)ADDRESS_ID (O) (FK)
![Page 59: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/59.jpg)
many-to-one, unidirektional
-id : int-name : String-salary : long
Employee
-id : int-name : String
Department
* 0..1
DEPARTMENT
ID
NAME (O)
EMPLOYEE
ID
NAME (O) SALARY (O) STARTDATE (O) DEPARTMENT_ID (O) (FK)MANAGER_ID (O) (FK)ADDRESS_ID (O) (FK)
DEPARTMENT
ID
NAME (O)
EMPLOYEE
ID
NAME (O) SALARY (O) STARTDATE (O) DEPARTMENT_ID (O) (FK)MANAGER_ID (O) (FK)ADDRESS_ID (O) (FK)
DEPARTMENT
ID
NAME (O)
EMPLOYEE
ID
NAME (O) SALARY (O) STARTDATE (O) DEPARTMENT_ID (O) (FK)MANAGER_ID (O) (FK)ADDRESS_ID (O) (FK)
Employee@ManyToOneprivate Department department;
(JPA2 unterstützt auch many-to-one mit einer zusätzlichen Zwischentabelle)
![Page 60: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/60.jpg)
one-to-many, bidirektional
Phone@ManyToOne(optional = false)private Employee employee;
Employee@OneToMany(mappedBy = "employee")private Collection<Phone> phones;
-id : int-phonenumber : String-type : String
Phone
-id : int-name : String-salary : long
Employee
* 1
EMPLOYEE
ID
NAME (O) SALARY (O) STARTDATE (O) DEPARTMENT_ID (O) (FK)MANAGER_ID (O) (FK)ADDRESS_ID (O) (FK)
PHONE
ID
PHONENUMBER (O) TYPE (O) EMPLOYEE_ID (O) (FK)
![Page 61: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/61.jpg)
many-to-many, bidirektional
Employee
@ManyToMany(mappedBy = "employees")private Collection<Project> projects;
Project
@ManyToManyprivate Collection<Employee> employees;
-id : int-name : String-salary : long
Employee
-id : int-name : String
Project
* *
PROJECT
ID
DTYPE (O) NAME (O)
PROJECT_EMPLOYEE
PROJECTS_ID (FK)EMPLOYEES_ID (FK)
EMPLOYEE
ID
NAME (O) SALARY (O) STARTDATE (O) DEPARTMENT_ID (O) (FK)MANAGER_ID (O) (FK)ADDRESS_ID (O) (FK)
![Page 62: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/62.jpg)
Many-To-Many Beziehungen
„If you think that two objects share a simple many-to-many relationship, you haven't looked closely enough at the domain. There is a third object waiting to be discovered with attributes and a life cycle all its own.“ - Dierk König
• Oft sind weitere Daten auf der Zwischentabelle nötig
• Üblicherweise mappt man dann die Zwischentabelle auf eine eigene Entity
![Page 63: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/63.jpg)
one-to-many, unidirektional• Bei einer unidirektionalen one-to-many Beziehungen
fehlt das mappedBy Element und das Target hat keine Rückbeziehung
• JPA verwendet in diesen Fällen ebenfalls eine Beziehungstabelle
• JPA 2 spezifiziert die unidirektionale one-to-many Beziehung ohne Zwischentabelle.
@OneToMany@JoinColumn (name=”department_id”)private Set<Employee> employees = new HashSet<Employee>();
@OneToManyprivate Set<Employee> employees = new HashSet<Employee>();
![Page 64: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/64.jpg)
Bidirektionale Beziehungen
JPA verändert die Java-Semantik nicht! D.h. der korrekte Unterhalt von bidirektionalen
Beziehungen ist Sache der Applikation!
Department taxes = new Department();
Employee john = new Employee();
taxes.getEmployees().add(john);
john.setDepartment(taxes);
![Page 65: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/65.jpg)
Bidirektionale Beziehungen
Best Practice: Convenience Methoden auf den Entities:@Entity
public class Department { … @OneToMany private List<Employee> employees = new ArrayList<Employee>();
public void addEmployee(Employee employee){ if (employee == null)
throw new IllegalArgumentException(“Null employee“); if (employee.getDepartment() != null) employee.getDepartment().getEmployees().remove(employee); getEmployees().add(employee); employee.setDepartment(this); } …}
Analog: removeEmployee() sowie Methoden auf Employee.
![Page 66: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/66.jpg)
Verwendung von Collections• java.util.Set
– Eindeutig (Object.equals())– @OneToMany
private Set<Phone> phones;
• java.util.List– geordnet, kann sortiert werden– @OneToMany
@OrderBy("phonenumber ASC")private List<Phone> phones;
• java.util.Map– Key/Value Paare– @OneToMany
@MapKey(name = "phonenumber")private Map<String, Phone> phones;
JPA 2:Persistenter Index@OneToMany@OrderColumn(name="index")private List<Phone> phones;
![Page 67: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/67.jpg)
Lazy- und Eager-Loading
• Default bei one-to-one und many-to-one– FetchType.EAGER
• Default bei one-to-many und many-to-many– FetchType.LAZY
• Defaultverhalten kann übersteuert werden. z.B.– @OneToMany(fetch = FetchType.EAGER)
private Set<Phone> phones;
EntityManager em = ...Department sales = em.find(Department.class, 123);sales.getEmployees().iterator().next();
Beziehungen werden transparent (nach)geladen:
![Page 68: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/68.jpg)
Speichern und Löschen von Beziehungen
Department taxes = new Department();Employee john = new Employee();taxes.addEmployee(john);Employee jane = new Employee();taxes.addEmployee(jane);
em.persist(taxes);em.persist(john);em.persist(jane);em.flush();
for (Employee empl : taxes.getEmployees()){ em.remove(empl);}em.remove(taxes);em.flush();
• Jede Entity hat einen eigenen, unabhängigen Lifecycle!• IllegalStateException
wenn vergessen wird, eine assoziierte Entity zu persistieren.
• Delete all entities individually
![Page 69: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/69.jpg)
Transitive Persistenz
Persistenz wird von JPA propagiert auf assoziierte Entities.
@OneToMany (mappedBy = “department“, cascade = CascadeType.ALL)
private Set<Employee> employees = new
HashSet<Employee>();Department taxes = new Department();Employee john = new Employee();taxes.addEmployee(john);Employee jane = new Employee();taxes.addEmployee(jane);
em.persist(taxes);em.flush();
em.delete(taxes);em.flush();
• Kaskadierung wird auf der Assoziation konfiguriert
• Speichern eines Parents speichert auch alle Kinder
• Löschen eines Parents löscht auch alle Kinder.
CascadeType {ALL, PERSIST, MERGE, REMOVE, REFRESH, DETACH};
![Page 70: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/70.jpg)
Orphan DeletionPhone phone1 = …Employee john = em.find(Employee.class, 123);john.getPhones().remove(phone1);em.flush();
• Child wird nicht gelöscht!
Entfernen eines Kindes aus der Collection des Parents setzt nur den Foreign Key auf der Kind-Tabelle auf NULL.– FK Constraint Verletzung möglich– Das Kind ist nun “orphaned”
• In JPA 1 muss das Löschen von Orphans explizit in der Applikation erfolgen.• JPA 2 unterstützt das automatische Löschen von Orphans
@OneToMany(cascade=ALL, mappedBy=”customer”, orphanRemoval=true) public Set<Order> getOrders() { return orders; }
![Page 71: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/71.jpg)
Working With Persistent Objects
Objektrelationales Mapping mit JPA 2.0
![Page 72: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/72.jpg)
Persistence Context
Der Persistence Context definiert das physische Umfeld von Entities zur Laufzeit: die Menge aller Managed Entities in der
Applikation den Entity Manager für diese Entities die laufende Transaktion den Contexttyp
72
![Page 73: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/73.jpg)
Kontext Typen
TRANSACTION Standard im Java EE Umfeld Lesender und schreibender Zugriff nur innerhalb der Transaktion. Gelesene Objekte sind nach der Transaktion im Zustand detached Wiedereinkopplung in eine Transaktion mit merge()
EXTENDED Standard im Java SE Umfeld Alle Objekte sind lesend und schreibend zugreifbar Modifikationen finden lokal statt Effekt von persist(), remove() usw. wird aufbewahrt Propagation von Efffekten und Änderungen in die DB aber nur,
wenn nachträglich begin()/commit() ausgeführt wird
73
![Page 74: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/74.jpg)
Objektverwaltung
Der Transfer von Objekten von und zur Datenbank erfolgt automatisch: so spät wie möglich Lazy Access
Der Transfer von Objekten von und zur Datenbank kann manuell erzwungen werden synchron zum Aufruf
Selbstverständlich gilt ein Transaktionsmodell: Der Zugriff auf Objekte erfolgt ab Beginn der Transaktion, die Synchronisation mit der Datenbank wird spätestens beim Commit abgeschlossen und unterliegt der ACID-Regel
Auf Objekte kann auch ausserhalb von Transaktionen zugegriffen werden, jedoch ohne Konsistenz- und Synchronisationsgarantie
74
![Page 75: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/75.jpg)
Objektzustand
Objekte haben vier mögliche Zustände: New
Objekt ist neu erzeugt, hat noch keinen Zusammenhang mit der Datenbank und noch keine gültige ID.
Managed Das Objekt hat eine Entsprechung in der Datenbank. Änderungen
werden vom Entity Manager automatisch getracked und mit der DB abgeglichen.
Detached Das Objekt hat eine Entsprechung in der Datenbank, wurde aber
abgekoppelt. Der Zustand wird nicht mehr automatisch abgeglichen mit der Datenbank.
Removed Das Objekt existiert noch, ist aber zum Löschen markiert.
75
![Page 76: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/76.jpg)
Zustände und Übergänge
new
managed
detached
removed
EntityManager.persist
EntityManager.remove
(Transaction.commit)Transaction.rollback
Serialisierung
EntityManager.clearEntityManager.close
EntityManager.merge
76
![Page 77: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/77.jpg)
Entity persistieren
Mit persist() wird eine neue Entity vom EntityManager verwaltet
Die Methode contains() kann geprüft werden ob eine Entity managed ist
77
Department dept = em.find(Department.class, deptId);Employee emp = new Employee();emp.setId(empId);emp.setName(empName);emp.setDepartment(dept);dept.getEmployees().add(emp);em.persist(emp);
![Page 78: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/78.jpg)
Objekt ID
Ein neues Objekt bekommt erst eine ID, wenn es das erste Mal physisch in die Datenbank transportiert wird
78
Employee emp = new Employee();em.persist(emp);System.out.println(emp.getId()); // null
em.flush(); oder em.getTransaction().commit();System.out.println(emp.getId()); // gültige ID, z.B. 1
![Page 79: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/79.jpg)
Kaskadierte Persistenz (1)
Kaskadierte Persistenz heisst: Alle von einem persistenten Objekt aus erreichbaren Objekte sind ebenfalls persistent
Die Kaskadierung muss deklariert werden: PERSIST MERGE REMOVE REFRESH ALL
79
Employee employee = new Employee();em.persist(emp);Address address = new Address();employee.setAddress(address);
![Page 80: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/80.jpg)
Kaskadierte Persistenz (2)
Die Kaskadierung kann für das Erstellen und das Löschen der Persistenz separat eingestellt werden
Die Kaskadierung bezieht sich nun auf die persist() und die remove()-Methode.
80
public class Employee { @OneToOne( cascade={CascadeType.PERSIST, CascadeType.REMOVE } ) private Address address; ...}
![Page 81: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/81.jpg)
Orphan Removal (JPA 2.0)
Sollen abhängige Kindelemente bei to-many Beziehungen ebenfalls gelöscht werden, kann dies seit JPA 2.0 ebenfalls deklariert werden:
81
@OneToMany(cascade=ALL, mappedBy=”customer”, orphanRemoval=true) private Set<Order> orders;
![Page 82: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/82.jpg)
Entity suchen
Mit find() kann eine Entity über ihren Primary Key gefunden werden
Die gefunden Entity wird kommt automatisch in den Zustand managed
Da find() über den Primary Key sucht, kann diese Methode vom Persistence Provider optimiert werden und unter Umständen einen Datenbankzugriff vermieden werden
Soll eine one-to-one oder many-to-one Reference auf eine bestehende Entity gebildet werden, kann getReference() verwendet werden um das vollständige Laden der Target-Entity zu verhindern
82
![Page 83: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/83.jpg)
Einlesen
Der Objektzustand wird beim ersten Zugriff auf das Objekt eingelesen.
Wenn FetchType.EAGER gesetzt ist, werden referenzierte Objekte ebenfalls mitgeladen.
Wenn FetchType.LAZY gesetzt ist, werden referenzierte Objekte beim ersten Gebrauch eingelesen.
Der Objektzustand wird nie automatisch aufgefrischt, nur via die EntityManager.refresh()-Methode.
Eine neue Transaktion führt nicht automatisch zum erneuten Einlesen bestehender Objekte.
83
![Page 84: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/84.jpg)
Entity löschen
Mit remove() wird dem EntityManager mitgeteilt, dass diese Entity gelöscht werden kann
84
Employee emp = em.find(Employee.class, empId);em.remove(emp);
![Page 85: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/85.jpg)
Objektzustand nach Commit
Wenn der Persistence Context EXTENDED ist, bleibt ein Objekt im Zustand managed nach dem Commit. Änderungen nach dem Commit werden aufbewahrt und im
Rahmen der nächsten Transaktion in die Datenbank übernommen.
Wenn der Persistence Context TRANSACTION ist, geht ein Objekt in den Zustand detached über nach dem Commit. Änderungen müssen mit EntityManager.merge() innerhalb
der nächsten Transaktion wieder eingekoppelt werden.
85
![Page 86: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/86.jpg)
Objektzustand nach Rollback
Nach einem Rollback ist jedes noch vorhandene Objekt im Zustand detached. Die Belegung der Felder wird durch den Rollback nicht geändert, jedoch der Zustand in der Datenbank
Vorsicht vor möglichen Inkonsistenzen
Objekte via Methoden des Entity Manager neu laden:find(), getReference(), createQuery() usw.
86
![Page 87: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/87.jpg)
Persistence Context aufräumen
Ab und zu kann es vorkommen, dass der Persistence Context gelöscht werden soll
Dies kann mit der Methode clear() des EntityManager erreicht werden
Alle Entities kommen in den Zustand detached
Vorsicht: enthält der Persistence Context Änderungen welche noch nicht mit commit() gespeichert wurden, gehen diese verloren
87
![Page 88: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/88.jpg)
Synchronisation mit der Datenbank
Das Zurückschreiben findet zum Commit-Zeitpunkt oder explizit mit der flush() Methode statt.
Das Zurückschreiben beinhaltet kein Refresh allfälliger Änderungen in der Datenbank in der Zwischenzeit -> Lost Update!
Das Zurückschreiben betrifft nur Änderungen, nicht ungeänderte Daten.Applikationm.setContent("A")tx.commit()
m.setContent("C")tx.commit()
SQL-Client
update Messageset content = 'B'; commit
Zustand von m in Appl in DB A A
A B
C C
88
![Page 89: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/89.jpg)
Foreign Key Constraints
Änderungsoperationen erzeugen oft Konflikte mit Fremdschlüssel-bedingungen, wenn Datensätze in der falschen Reihenfolge gelöscht werden.
Oracle erlaubt die Constraints DEFERABLE zu definieren, damit diese erst zum Commit Zeitpunkt geprüft werden:
89
ALTER TABLE EMPLOYEE ADD CONSTRAINT EMPLOYEE_ADDRESS_FK FOREIGN KEY (ADDRESS_ID) REFERENCES ADDRESS(ID) DEFERRABLE INITIALLY DEFERRED;
![Page 90: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/90.jpg)
Querying
Objektrelationales Mapping mit JPA 2.0
![Page 91: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/91.jpg)
Entities laden
In JPA gibt es verschiedene Optionen Entitäten zu laden: Eine einzelne Instanz über die ID laden Navigation auf dem Objektgraphen Queries in der Java Persistence Query
Language (JPQL) Queries in SQL
In JPA2 kommt neu die Criteria API hinzu
![Page 92: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/92.jpg)
Entity über die ID laden
Der EntityManager stellt zwei Möglichkeiten zur Verfügung: find() und getReference()EntityManager em = …Integer id = 1234;Employee john = em.find(Employee.class, id);
Falls die Entität bereits im Persistence Context geladen ist, so wird kein DB-Query ausgeführt.
find(): Wenn sich die Entity noch nicht im Persistence Context befindet, so wird sie von der DB geladen. Resultat is null, falls die Entity nicht existiert
getReference(): Wenn sich die Entität noch nicht im Persistence Context befindet, so wird ein Proxy zurückgegeben. Es wird vorerst kein DB-Query ausgeführt. Dieses erfolgt erst wenn auf die Entität zugegriffen wird. EntityNotFoundException erst beim Zugriff, falls die Entity nicht existiert.
![Page 93: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/93.jpg)
Navigation des Objektgraphen
Ausgehend von einer Entity kann ein Objektgraph traversiert werden. Dabei lätdt JPA transparent alle notwendigen Daten von der DB.
– Dieses Feature wird “Lazy Loading” genannt
– Die Entities müssen persistent und der EntityManager muss offen sein
– Dies ist ein mächtiges Feature, birgt aber auch Gefahren
![Page 94: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/94.jpg)
Queries mit JPQL
JPQL ist eine mächtige Abfragesprache basierend auf dem Entitätenmodell: Stark an SQL angelehnt Unabhängig von der darunterliegenden Datenbank Abfragen basieren auf dem Klassenmodell (Entitäten), nicht auf
dem Datenmodell (Tabellen) Unterstützt OO-Konstrukte wie Vererbung, Polymorphismus
und Pfadausdrücke
String queryString =
“select e.address from Employee e where e.mainProject.name = ‘JPA Kurs‘“;
Query query = em.createQuery(queryString);
List<Address> users = query.getResultList();
![Page 95: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/95.jpg)
Verwendung von JPQL
Typischerweise wird JPQL verwendet um Entities zu laden. JPQL unterstützt aber auch andere Szenarien: Abfrage von skalaren Werten (Projektionen oder
Aggregationen) Bulk Updates und Deletes Reporting Queries: Rückgabe von Daten-Tupels, Nutzung von
Gruppierungs- und Aggregationsfunktionen der DB Constructor Expressions: Abfüllen von beliebigen Objekten
(nicht notwendigerweise Entities)
JPQL kann entweder in Dynamischen Queries oder in Named Queries verwendet werden.
![Page 96: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/96.jpg)
Dynamische Queries
Bei Dynamischen Queries wird der JPQL String zur Laufzeit erstellt. Kontextabhängige Queries String Concatenation
EntityManager em = ...
String queryString =
“select e from Employee e where e.address.city = ‘Bern‘“;
Query query = em.createQuery(queryString);
List<Employee> employees = query.getResultList();
![Page 97: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/97.jpg)
Named Queries Named Queries werden statisch definiert und können überall in
der Applikation verwendet werden. Die JPA Infrastruktur kann Named Queries vor der eigentlichen
Ausführung parsen und kompilieren (Prepared Statements) Parsen/Kompilierung muss nur einmal durchgeführt werden Kann beim Deployen/Startup erfolgen und überprüft werden (Fail Fast)
@NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e")public class Employee { ... }
EntityManager em = ...Query q = em.createNamedQuery("Employee.findAll");
List<Employee> employees = query.getResultList();
![Page 98: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/98.jpg)
Parameter Binding
Queries sollten parametrisert werden. Es gibt zwei Arten der Parametrisierung:
• Named Parameters
• Positional Parameters
SELECT e FROM Employee eWHERE e.department = :dept
AND e.salary > :base
Query q = ...q.setParameter("dept", "Taxes");q.setParameter("base", "3500");
SELECT e FROM Employee eWHERE e.department = ?1 AND e.salary > ?2
Query q = ...q.setParameter(1, "Taxes");q.setParameter(2, "3500");
![Page 99: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/99.jpg)
Queries ausführen
• Abholen des Resultates mit Methoden von Query
List getResultList()Object getSingleResult()int executeUpdate()
• BeispielQuery q = em.createQuery("SELECT e FROM Employee e");List<Employee> emps = q.getResultList();
for(Employee e : emps) { System.out.println(e);}
![Page 100: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/100.jpg)
JPQL Sprach-Features
JPQL ist eine sehr mächtige und flexible Abfragesprache. Hier nur einige Features:
JOINS und Subqueries (IN, EXISTS) Aggregatsfunktionen (AVG, COUNT, MIN, MAX, SUM) GROUP BY und HAVING Funktionen (LOWER, ABS, TRIM ...) LIKE Collection-Abfragen: IS EMPTY, MEMBER ANY, ALL, SOME,
![Page 101: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/101.jpg)
Pfad-Ausdrücke
Ein Pfadausdruck ermöglicht die direkte Navigation von einem äusseren zu inneren, referenzierten Objekten:
SELECT e.address FROM Employee e SELECT e.address.name FROM Employee e
Ein Pfadausdruck kann in einer Collection enden: SELECT e.projects FROM Employee e
Ein Pfadausdruck kann nicht über eine Collection hinweg navigieren:
SELECT e.projects.name FROM Employee e
![Page 102: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/102.jpg)
Pagination
String queryString = “select e from Employee“;
Query query = em.createQuery(queryString);
query.setFirstResult(110);
query.setMaxResults(10);
List<Order> orders = query.getResultList();
• JPA schreibt nicht vor, wie Pagination umgesetzt wird! Dies kann von JPA-Implementation und DB-Dialekt abhängen.
– In der Regel wird das resultierende SQL-Query für den entsprechenden SQL-Dialekt optimiert.
– Achtung: Meist wird das SQL-Rowset limitiert, und nicht die resultierenden Entities!
Mit JPA ist Pagination sehr einfach:
![Page 103: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/103.jpg)
Fetching & Lazy Loading
Die Idee von Lazy Loading ist es, die Daten erst dann von der DB zu laden, wenn sie auch wirklich in der Applikation benötigt werden. Das Laden sollte für den Client transparent sein Dem Programmierer wird viel Arbeit erspart
Nachteile: Traversieren eines Objekt-Graphen kann in vielen einzelnen
DB-Queries resultieren “N+1 select problem”: Für eine Parent-Child Beziehung wird für
jedes Kind ein eigenes DB-Query abgesetzt
Das Gegenteil von Lazy Loading ist Eager Loading
![Page 104: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/104.jpg)
Fetching & Lazy Loading
• In JPA kann das Lade-Verhalten auf zwei Weisen beeinflusst werden:– Global Fetch Plan: Konfiguriert in den
Entity-Metadaten (Annotationen/XML)
– Programmatisch beim Erstellen eines Queries mittels Join Fetch
@OneToMany(mappedBy = "employee", fetch = FetchType.EAGER)private Set<Phone> phones = new HashSet<Phone>();
SELECT d FROM Department d LEFT JOIN FETCH d.employees
Fetch Join analog mit JPA 2 Criteria API.
![Page 105: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/105.jpg)
Joins & Fetching
Es gibt unterschiedliche Joins in JPQL:
SELECT d FROM Department d LEFT JOIN FETCH d.employees
• Explizite Joins für Selektion und Projektion
• Implizite Joins aus Pfadausdrücken
• Fetch Joins für Eager Loading
SELECT e FROM Employee e where e.address.city = 'Bern'
SELECT employee FROM Employee employee JOIN employee.projects project WHERE project.name = 'Arcos'
SELECT e.address FROM Employee e where e.name = 'John'
SELECT project FROM Employee employee JOIN employee.projects project WHERE employee.name = 'John'
![Page 106: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/106.jpg)
Polymorphe Queries
Query q = em.createQuery("select p FROM Project
p");List<Project> projects = q.getResultList();
JPQL unterstützt Polymorphie:
• JPA 1: Queries sind immer polymorph!• JPA 2: Einschränkungen des Typs mittels
Type-Expression möglich
SELECT p FROM Project p WHERE TYPE(p) IN (DesignProject)
Selektion aufgrund einer Subklasse:
SELECT employee FROM Employee employee JOIN employee.projects project, DesignProject dprojectWHERE project = dproject AND dproject.innovationLevel > 2
![Page 107: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/107.jpg)
Reporting Queries Wird mehr als eine Expression in der SELECT Klausel
verwendet, wird ein Object[]-Array zurückgegeben:
List result = em.createQuery( "SELECT e.name, e.department.name " + "FROM Project p JOIN p.employees e " + "where p.name = "ZLD").getResultList();
for (Iterator i = result.iterator(); i.hasNext()) { Object[] values = (Object[])i.next(); System.out.println(values[0] + "," + values[1]);}
• Solche Queries werden typischerweise für Reporting verwendet
• Das Resultat sind keine Entities und wird nicht vom Persistence Context gemanagt!
![Page 108: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/108.jpg)
Constructor Expressions Mit Constructor Expressions existiert eine einfache
Möglichkeit um Resultate auf Klassen zu mappen: public class EmployeeDTO { public String employeeName; public String deptName; public EmployeeTO(String employeeName, String deptName) {...}}
List result = em.createQuery( "SELECT NEW jpa.util.EmployeeDTO(e.name, e.department.name) " + "FROM Project p JOIN p.employees e " + "where p.name = "ZLD").getResultList();
for (EmployeeTO emp : result) { System.out.println(emp.employeeName + "," + emp.deptName);}
• Achtung: Klasse muss vollqualifiziert angegeben werden!• Kann auch mit Entities verwendet werden.• Das Resultat wird nicht vom Persistence Kontext
gemanagt.
![Page 109: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/109.jpg)
Bulk Statements
In JPQL können UPDATE und DELETE-Statements formuliert werden, welche auf eine Menge von Entities angewendet werden.
Query q = em.createQuery("DELETE from Employee e");int count = q.executeUpdate();
Query q = em.createQuery("UPDATE Employee e " + "SET e.name = 'Simon' " + "WHERE e.name = 'Peter');int count = q.executeUpdate();
Achtung: Bulk Statements umgehen den Entity Manager!Damit geladene Entities die Veränderungen mitbekommen, müssen sie mit der Datenbank synchronisiert werden.
![Page 110: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/110.jpg)
Vorteile und Nachteile von JPQL
• Vorteile– Sehr mächtig und flexibel– Stark an SQL angelehnt
• Nachteile– JPQL ist eine embedded Language die in Java
mittels Stings verwendet wird.• Keine Überprüfung beim Kompilieren, keine Typ-Sicherheit
– Flexible Komposition eines Queries ist nicht elegant möglich (String-Manipulation)
– Für nicht-triviale Anwendungen ist SQL Knowhow und Verständnis des Datenmodels ist notwendig
![Page 111: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/111.jpg)
SQL Queries
• Stored Procedures werden in JPA nicht unterstützt. Die meisten JPA-Implementationen bieten jedoch proprietäre Mechanismen zum Einbinden von Stored Procedures.
• JPA ermöglicht die Formulierung von SQL-Queries:
Query q = em.createNativeQuery("SELECT * FROM emp WHERE id = ?", Employee.class);q.setParameter(1, employeeId);List<Employee> employees = q.getResultList();
• SQL-Queries könne auch als NamedQuery definiert werden:
@NamedNativeQuery(name = "employeeReporting", query = "SELECT * FROM emp WHERE id = ?", resultClass = Employee.class)
Ausführung analog Named Queries in JPQL
![Page 112: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/112.jpg)
SQL Queries• Update und Delete Statements:
Query q = em.createNativeQuery("UPDATE emp SET salary = salary + 1");int updated = q.executeUpdate();
• Flexibles Mapping des Result-Sets
String s = "SELECT e.*, a.* FROM emp e, address a" + "WHERE e.adress_id = a.id";
Query q = em.createNativeQuery(s, "EmployeeWithAddress");List<Employee> employees = q.getResultList();
@SqlResultSetMapping(name = "EmployeeWithAddress",entities = {@EntityResult(entityClass = Employee.class), @EntityResult(entityClass = Address.class)}
![Page 113: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/113.jpg)
Criteria API in JPA 2
Mit der Criteria API wird in JPA 2 eine Objekt-Orientierte Schnittstelle zum programmatischen Erstellen von Queries standardisiert.
Vorteile: Dynamisches Erstellen von Queries (Komposition) Keine String-Manipulation notwendig OO-Konstrukte zum Erstellen komplexer Queries Gewisse Typsicherheit
![Page 114: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/114.jpg)
Criteria API in JPA 2Beispiel mit Strings für Referenzen:
Beispiel mit dem typsicheren, statischen Metamodel:
QueryBuilder qb = ... CriteriaQuery q = qb.create(); Root<Customer> cust = q.from(Customer.class); Join<Order, Item> item = cust.join("orders").join("lineitems"); q.select(cust.get("name")).where( qb.equal(item.get("product").get("productType"), "printer"));
QueryBuilder qb = ... CriteriaQuery q = qb.create(); Root<Customer> cust = q.from(Customer.class); Join<Customer, Order> order = cust.join(Customer_.orders); Join<Order, Item> item = order.join(Order_.lineitems); q.select(cust.get(Customer_.name)) .where(qb.equal(item.get(Item_.product).get(Product_.productType), "printer"));
![Page 115: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/115.jpg)
Metamodel API
Metamodel: statische Klassen, welche das Entity-Model abbilden
Queries mit der Criteria API kann können mit dem Metamodel komplett typsicher programmiert werden
@StaticMetamodel(Department.class)public class Department_ { public static volatile SingularAttribute<Department, Integer> id; public static volatile SingularAttribute<Department, String> name; public static volatile SetAttribute<Department, Employee> employees;}
![Page 116: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/116.jpg)
Metamodel API Erstellung des Metamodels ist nicht
standardisiert. Typischerweise erfolgt sie über einen JDK6 Annotation Processor (APT)
Java CompilerDepartment.java
Department_.java
Department_.classDepartment.class
AnnotationProcessor
call
generate
compile
compile
![Page 117: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/117.jpg)
Advanced Mapping
Objektrelationales Mapping mit JPA 2.0
![Page 118: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/118.jpg)
Embedded Objects
-id : int-name : String-salary : long
Employee
-id : int-street : String-city : String-state : String-zip : String
Address
0..1
118
Komposition: Mutterobjekt mit eingebetteten Objekten
Eingebettete Objekte haben keine eigene Identität
Mutterobjekt und eingebettete sind in derselben Tabelle abgelegt
EMPLOYEE
PK ID
NAME SALARY STREET CITY STATE ZIP
![Page 119: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/119.jpg)
Embedded Objects, Beispiel
119
@Embeddablepublic class Address { private String street; private String city; private String state; private String zip;}
@Entitypublic class Employee { @Id private int id; private String name; private long salary; @Embedded private Address address;}
![Page 120: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/120.jpg)
Enhanced Embeddables (JPA 2.0)
Verschachtelung von Embeddables und Embeddables mit Beziehungen
120
@Embeddablepublic class Assembly { ... @Embedded ShippingDetail shipDetails;
@ManyToOne Supplier supplier; ...}
![Page 121: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/121.jpg)
Zusammengesetzte Primärschlüssel
121
public class EmployeeId implements Serializable { protected String country; protected int id;}
// Variante 1@IdClass( EmployeeId.class )@Entity public class Employee { @Id protected String country; @Id protected int id;}
// Variante 2@Entity public class Employee { @EmbeddedId public EmployeeId id;}
![Page 122: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/122.jpg)
Composite Primary Key With Relationships (JPA 2.0)
122
@Entity @IdClass(PartPK.class)public class Part { @Id int partNo; @Id @ManyToOne Supplier supplier;}
public class PartPK { int partNo; int supplier;}
![Page 123: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/123.jpg)
Read-Only Mappings und Optional
Read-Only@Column(insertable = false, updateable = false)
Optional@ManyToOne(optional = true) // Default
123
![Page 124: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/124.jpg)
Mehrere Tabellen pro Entity
Gelegentlich wird eine Entity in der Datenbank in mehrere Tabellen modelliert oder muss umgekehrt aus mehreren Tabellen zusammengesetzt werden.
Eine Entity kann beliebig viele Sekundärtabellen haben:
124
@Entity@Table( name = "Employee" )@SecondaryTable( name = "EmployeeExt", pkJoinColumns = { @PrimaryKeyJoinColumn(name="idRef", referencedColumnName = "id")})public class Employee { ...}
![Page 125: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/125.jpg)
Mapping von SQL-Views
Komplexe Abfragen werden in einer Datenbank gerne als (materialisierte) View vorgehalten. Um Performance-Vorteile zu nutzen, kann eine View wie eine Entity angesprochen werden. Beispiel:
125
@Entity public class EmployeeStats{ @Id protected long id; @Column( insertable=false, updatable=false) protected int numPhones; // ... CREATE VIEW employeestats ( id, numPhones ) AS SELECT e.id, COUNT(p.*) FROM employee e LEFT OUTER JOIN PHONES P on (…) group by e.id
![Page 126: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/126.jpg)
Vererbung
Vererbungshierarchien können problemlos verwendet und abgebildet werden.
Klassen können abstrakt oder konkret sein.
Alle Klassen in der Vererbungshierarchie müssen den Primärschlüssel der Basisklasse verwenden (erben).
Es gibt vier Mappingstrategien auf die Datenbank:
Eine einzige Tabelle für die gesamte Verbungshierarchie Eine Tabelle für jede konkrete Klasse Eine Tabelle für jede Klasse Mapped Superclass
126
![Page 127: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/127.jpg)
SINGLE_TABLE
-id : int-name : String
Project
DesignProject QualityProject
PROJECT
ID
DTYPE (O) NAME (O)
127
@Entity @Inheritance public class Project
@Entity public class DesignProject extends Project
@Entity public class QualityProject extends Project
![Page 128: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/128.jpg)
JOINED
PROJECT
ID
DTYPE (O) NAME (O)
QUALITYPROJECT
ID (FK)DESIGNPROJECT
ID (FK)
-id : int-name : String
Project
DesignProject QualityProject
128
@Entity @Inheritance(strategy=InheritanceType.JOINED)public class Project
@Entity public class DesignProject extends Project
@Entity public class QualityProject extends Project
![Page 129: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/129.jpg)
TABLE_PER_CLASS (Optional)
-id : int-name : String
Project
DesignProject QualityProject
DesignProject
name (O)
QualityProject
name (O)
129
@Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)public class Project
@Entity public class DesignProject extends Project
@Entity public class QualityProject extends Project
![Page 130: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/130.jpg)
MAPPED_SUPERCLASS
-phonenumber : String-type : String
Phone
-id : Integer-createdAt : Date-createdFrom : String-updatedAt : String-updatedFrom : String-version : Integer
BaseEntity
130
// Klasse BaseEntity@MappedSuperclasspublic abstract class BaseEntity { @Id @GeneratedValue protected Integer id; protected Integer version; protected Timestamp createdAt; protected String createdFrom; protected Timestamp updatedAt; protected String updatedFrom;
// Klasse Phone@Entitypublic class Phone extends BaseEntity
![Page 131: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/131.jpg)
Performance
Objektrelationales Mapping mit JPA 2.0
![Page 132: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/132.jpg)
“Premature Optimization is the Root of all Evil.”
- Donald Knuth
“You can't control what you can't measure.”
- Tom DeMarco
![Page 133: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/133.jpg)
SQL Logging
• Logging des JPA-Providers– z.B: in persistence.xml:
• Logging/Profiling Funktionalität der DB• Logging/Profiling auf JDBC Ebene
– Log4jdbc (http://code.google.com/p/log4jdbc/)
– Log4jdbc-remix (http://code.google.com/p/log4jdbc-remix/)
– P6Spy (http://www.p6spy.com/)
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.level.parameters" value=“true"/>
![Page 134: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/134.jpg)
Minimizing Query Count
• Typischer Weise entstehen die ersten Persistenz bezogenen Performance Probleme aufgund der Anzahl Queries auf die DB – Analyse– Optimierung des Globalen Fetch Plans– Optimierung des Fetch Plans auf Use-Case
Ebene– Caching in der Applikation (z.B. DAO,
Manager)– 2nd Level Cache / Query Cache– “Reporting View” mit Constructor Expressions
![Page 135: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/135.jpg)
Teure Queries
• Analyse, auch auf DB Ebene (Execution-Plan)– Meist hilft das setzten eines Index in der
DB– Optimierung der Fetch-Strategie– Optimierung von Queries– Verwendung von Query Hints – Verwendung von SQL-Queries
![Page 136: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/136.jpg)
Named Queries
• Named Queries können vom JPA-Provider beim Deploy oder Startup-Zeitpunkt geparst und kompiliert werden. Das resultierende prepared Statement kann dann wiederverwendet werden.
![Page 137: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/137.jpg)
Instanzierung und Marshalling
• In Typischen Anwendungen ist dies kaum ein Performance Problem.– Objektinstanzierung ist um
Grössenordnungen schneller als DB-Query• Bei sehr grossen Datenmengen können
Probleme entstehen aufgrund der Session Grösse (Identity-Map)
Result SetsObjekte / Objekt-Graphen
Statements
![Page 138: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/138.jpg)
Constructor Expressions
• Erlaubt “Views” auf Daten, welche nicht den Entity-Strukturen entspricht.
![Page 139: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/139.jpg)
Session Grösse
• Eine grosse Session kann zu Performance Problemen führen– Out of Memory– Garbage Collector– Identity Map
• Typischerweise ein Problem in Batch Szenarien– Frühe Erkennung während des Designs
sinnvoll– Anwendung einer anderen Persistenz
Strategie• Achtung: Session-Management sollte von
Transktions-Steuerung getrennt behandelt werden!
![Page 140: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/140.jpg)
Session Grösse
• Lösungsansätze– Regelmässiges flush() und clear()– Bulk-Statements in JPQL– Direktes SQL über JDBC– Proprietäre Mechanismen des JPA-Providers,
z.B. Hibernate Stateless Session
![Page 141: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/141.jpg)
Entity Caching
• Explizites Caching in der Applikation– z.B. DAO, Business-Komponente, Application-
Infrastruktur– Lifetime kann explizit kontrolliert werden (z.B.
Request, Conversation, Session, Application)
• Verwendung eines transparenten Caching Mechanismus (2nd Level Cache)– Lernkurve! Oft beinahe “Black Magic”.– Grösse, Invalidation, Transaction-Isolation ...
![Page 142: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/142.jpg)
Query Caching
• Etliche JPA Providers ermöglichen das Caching von Query-Results.– Ist nur in sehr seltenen Fällen sinnvoll– Queries sind meist parametrisiert ...– Invalidation und Read/Write Verhältnis
![Page 143: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/143.jpg)
Testing
Objektrelationales Mapping mit JPA 2.0
![Page 144: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/144.jpg)
Testen mit Einbezug der DB
Schwierigkeiten:• Die DB repräsentiert den Zustand unseres Systems• Oft enthält die DB den Input und den Output unseres
Tests• Um gezielt und deterministisch zu Testen müssen wir
den DB Zustand kennen und beeinflussen• Zusätzlich: Fast immer enthält die DB auch Logik
(Constraints sind auch Logik)
![Page 145: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/145.jpg)
Unit- vs. Integration Tests
• Mocking der DB soweit möglich:
• Einbindung der DB– DB in einen definierten Zustand bringen
– Tests durchführen
– Veränderungen verifizieren
– (Aufräumen)
![Page 146: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/146.jpg)
Mocking
• DAOs sind ein guter Ansatzpunkt– Zentraler Zugriffspunkt, klares Interface– Formulierung der Erwartungen an den
Data-Access Layer mit Business Semantik– Erwartungen können gegen die DB
gestestet werden
• Mocking der JPA-Infrastrukur – Möglich, aber aufwändig (EntityManager,
Query)– Viel technische Komplexität, kein Business
Value
![Page 147: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/147.jpg)
In-Memory Datenbank
• HSQLDB, H2 und Derby sind “reife” Datenbanken mit einem In-Memory Mode
• DB wird für jeden Test neu gestartet und initialisiert
– Einfache Integration, lokale Datenbank– Keine Seiteneffekte– Schema immer aktuell– Die meisten Persistenz bezogenen
Probleme können erkannt werden
![Page 148: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/148.jpg)
Mehrstufige Testing Strategie• Unit-Tests mit Mocking
– Testen von Business Komponenten in Isolation
– Korrektes Verhalten bezüglich erwartetem Business
• Funktionale Tests mit In-Memory Datenbank– Korrektes Verhalten mit Einbezug der Persistenz-API– Sehr einfache Integration, schnell, lokal– Setup/Teardown pro Test
• Integrations Tests gegen Produktions-Datenbank– Produktives Verhalten– Wenn möglich mit produktiven Datenbeständen– Komplizierteres Setup/Teardown, langsam
![Page 149: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/149.jpg)
Testdaten Management
• Wichtiges Thema das früh im Projekt angegangen werden sollte
• Wer liefert valide Testdaten• Wie und wann werden Testdaten in die
verschiedenen DBs eingespielt• Schema-Migrationen• Patterns für Unit-Tests:
– Object Mother, Test Data Builder
![Page 150: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/150.jpg)
Architecture
Objektrelationales Mapping mit JPA 2.0
![Page 151: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/151.jpg)
151
Java EE 6 Integration
![Page 152: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/152.jpg)
JSF 2.0 und Bean Validation
<h:inputText id="name" value="#{employeeBean.employee.name}"> <f:validateBean for="name"/></h:inputText>
<h:message for="name" />
152
![Page 153: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/153.jpg)
JSF und NULL Werte
Leere Input Felder werden von JSF als «» (leerer String) behandelt
Dies ist evtl. ein Problem für die BeanValidation @NotNull Constraint greift nicht
Lösung:<context-param> <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name> <param-value>true</param-value> </context-param>
Achtung vor allfälligen «Nebenwirkungen»!
153
![Page 154: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/154.jpg)
EJB 3.x Dependency Injection
@PersistenceUnit Liefert eine Referenz zur EntityMangerFactory
@PersistenceContext Liefert eine Referenz zum EntityManger
154
@PersistenceContextprivate EntityManager em;
@PersistenceUnitprivate EntityManagerFactory emf;
![Page 155: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/155.jpg)
JPA 2.0 und JSR 303
@NotNull statt @Column(nullable=false) @Size.max statt @Column.length @Digits statt @Column.precision/.scale @Min / @Max bei numerischen Columns @Future / @Past bei Datumstypen @Size für Collections und Arrays
155
![Page 156: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/156.jpg)
Stateless Session Beans
156
@Statelesspublic class EmployeeService {
@PersistenceContext( type=PersistenceContextType.TRANSACTION) private EntityManager em;
public Employee findById(Integer id) { Employee e = em.find(Employee.class, id);
return e; }}
![Page 157: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/157.jpg)
Stateful Session Beans
157
@Statefulpublic class EmployeeService {
@PersistenceContext( type=PersistenceContextType.EXTENDED) private EntityManager em;
public Employee findById(Integer id) { Employee e = em.find(Employee.class, id);
return e; }}
![Page 158: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/158.jpg)
Persistence Unit
158
<persistence> <persistence-unit name="jpa.sbb" transaction-type="JTA">
<jta-data-source>jdbc/emp</jta-data-source>
</persistence-unit></persistence>
![Page 159: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/159.jpg)
JPA 2.0 und JSR 303
@NotNull statt @Column(nullable=false) @Size.max statt @Column.length @Digits statt @Column.precision/.scale @Min / @Max bei numerischen Columns @Future / @Past bei Datumstypen @Size für Collections und Arrays
159
![Page 160: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/160.jpg)
160
Patterns
![Page 161: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/161.jpg)
Data Access Object (DAO)
ProblemYou want to encapsulate data access and manipulation in a separate layer
SolutionUse a Data Access Object to encapsulate all access to the persistent store. The Data Access Object manages the connection with the data source to obtain and store data
DAOs werden als einfache, zustandslose Klassen realisiert, die den Zugriff auf eine Datenquelle kapseln
Ziele: Trennung von Business Logik und technischer Zugriffslogik Kapselung von Zugriff auf Datenbank oder Fremdsystem
![Page 162: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/162.jpg)
DAO Klassendiagramm
Client Data Access Object Datenquelle
ResultSetTransfer Object
uses
uses createscreates
accesses
creates /uses
![Page 163: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/163.jpg)
DAO und JPA
Häufig überflüssig dank EntityManager Wenn schon DAO dann generisch
public interface GenericDAO { <T extends BaseEntity> T create(T t); <T extends BaseEntity> T find(Class<T> type, Serializable id); <T extends BaseEntity> T update(T t); void delete(Object t); List findByNamedQuery(String queryName); List findByNamedQuery(String queryName, Map<String, Object> parameters);}
![Page 164: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/164.jpg)
Transfer Object (TO)
ProblemYou want to transfer multiple data elements over a tier
SolutionUse a Transfer Object to carry multiple data across a tier
Daten werden in Datencontainern zusammengefasst und über Tier-Grenzen transportiert
Das Konzept sollte generell zwischen den Schichten eingesetzt werden
Ziel: Verringerung der übertragenen Datenmenge
![Page 165: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/165.jpg)
TO und JPA
Mit Constructor Expressions existiert eine einfache Möglichkeit direkt aus den Resultaten Transfer Objects zu erzeugen. public class EmpMenu { public EmpMenu(String employeeName, String deptName){...}}
List result = em.createQuery( "SELECT NEW jpa.util.EmpMenu(e.name, e.department.name) " + "FROM Project p JOIN p.employees e " + "where p.name = "ZLD").getResultList();
for (EmpMenu menu : result) { log.info(menu.employeeName + "," + menu.deptName);}
![Page 166: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/166.jpg)
Schichtung und Verteilung
Applikationsserver DB Server
Datenzugriff
Business
Client oder Webserver
Präsentations-schicht
Datenhaltung
Fassade Service
3rd Party
Applikation XY
TOs und Entities
Ausschliesslich TOs
![Page 167: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/167.jpg)
Client/Server
Ausschliesslich TOs
Entities
![Page 168: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/168.jpg)
Lazy Loading und Verteilung
Lazy Loading deaktivieren Vorteil: einfach, für wenig Daten nutzbar Nachteil: bei vielen Daten aus Performance Gründen nicht nutzbar
Open Session in View Pattern geht davon aus, dass in einer Webappliaktion die Session erst geschlossen wird, wenn der Request beendet ist. Vorteil: Die Daten werden bei Bedarf nachgeladen Nachteil: Funktioniert nur bei einer Webapplikation, Änderungen der Daten
auf dem GUI-Level unter Umgehung der Businesslogik, saubere Trennung der Layer nicht möglich.
Preload Pattern: Der Aufrufer einer DAO-Methode übergibt Informationen, welche Daten vorgeladen werden sollen. Vorteil: Abhängig von der Situation kann Lazy Loading eingesetzt oder
umgangen werden Nachteil: Kann zu einer Schwemme von DAO-Methoden führen um die
möglichen Kombinationen anzubieten.
168Java Persistence API
![Page 169: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/169.jpg)
Open Session in View
169Java Persistence API
HTTP Session
Transaktion 1 Transaktion 2
O1 O1
Lazy
![Page 170: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/170.jpg)
Preload Pattern nach Jürgen Kohl (1)
Jürgen Kohl beschreibt in der Ausgabe 4/2008 des Java Magazins sein Preload Pattern, dass in einigen Praxisprojekten erfolgreich eingesetzt wurde. Hierbei liegt der Fokus darauf die Methodenschwemme zu vermeiden und weiterhin die Nutzung eines GenericDAO zu erlauben.
Seine Anforderungen sind: generischer Mechanismus keine Verkomplizierung der Backend-Methoden bei
steigender Komplexität des Domain Models Anwender der Backend-Methoden können denkbare
Preload-kombinationen selbst definieren.
170Java Persistence API
![Page 171: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/171.jpg)
Preload Pattern nach Jürgen Kohl (2)
171Java Persistence API
public class Preload { private Class modelClass; private String property;
public Preload(Class modelClass, String property) { this.modelClass = modelClass; this.property = property; }}
![Page 172: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/172.jpg)
Preload Pattern nach Jürgen Kohl (3)
172Java Persistence API
public abstract class GenericDAO<T, ID> {
private Class<T> persistentClass;
private String getPropertyGetterName(String property ) { String propertyUpper = property.toUpperCase().substring(0, 1); return "get" + propertyUpper + property.substring(1); }
private Object invokeGetter(Object entity, Preload preload) { String getterName = getPropertyGetterName(preload.getProperty()); try { Method method = preload.getModelClass().getMethod( getterName, (Class[]) null); return method.invoke(entity, (Object[]) null); } catch (Exception ex) { throw new RuntimeException("Can't invoke getter for property: " + preload.getProperty(), ex); } }
![Page 173: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/173.jpg)
Preload Pattern nach Jürgen Kohl (4)
173Java Persistence API
// Fortsetzung GenericDAO
protected void preload(Object entity, Preload[] preloads) { if (entity instanceof Collection) { for (Object resultEntity : (Collection) entity) { preload(resultEntity, preloads); } } else { for (Preload preload : preloads) { if (preload.getModelClass().isInstance(entity)) { Object getterResult = invokeGetter(entity, preload); preload( getterResult, preloads); } }}
![Page 174: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/174.jpg)
Preload Pattern nach Adam Bien
Idee: Verwendung JXPath für die Initiatlisierung von Lazy Loading Beziehungen
Beispielklasse mit Lazy OneToOne Beziehung:
Aufruf der Getter-Methode mit JXPath:
174Java Persistence API
@Entitypublic class Master { ... @OneToOne(fetch=FetchType.LAZY) private Detail detail; ...}
JXPathContext.newContext(master).getValue("/detail");
![Page 175: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/175.jpg)
Batch
Problematik Sequenzielle Verarbeitung von grossen
Datenmengen Verwendung von Cursors mit JPA nicht möglich
Lösung Pagination
Vorsicht Persistence Context kann gross werden und
sollte regelmässig aufgeräumt werden (EntitManager.clear())
![Page 176: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/176.jpg)
Clustering
Zur Erhöhung der Verfügbarkeit und der Verbesserung der Performance werden Application Server häufig geclustert
Problem Persistence Context auf mehreren Knoten
vorhanden Synchronität mit Datenbank nicht gegeben
Lösung Synchronisation (Providerabhängig) Referesh der Entitäten bei Bedarf
![Page 177: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/177.jpg)
Advanced Topics
Objektrelationales Mapping mit JPA 2.0
![Page 178: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/178.jpg)
SQL Queries
EntityManager.createNativeQuery(String sql) EntityManager.createNativeQuery(String sql, Class
resultClass) Kann auch als NamedQuery definiert werden:
Ausführen des NamedQueries und Parameterübergabe:
178
@NamedNativeQuery( name = "employeeReporting", query = "SELECT * FROM emp WHERE id = ?", resultClass = Employee.class)
Query q = em.createNamedQuery("employeeReporting");q.setParameter(1, employeeId);q.getResultList()
![Page 179: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/179.jpg)
Result Set Mapping (1)
Definition
Verwendung
179
@SqlResultSetMapping(name = "employeeResult",entities = @EntityResult(entityClass = Employee.class)
Query q = em.createNativeQuery( "SELECT * FROM EMPLOYEE", "employeeResult");
![Page 180: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/180.jpg)
Result Set Mapping (2)
Mapping Foreign Keys Wenn die Foreign Keys im Resultat der Abfrage enthalten
sind, werden die einfachen Beziehungen ebenfalls mitgeführt
Multiple Result Mapping
SELECT e.*, a.* FROM emp e, address a WHERE e.adress_id = a.id
180
@SqlResultSetMapping(name = "EmployeeWithAddress",entities = {@EntityResult(entityClass = Employee.class), @EntityResult(entityClass = Address.class)}
![Page 181: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/181.jpg)
Result Set Mapping (3)
Mapping InheritanceSELECT id, name, start_date, daily_rate, term, vacation, hourly_rate, salary, pension, type FROM employee_stage
181
@SqlResultSetMapping( name="EmployeeStageMapping", entities= @EntityResult( entityClass=Employee.class, discriminatorColumn="TYPE", fields={ @FieldResult(name="startDate",column="START_DATE"), @FieldResult(name="dailyRate",column="DAILY_RATE"), @FieldResult(name="hourlyRate",column="HOURLY_RATE") } ) )
![Page 182: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/182.jpg)
Lifecycle Callbacks
Callbacks sind eine gängige Methode, um Einfluss auf den Lade- oder Speichervorgang von Objekten zu nehmen.
Mögliche Events:PrePersist, PostPersist, PreRemove, PostRemove, PreUpdate, PostUpdate, PostLoad
182
@Entitypublic class ImageMessage extends Message { @PrePersist @PreUpdate protected void compress(){ ... } @PostLoad @PostUpdate protected void uncompress() { ... }
![Page 183: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/183.jpg)
Entity Listeners
Wenn Sie dieselbe Funktionalität bei Callbacks von verschiedenen Entities verweden wollen, können Sie einen Entity Listener erstellen:
Entity Listener verwenden:
183
public class BaseEntityDebugListener { @PrePersist public void debugPrePersist(BaseEntity e) { log.debug("PrePresist: " + e); }}
@Entity@EntityListeners({BaseEntityDebugListener.class})public class Employee extends BaseEntity
![Page 184: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/184.jpg)
Vererbung und Lifecycle Events
1. Prüfen ob Default Listeners existieren
2. Höchste Ebene der Vererbung auf @EntityListeners Annotations prüfen
3. Wiederhole Schritt 2 für die nächst tiefere Ebene
4. Höchste Ebene der Vererbung auf Methoden mit zum Event passender Annotation prüfen
5. Wiederhole Schritt 4 für die nächst tiefere Ebene
184
![Page 185: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/185.jpg)
Sperrzeitpunkt
Daten werden in der Datenbank im Rahmen von SQL-Befehlen gesperrt.
Da Änderungen vorerst lokal durchgeführt und erst zum Commit-Zeitpunkt in die DB propagiert werden, findet das Sperren erst beim Commit statt.
Allfällige Wartesituationen, Deadlocks, Integritätsverletzungen treten effektiv erst zum Commit-Zeitpunkt auf.
185
![Page 186: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/186.jpg)
Optimistic Locking / Versionierung
Die Versionierung im Rahmen von JPA ist als optimistsches Locking zu verstehen. Mit der Versionierung kann ein Concurrency Control über Transaktionen hinweg realisiert werden.
Mit einer @Version können Lost Updates detektiert und vermieden werden:Das Feld kann int, Integer, short, Short, long, Long oder java.sql.Timestamp sein
186
@Entity public class Employee { @Version protected long version; ...
create table emp ( version bigint not null, ...
![Page 187: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/187.jpg)
Weitere Locking Strategien
Soll REPEATABLE_READ zur Anwendung kommen, kann Read Locking verwendet werden:
em.lock(LockModeType.READ)
Um eine Entität zum Schreiben zu sperren, wird Write Locking verwendet
em.lock(LockModeType.WRITE)
Die Verwendung von anderen Isolationlevels, muss über die JDBC Connection erfolgen
187
![Page 188: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/188.jpg)
Enhanced Locking (JPA 2.0)
JPA 2.0 führt neue Lockingstrategien ein: OPTIMISTIC ( = READ ) OPTIMISTIC_FORCE_INCREMENT ( = WRITE ) PESSIMISTIC_READ Repeatable Read PESSIMISTIC_WRITE Serialized PESSIMISTIC_FORCE_INCREMENT -> With
version field
Kombination Opitmistic/Pessimistic möglich! 188
![Page 189: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/189.jpg)
189
Enhanced Locking (JPA 2.0)
Example in EntityManager.refresh()
public void applyCharges() { Account acct = em.find(Account.class, acctId); // calculate charges, etc. int charge = … ; if (charge > 0) { em.refresh(acct, PESSIMISTIC_WRITE); double balance = acct.getBalance(); acct.setBalance(balance - charge); }}
![Page 190: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/190.jpg)
Schema Generation
Die Erzeugung von DDL kann, aber muss nicht durch eine Implementation der JPA Spezifikation angeboten werden.
In der JPA Spezifikation sind verschiedene Angaben (Annotations und Attribute davon) vorgesehen, welche die Erzeugung von DDL-Befehlen ermöglichen
190
public class Message { @Column (unique = false, nullable=false, columnDefinition="varchar", lenghth=64 ) public BigDecimal sender;
![Page 191: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/191.jpg)
191
XML Mapping
![Page 192: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/192.jpg)
The Metadata Puzzle
Reihenfolge bei der Verarbeitung der Metadaten:1. Annotations verarbeiten2. Klassen aus XML Mapping hinzufügen3. Attribute aus XML Mapping hinzufügen4. Defaultwerte setzen
192
![Page 193: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/193.jpg)
Das Mapping File
Rootelement is entity-mappings:
193
<?xml version="1.0" encoding="UTF-8"?><entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation= "http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
version="2.0">
![Page 194: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/194.jpg)
Defaults im Mapping File
Annotations ausschalten <xml-mapping-metadata-complete />
Persistence Unit Defaults schema catalog access cascade-persist entity-listeners
Diese können auch ausgeschaltet werden exclude-default-listeners @ExcludeDefaultListeners
194
![Page 195: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/195.jpg)
Defaults im Mapping File
Mapping File Defaults package schema catalog access
195
![Page 196: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/196.jpg)
Queries und Generators
sequence-generator
table-generator
named-query
named-native-query
sql-result-set-mapping
196
![Page 197: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/197.jpg)
Entity Mapping mit XML
197
<entity class="examples.model.Employee"><attributes> <id name="id"> <generated-value strategy="SEQUENCE" /> </id> <many-to-one name="department" /> <many-to-one name="manager" /> <one-to-many name="phones" mapped-by="employee" /> <one-to-many name="directs" mapped-by="manager" /> <one-to-one name="address" /> <many-to-many name="projects" mapped-by="employees" /></attributes></entity>
![Page 198: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/198.jpg)
198
Packaging and Deployment
![Page 199: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/199.jpg)
Configuring Persistence Units
Persistence Unit Name<persistence-unit name="EmployeeService" />
Transaction TypeRESOURCE_LOCAL oder JTA
Persistence Provider<provider>org.hibernate.ejb.HibernatePersistence</provider>
Data Source nur bei JTA
Mapping Files<mapping-file>META-INF/queries.xml</mapping-file>
199
![Page 200: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/200.jpg)
Managed Classes
Lokale Klassen Alle annotierten Klassen im Deployment Unit in welcher das persistence.xml gepackt ist
Klassen in Mapping FilesMit XML gemappte Klassen
Explicitly Listed ClassesIm persistence.xml eingetragene Klassen
Zusätzliche JARs mit Managed ClassesIm persistence.xml unter jar-file eingetragene JARs
200
![Page 201: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/201.jpg)
Properites zur Laufzeit übergeben
Die properties im persistence.xml können ebenfalls zur Laufzeit beim Erstellen der EntityManagerFactory übergeben werden:
201
Map props = new HashMap();props.put("toplink.jdbc.user", "emp");props.put("toplink.jdbc.password", "emp");EntityManagerFactory emf = Persistence .createEntityManagerFactory("EmployeeService", props);
![Page 202: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/202.jpg)
202
Tools
![Page 203: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/203.jpg)
IDE Integration
Eclipse Projekt DALI Oracle Enterprise Pack for Eclipse JBoss Tools
NetBeans IntelliJ IDEA
203
![Page 204: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/204.jpg)
Zusammenfassung / Ausblick
Objektrelationales Mapping mit JPA 2.0
![Page 205: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/205.jpg)
JPA 1.0 & 2.0
• JPA 1 is inzwischen mehr als 4 Jahre alt
• JPA 2 ist eine eigenständge Spezifikation, welche auf JPA 1 aufbaut und etliche zusätzliche Features bietet
– JSR 317, final release: 10.12.2009– EclipseLink ist die Referenzimplementation– JPA 2 Provider: EclipseLink 2.0, Hibernate 3.5,
OpenJPA 2.0, DataNucleus 2.1
![Page 206: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/206.jpg)
Zusammenfassung JPA 2.0 Features• Mixing field- and property-access in one Entity• Unidirectional one-to-many without join-table• Ordered lists with persistent order• Collections of basic and embeddable types• Orphan deletion for collections• Embeddables can be nested and have relationships• Improved support for maps• Pessimistic locking• Caching standardization• Improvements in JPQL (collection-valued expressions, polymorphism
…)• Criteria API• Metadata Model API• More standardized properties for configuration• Integration with Bean Validation (JSR-303)
![Page 207: Objektrelationales Mapping mit JPA 2.0](https://reader035.vdokument.com/reader035/viewer/2022062308/56813350550346895d9a5919/html5/thumbnails/207.jpg)
JPA 2.1 JSR 338
Support for the use of custom types and transformation methods in object/relational mapping.
Support for the use of "fetch groups" and/or "fetch plans" to provide further control over data that is fetched, detached, copied, and/or used in merging.
Support for the specification of immutable attributes and readonly entities.
More flexibility in the use of generated values; support for UUID generator type.
Support for multitenancy. Additional event listeners and callback methods; availability of
entity manager to callbacks. Improvements to the Java Persistence query language and criteria
APIs, including: support for stored procedures; support for additional built-in functions, and for the invocation of other database
and vendor functions;