JAVA PERSISTENCE API

Werbung
JAVA PERSISTENCE API
CAS Enterprise Application Development Java EE
Dieses Skript basiert auf:
Pro JPA 2: Mastering the Java Persistence API, Keith and Schincariol,
ISBN 978-1-4302-1956-9
Simon Martinelli, 03.2015
[email protected] | about.me/simas_ch
1
INHALT
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
INTRODUCTION
GETTING STARTED
ENTERPRISE APPLICATIONS (Æ EJB KURS)
OBJECTION-RELATIONAL MAPPING
COLLECTION MAPPING
ENTITY MANAGER
USING QUERIES
QUERY LANGUAGE
CRITERIA API
ADVANCED OBJECT-RELATIONAL MAPPING
ADVANCED TOPICS
XML MAPPING FILES
2
1 INTRODUCTION
3
DAS PROBLEM
4
GRUNDSÄTZE DES O/R MAPPINGS
• Objekte nicht Tabellen
Applikationen arbeiten grundsätzlich nur mit dem
Klassenmodell
• Richtig nutzen, nicht ignorieren
Um "gutes" O/R-Mapping zu betreiben, muss man sich
der Probleme bewusst sein und die relationale
Technologie kennen
• Unauffällig, nicht transparent
Persistenz ist nicht transparent. Die Applikation muss die
Kontrolle über den Objekt-Lifecycle haben
5
GRUNDSÄTZE DES O/R MAPPINGS
• Alte Daten, neue Objekte
Es ist sehr häufig, dass eine Applikation bestehende
Daten verwenden muss. Deshalb ist der Support für
Legacy Daten zentral.
• Ausreichend, aber nicht zuviel
Applikationen dürfen nicht durch ein schwergewichtiges
Persistenzmodell erdrückt werden
• Lokal und mobil
Entitäten müssen transportiert werden können
6
MODERNE PERSISTENZ APIS
• Arbeiten mit gewöhnlichen Java-Klassen für Daten
(POJOs)
• Objekte können transient oder persistent sein
• Innerhalb und ausserhalb von Applikationsservern
verwendbar
• Vererbung, Aggregation, Komposition abbildbar
• Transitive Persistenz oder Persistence by Reachability
• Lazy Loading
• Automatic Dirty Checking
• Datenbank-Roundtrips minimieren, Outer Join Fetching
• SQL-Generierung zur Laufzeit
7
TECHNOLOGIE STACK
8
Geschichte
9
API
Packages
• javax.persistence
• javax.persistence.spi
Classes
• Persistence
Interfaces
• EntityManagerFactory
• EntityManager
• EntityTransaction
• Query
Exceptions ( ~8 )
• RollbackException
Annotations ( ~64 )
• Entity
• Id
• OneToOne
• OneToMany
Enumerations ( ~10 )
• InheritanceType
• CascadeType
• FetchType
10
2 GETTING STARTED
11
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
12
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
CONVENTIONS OVER CONFIGURATION
13
ENTITY, BEISPIEL
@Entity
public class Employee {
@Id
protected int id;
protected String name;
protected long salary;
public Employee() {
}
public Employee(int id) {
this.id = id;
}
}
14
ENTITY MANAGER, ÜBERBLICK
15
ENTITY MANAGER, BEISPIEL
// ENTITYMANAGER ERSTELLEN
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("hr");
EntityManager em = emf.createEntityManager();
// ENTITY PERSISTIEREN
em.getTransaction().begin();
Employee emp = new Employee(158);
em.persist(emp);
em.getTransaction().commit();
// ENTITY FINDEN
Employee emp = em.find(Employee.class, 158);
16
ENTITY MANAGER, BEISPIEL
// ENTITY VERÄNDERN
em.getTransaction().begin();
emp.setSalary(emp.getSalary() + 1000);
em.getTransaction().commit();
// ENTITY LÖSCHEN
em.getTransaction().begin();
em.remove(emp);
em.getTransaction().commit();
// QUERIES
Query q = em.createQuery("SELECT e FROM Employee e");
Collection emps = q.getResultList();
17
PERSISTENCE UNIT, BEISPIEL
<!-- META-INF/persistence.xml -->
<persistence version="2.0" ...>
<persistence-unit name="hr" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>hr.Employee</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:derby://localhost:1527/test"/>
<property name="javax.persistence.jdbc.password" value="test"/>
<property name="javax.persistence.jdbc.driver"
value="org.apache.derby.jdbc.ClientDriver"/>
<property name="javax.persistence.jdbc.user" value="test"/>
<property name="eclipselink.ddl-generation“ value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
18
ÜBUNG: GETTING STARTED
1. Erstellen Sie eine neue Derby Datenbank
2. Erstellen Sie ein neues Projekt
3. Erstellen Sie eine Persistence Unit (METAINF/persistence.xml)
4. Erstellen Sie eine Klasse Employee
5. Machen Sie die Klasse zur Entity (@Entity, @Id)
6. Implementieren Sie den JUnit-Test um Employees
1.
2.
3.
4.
einzufügen
zu finden
zu verändern
zu löschen
19
20
4 OBJECT-RELATIONAL
MAPPING
21
ACCESS TYP
/* FUER DAS PERSISTENZ-FRAMEWORK EXISTIEREN
ZWEI ZUGRIFFSPUNKTE AUF DIE DATEN EINER KLASSE */
//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;
}
}
22
ACCESS TYP OPTIONS (JPA 2.0)
/* - VERSCHIEDENE ACCESS TYPES PRO KLASSE MÖGLICH
- MISCHEN VON ACCES TYPES IN EINER VERERBUNGSHIERARCHIE */
@Entity @Access(FIELD)
public class Vehicle {
...
@Transient double fuelEfficiency;
@Access(PROPERTY)
protected double getDbFuelEfficiency() {
return convertToImperial(fuelEfficiency);
}
...
}
23
MAPPING
• Es wird immer vom Defaultverhalten ausgegangen
• Das Defaultverhalten kann übersteuert werden
@Entity
@Table(name = "EMP")
public class Employee {
@Id
@Column(name = "EMP_ID")
private int id;
}
24
PERSISTENTE DATENTYPEN
• Erlaubt
• Alle primitiven Typen, String
• Alle Wrapperklassen (z.B. Integer, BigDecimal, Date,
Calendar)
• byte[], Byte[], char[], Character[]
• Enumerations
• Beliebige weitere Entity-Klassen
• Collections von Entities und Wrapperklassen und String,
welche als Collection<>, List<>, Set<> oder Map<>
deklariert sind
• Serialisierbare Klassen
25
JAVA / SQL TYPE MAPPING
• Implizit durch JDBC “Data Type Conversion Table“
definiert
• Explizit durch die @Column Annotation,
z.B.@Column(name = "sender")
protected String sender;
• Produktespezifisch durch JPA-Implementation oder
im JDBC-Driver für die jeweilige Datenbank
26
LARGE OBJECTS
// Speichern von Daten in BLOB oder CLOB
public class Employee {
@Lob // BLOB
private byte[] picture;
@Lob // CLOB
private char[] largeText;
...
}
27
ENUMERATIONS
/* Enumerations können persistiert werden. Entweder als
- Ordinalwert (position) oder
- Stringwert (Name der Konstante) */
// VARIANTE ORDINAL
@Enumerated(EnumType.ORDINAL)
private Color color;
// VARIANTE STRING
@Enumerated(EnumType.STRING)
private Color color;
/* VORSICHT BEI ÄNDERUNGEN AN DER ENUMERATION */
28
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
• TemporalType.DATE, TemporalType.TIME,
TemporalType.TIMESTAMP
@Temporal(TemporalType.DATE)
private Calendar dob;
29
TRANSIENTE ATTRIBUTE
• Attribute können von der Persistierung ausgeschlossen
werden
• Entweder mittels dem Schlüsselwort transient
transient private String translatedName;
• oder wenn das Attribut serialisiert werden soll
mittels Annotation
@Transient
private String translatedName;
30
ENTITY IDENTITY
DER 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, java.util.Date,
java.sql.Date
• Floating Point Typen sind ebenfalls erlaubt, aber sind
aufgrund der möglichen Rundungsfehler nicht zu
empfehlen
•
•
•
•
31
PRIMÄRSCHLÜSSEL
GENERIERUNG
• Primärschlüssel können in Zusammenarbeit mit der
Datenbank generiert werden.
• Strategien sind Identity, Table, Sequence und Auto
@Entity public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer id;
}
32
5 COLLECTION MAPPING
33
BEZIEHUNGEN
• Beziehungen zwischen Entities sind prinzipiell gegeben durch
entsprechende Referenzen oder Collection-Member in den
Entity-Klassen.
• Sie müssen jedoch deklariert werden, und sehr oft sind
Details zum O/R-Mapping und zum Verhalten notwendig.
• Folgende Beziehungs-Charakteristiken spielen eine Rolle:
• Unidirektional, bidirektional
• many-to-one, one-to-one, one-to-many, many-to-many
• Aggregation, Komposition
DER KORREKTE UNTERHALT DER BEZIEHUNGEN IST SACHE DER
APPLIKATION!
34
BEZIEHUNGEN - KONZEPTE
• Richtung
• Unidirektional
• Bidirektional
• Kardinalität
•
•
•
•
one-to-one
many-to-one
one-to-many
many-to-many
35
OWNING AND INVERSE SIDE
• In JPA spricht man von owning und inverse Side
• Die besitzende Seite ist verantwortlich für das
führen der Beziehung in der Datenbank (Foreign
Key)
• Die inversen Seite wird durch das mappedBy
Attribut gekennzeichnet
• Bei unidirektonalen Beziehungen fehlt die inverse
Seite
36
ONE-TO-ONE, UNIDIREKTIONAL
// K
Klasse
lass
la
sse
ss
e Employee
@
OneToOne
@OneToOne
private Address addr
res
ess;
s;
address;
// entspricht:
@OneToOne
private Address address;
37
MANY-TO-ONE, UNIDIREKTIONAL
// K
//
la
l
ass
s e Em
E
ploy
pl
o ee
ee
Klasse
Employee
@One
@O
neTo
ne
ToOn
To
One
On
@OneToOne
private Address address;
// entspricht:
@ManyToOne
private Department department;
38
ONE-TO-MANY, BIDIREKTIONAL
// Klasse Phone
@ManyToOne(optional = false)
private Employee employee;
// Klasse Employee
@OneToMany(mappedBy = "employee")
private Set<Phone> phones;
39
MANY-TO-MANY, BIDIREKTIONAL
// Klasse Employee
@ManyToMany(mappedBy = "employees")
private Set<Project> projects;
// Klasse Project
@ManyToMany
private Set<Employee> employees;
40
COLLECTIONS OF NON-ENTITES
AND EMBEDDABLES (JPA 2.0)
@Entity
public class Employee {
@ElementCollection
@Column(name="PHONE_NUMBER")
private List<String> phoneNumbers;
}
41
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;
42
PERSISTENT ORDERING (JPA 2.0)
/* DIE REIHENFOLGE EINER LISTE KANN PERSISTIERT WERDEN */
@Entity
public class Employee {
@OneToMany
@OrderColumn(name="PHONE_POS")
List<Phone> phones;
}
43
ENHANCED MAP SUPPORT
(JPA 2.0)
/* VERWENDUNG VON OBJECTS, EMBEDABBLES UND
ENTITIES ALS MAP KEY UND VALUE /*
@Entity
public class Vehicle {
@OneToMany
@MapKeyJoinColumn(name="PART_ID")
Map<Part, Supplier> suppliers;
}
44
LAZY 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.
@OneToMany(fetch = FetchType.EAGER)
private Set<Phone> phones;
45
ÜBUNG: BEZIEHUNGEN
• Erweitern Sie Ihr Projekt gemäss nachfolgendem
Klassenmodell
• Wählen Sie die ID Generierungsstrategie
• Definieren Sie die Beziehungstypen
• Definieren Sie die Beziehungsmappings
• Testen Sie Ihre Arbeit in dem Sie einen Employee
mit sämtlichen Beziehungen erstellen
46
KLASSENMODELL
47
48
6 ENTITY MANAGER
49
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
50
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
51
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 ACIDRegel
• Auf Objekte kann auch ausserhalb von Transaktionen
zugegriffen werden, jedoch ohne Konsistenz- und
Synchronisationsgarantie
52
ZUSTÄNDE UND ÜBERGÄNGE
53
Entity persistieren
/* MIT PERSIST() WIRD EINE NEUE ENTITY
VOM ENTITYMANAGER VERWALTET */
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);
/* DIE METHODE CONTAINS() KANN GEPRÜFT WERDEN OB
EINE ENTITY MANAGED IST */
if (em.contains(emp)) {
}
54
KASKADIERTE PERSISTENZ (1)
• Kaskadierte Persistenz heisst:
Alle von einem persistenten Objekt aus
erreichbaren Objekte sind ebenfalls persistent
Employee employee = new Employee();
em.persist(emp);
Address address = new Address();
employee.setAddress(address);
• Die Kaskadierung muss deklariert werden:
• PERSIST, MERGE, REMOVE, REFRESH
• ALL
55
KASKADIERTE PERSISTENZ (2)
/* DIE KASKADIERUNG KANN FÜR DAS ERSTELLEN
UND DAS LÖSCHEN DER PERSISTENZ SEPARAT
EINGESTELLT WERDEN */
public class Employee {
@OneToOne(cascade={CascadeType.PERSIST,
CascadeType.REMOVE})
private Address address;
}
56
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 (Orphan = Weisenkind) */
@OneToMany(cascade = CascadeType.ALL,
mappedBy = "customer",
orphanRemoval = true)
private Set<Order> orders;
57
ENTITY SUCHEN
• Mit find() kann eine Entity über ihren Primary Key
gefunden werden
• Die gefunden Entity 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
58
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.
59
OBJEKTZUSTAND NACH COMMIT
• Persistence Context EXTENDED
• Entity bleibt im Zustand managed
• Änderungen nach dem Commit werden berücksichtig
und im Rahmen der nächsten Transaktion in die
Datenbank übernommen
• Persistence Context TRANSACTION
• Objekt ist nach Commit im Zustand detached
• Änderungen müssen mit EntityManager.merge()
innerhalb der nächsten Transaktion dem EntityManager
übergeben werden
60
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
• Achtung! Inkonsistenzen!
Objekte mit Entity Manager neu laden
61
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
62
ÜBUNG: ENTITY MANAGER
• Definieren Sie die Kaskadierung auf den
Beziehungen im Modell
• Entfernen Sie die nicht mehr benötigten persist()
Aufrufe
• Definieren Sie das Ladverhalten (EAGER oder LAZY)
bei Ihren Beziehungen
• Schauen Sie sich im Debugger das Lazy Loading an
• Wiederholen Sie die Tests und achten Sie auf die
generierten SQL Statements in Bezug auf das
Ladeverhalten
63
64
7 USING QUERIES
65
QUERIES IN JPA
• JPA kennt drei Möglichkeiten um Abfragen zu
formulieren
• Java Persistence QL
• Unabhängig von der darunterliegenden Datenbank
• SQL Subset
• Abfragen basieren auf dem Klassenmodell, nicht auf dem
Datenmodell
• SQL
• Criteria API seit JPA 2.0
66
QUERIES DEFINIEREN
/* DYNAMISCHE QUERIES */
em.createQuery("SELECT e FROM Employee e");
/* NAMED QUERIES */
// Deklaration
@NamedQueries { @NamedQuery(name = "Employee.findAll",
query = "SELECT e FROM Employee e") }
public class Employee {...}
// Verwendung
Query q = em.createNamedQuery("Employee.findAll");
67
QUERY API
• Es stehen Query und TypedQuery<X> zu Verfügung
• Methoden zum Ausführen sind
• List getResultList() oder List<X> getResultList()
• Object getSingleResult() oder X getSingleResult()
• int executeUpdate()
• Als Rückgabewert wird die Anzahl betroffener Datensätze
zurückgeliefert
68
QUERIES AUSFÜHREN
TypedQuery<Employee> q =
em.createQuery("SELECT e FROM Employee e", Employee.class);
List<Employee> emps = q.getResultList();
for(Employee e : emps) {
...
}
69
EINFÜHRUNG (1)
• Einfachstes Query
SELECT e FROM Employee e
• Pfadausdrücke, Navigation mit .
SELECT e.name FROM Employee e
SELECT e.department FROM Employee e
• Resultate filtern
SELECT e FROM Employee e
WHERE e.department.name = 'NA42'
AND e.address.state in ('NY','CA')
• Projektion
SELECT e.name, e.salary FROM Employee e
70
EINFÜHRUNG (2)
• Join zwischen Entities
SELECT p.number
FROM Employee e, Phone p
WHERE e = p.employee
AND e.department.name = 'NA42'
AND p.type = 'Cell'
• Join mit JOIN Operator
SELECT p.number
FROM Employee e JOIN e.phones p
WHERE e.department.name = 'NA42'
AND p.type = 'Cell'
71
EINFÜHRUNG (3)
• Aggregatfunktionen
SELECT d, COUNT(e), MAX(e.salary),
AVG(e.salary)
FROM Department d JOIN d.employees e
GROUP BY d HAVING COUNT(e) >= 5
• Query Parameter
• Named
SELECT e FROM Employee e
WHERE e.department = :dept
AND e.salary > :base
• Positional
SELECT e FROM Employee e
WHERE e.department = ?1
AND e.salary > ?2
72
PARAMETERÜBERGABE
// Uebergabe eines Named Parameter
q.setParameter("dept", "NA42");
// Uebergabe eines Positional Parameter
q.setParameter(1, "NA42");
73
PFADAUSDRÜ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
74
QUERY RESULTATE VERARBEITEN
• Mögliche Typen im Resultat: Primitive Typen und String,
Entity Typen, Object[] und Benutzertypen durch
Constructor Expression
• Die List von getResultList() bzw. das Object aus
getSingleResult() enhält direkt diese Resulttypen
• Handelt es sich beim Resultat um eine Entity kommt
diese in den Zustand managed wenn das Query:
• innerhalb einer Transaktion ausgeführt wird
• ausserhalb einer Transaktion ausgeführt wird und der
Contexttyp EXTENDED ist.
• Wird ein Query ausserhalb einer Transaktion im Context
Type TRANSACTION ausgeführt, spricht man von einem
Read-only Query
75
MEHRERE RESULTAT TYPEN
/* BEI EINER PROJEKTION IN DER SELECT KLAUSEL WIRD
EINE LISTE VON OBJECT[]-ARRAY ZURÜCKGEGEBEN */
List<Object[]> result = em.createQuery(
"SELECT e.name, e.department.name " +
"FROM Project p JOIN p.employees e " +
"where p.name = "ZLD").getResultList();
for (Object[] values : result) {
System.out.println(values[0] + "," + values[1]);
}
76
CONSTRUCTOR EXPRESSION
DEKLARATION
/* MIT DER CONSTRUCTOR EXPRESSIONS EXISTIERT EINE EINFACHE
MÖGLICHKEIT UM RESULTATE AUF KLASSEN ZU MAPPEN. */
// Beispiel TransferObject
public class EmployeeTO {
private String employeeName;
private String deptName;
public EmployeeTO(String employeeName, String deptName) {
this.employeeName = employeeName;
this.deptName = deptName;
}
}
77
CONSTRUCTOR EXPRESSION
/* Query ausführen
ACHTUNG: KLASSE MUSS VOLLQUALIFIZIERT
ANGEGEBEN WERDEN! */
TypedQuery<EmployeeTO> q = em.createQuery(
"SELECT NEW jpa.util.EmployeeTO(e.name, e.department.name) " +
"FROM Project p JOIN p.employees e where p.name = "ZLD");
List<EmployeeTO> result = q.getResultList();
for (EmployeeTO emp : result) {ß
System.out.println(emp.employeeName + "," + emp.deptName);
}
78
PAGING UND SYNCHRONISATION
• Paging wird in Applikationen definiert, um die
Resultatmenge einzuschränken:
Query.setFirstResult(int pos)
Query.setMaxResults(int max)
• Synchronisation
Query.setFlushModeType(FlushModeType type)
• FlushModeType.AUTO
Ausstehende Änderungen werden ebenfalls in das
Resultat einbezogen
• FlushModeType.COMMIT
Nur comittete Daten werden zurückgegeben
79
BULK UPDATE UND DELETE
// BULK DELETE
Query q = em.createQuery("DELETE from Employee e");
int count = q.executeUpdate();
// BULK UPDATE
Query q = em.createQuery("UPDATE Employee e " +
"SET e.name = 'Simon' WHERE e.name = 'Peter');
int count = q.executeUpdate();
/* VORSICHT damit wird der Entity Manager umgangen!
Verwaltete Entities unbedingt aktualisieren!
Versionen müssen selber hochgezählt werden */
80
QUERY HINTS
/* MÖGLICHKEIT FÜR DEN HERSTELLER FÜR OPTIMIERUNGEN */
// Beispiel direkt beim Query
q.setHint("toplink.cache-usage", "DoNotCheckCache");
// Beispiel als Named Query
@NamedQuery(name = "findAll",
query = "SELECT e FROM Employee e",
hints = {@QueryHint(name = "toplink-cache-usage",
value = "DoNotCheckCache")})
public class Employee {
...
}
81
EMPFEHLUNGEN
• Verwenden Sie Named Queries
• Constructor Expression
• Werden die Daten nur zum Anzeigen z.B. für Statistiken
verwendet, brauchen diese nicht als Entites gelesen werden
• Verwenden Sie Query Hints zur Optimierung
• Bulk Update und Delete in isolierter Transaktion
verwenden und danach den Persistence Context
"aufräumen"
• Provider Unterschiede beachten
• Studieren Sie die generierten SQLs um ein Gefühl für Ihre JPA
Implementation zu erhalten
82
8 QUERY LANGUAGE
83
KLASSENMODELL
84
SELECT
SELECT <select_expression>
FROM <from_clause>
[WHERE <conditional_expression>]
[ORDER BY <order_by_clause>]
// Beispiel
SELECT e FROM Employee e
WHERE e.name = 'John Doe'
ORDER BY e.salary
85
FROM
Identifikationsvariable
FROM Employee e
SQL Joins werden automatisch erzeugt, wenn
- zwei oder mehr Range Variablen verwendet werden
FROM Employee e, Department d
- der JOIN Operator verwendet wird
FROM Employee e JOIN e.department d
- ein Pfad Ausdruck über eine Beziehung navigiert
SELECT e.department ...
86
JOINS
INNER JOINS
JPQL: SELECT p FROM Employee e JOIN e.phones p
SQL:
SELECT p.* FROM emp e, phone p WHERE e.id = p.emp_id
OUTER JOINS
JPQL: SELECT e, d FROM Employee e LEFT JOIN e.department d
SQL:
SELECT * FROM emp e, dept d WHERE e.dept_id = d.id (+)
FETCH JOINS
SELECT e FROM Employee e JOIN FETCH e.address
87
WHERE
INPUT PARAMETER
Named = :name
Positional = ?1
OPERATOREN PRÄZEDENZ
Navigations Operator .
Unäre Operatoren +/Multiplikation (*) und Division (/)
Addition (+) und Subtraktion (-)
Vergleichsoperatoren
=, >, >=, <, <=, [NOT] BETWEEN, [NOT] LIKE, [NOT] IN, IS
[NOT] NULL, IS [NOT] EMPTY, [NOT] MEMBER [OF]
Logische Operatoren (AND, OR, NOT)
88
BETWEEN
SELECT e
FROM Employee e
WHERE e.salary BETWEEN 40000 AND 45000
entspricht
SELECT e
FROM Employee e
WHERE e.salary >= 40000 AND e.salary <= 45000
89
IN
SELECT e
FROM Employee e
WHERE e.address.state IN ('NY', 'CA')
SELECT e
FROM Employee e
WHERE e.department IN
(SELECT DISTINCT d FROM Department d
JOIN d.employees de
JOIN de.projects p
WHERE p.name LIKE 'QA%')
90
COLLECTIONS IS EMPTY
/* IS EMPTY ist in Bezug auf Collections equivalent zu
IS NULL bei Feldern */
SELECT e FROM Employee e
WHERE e.directs IS NOT EMPTY
entspricht
SELECT m FROM Employee m
WHERE (SELECT COUNT(e) from Employee e
WHERE e.manager = m) > 0
91
COLLECTIONS MEMBER OF
/* MEMBER OF prüft ob das Objekt ein Element einer
Collection ist */
SELECT e FROM Employee e
WHERE :project MEMEBER OF e.projects
entspricht
SELECT e FROM Employee e
WHERE :project IN (SELECT p FROM e.projects p)
92
EXISTS
SELECT e
FROM Employee e
WHERE NOT EXISTS
(SELECT p
FROM e.phones p
WHERE p.type = 'Cell')
93
ANY, ALL und SOME
SELECT e
FROM Employee e
WHERE e.directs IS NOT EMPTY
AND
e.salary > ALL
(SELECT d.salary
FROM e.directs d)
94
FUNKTIONEN
ABS(number)
CONCAT(string1, string2)
CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
LENGTH(string)
LOCATE(string1, string2 [,start])
LOWER(string)
MOD(number1, number2)
SIZE(collection)
SQRT(number)
SUBSTRING(string, start, end)
UPPER(STRING)
TRIM
95
ORDER BY
// Einfache Sortierung
SELECT e FROM Employee e
ORDER BY e.name DESC
// Mehrfache Sortierung
SELECT e
FROM Employee e
ORDER BY e.name, e.salary DESC
/* Das beim ORDER BY verwendete Feld muss im SELECT enthalten
sein! Folgendes Query ist NICHT erlaubt: */
SELECT e.name
FROM Employee e
ORDER BY e.salary DESC
96
AGGREGAT QUERIES
SELECT <select_expression>
FROM <from_clause>
[WHERE <conditional_expression>]
[GROUP BY <group_by_clause>]
[HAVING <conditional_expression>]
[ORDER BY <order_by_clause>]
// Beispiel
SELECT AVG(e.salary)
FROM Employee e
97
AGGREGAT FUNKTIONEN
AVG
Durchschnitt der Gruppe
COUNT
Anzahl Werte in der Gruppe
MAX
Maximaler Wert in der Gruppe
MIN
Minimaler Wert in der Gruppe
SUM
Summe der Gruppe
98
GROUP BY
/* Definiert eine Gruppierung für die Aggregation der
Resultate /*
SELECT d.name, COUNT(e)
FROM Department d JOIN d.employee e
GROUP by d.name
/* Fehlt die GROUP BY Angabe, wird das ganze Query als Gruppe
verwendet */
SELECT COUNT(e)
FROM Department d JOIN d.employee e
99
HAVING
/* Definiert einen Filter, welcher nach der Gruppierung der
Resultate angewendet wird */
SELECT e, COUNT(p)
FROM Employee e JOIN e.projects p
GROUP BY e
HAVING COUNT(p) >= 2
100
UPDATE
UPDATE <entity_name> [[AS] <identification_variable>]
SET <update_statement> {, <update_statement>}*
[WHERE <conditional_expression>]
// Beispiel
UPDATE Employee e
SET e.salary = 60000
WHERE e.salary = 55000
101
DELETE
DELETE FROM <entity_name> [[AS] <identification_variable>]
[WHERE <condition>]
// Beispiel
DELETE FROM Employee e
WHERE e.department IS NULL
102
JPQL ERWEITERUNGEN IN JPA 2.0
// Timestamp
SELECT t from BankTransaction t
WHERE t.txTime > {ts ‘2008-06-01 10:00:01.0’}
// Non-polymorphic Queries
SELECT e FROM Employee e
WHERE TYPE(e) = FullTimeEmployee OR e.wage = "SALARY"
// Collection Parameters in IN Expression
SELECT emp FROM Employee emp
WHERE emp.project.id IN [:projectIds]
103
JPQL ERWEITERUNGEN IN JPA 2.0
// Ordered List Index
SELECT t FROM CreditCard c JOIN c.transactionHistory t
WHERE INDEX(t) BETWEEN 0 AND 9
CASE Statement
UPDATE Employee e SET e.salary =
CASE
e.rating WHEN 1 THEN e.salary * 1.1
WHEN 2 THEN
e.salary * 1.05
ELSE
e.salary * 1.01
END
104
ÜBUNG: QUERY LANGUAGE
• Erstellen Sie JUnit-Tests, um die Möglichkeiten der
Query Language auszuprobieren
• Abfragen von Objekten mit Bedingungen / Sortierung
• Aggregatfunktionen
• Gibt es Abfragen, die Schwierigkeiten bereiten, aber
in SQL grundsätzlich möglich wären?
• Verwenden Sie Named Queries
105
106
9 CRITERIA API
http://www.ibm.com/developerworks/library/j-typesafejpa/
107
MOTIVATION
• Vor JPQL hatten die meisten OR-Mapper bereits
eine objektorientierte Abfragesprache
• Mit JPA 2.0 wurden diese APIs in der Criteria API
standardisiert
• Im Gegensatz zu JPQL können mit der Criteria API
Abfragen mit Java programmiert werden, welche
vom Compiler geprüft werden
108
EINFACHES QUERY
SELECT e FROM Employee e WHERE e.name = 'John Smith';
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Employee> cq =
cb.createQuery(Employee.class);
Root<Employee> employee = cq.from(Employee.class);
cq.select(employee)
.where(cb.equal(emp.getName("name"), "John Smith";
109
PROJEKTION
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object> cq =
cb.createQuery(Object.class);
Root<Employee> employee = cq.from(Employee.class);
cq.multiselect(employee.get("id"));
// entspricht JPQL
SELECT e.id FROM Employee e
110
VORTEILE DER CRITERIA API
• Gerade bei dynamischen Queries (z.B. bei
Suchformularen) ist das Zusammensetzen eines
JPQL Queries als String eine mühselige und
fehleranfällige Tätigkeit
• Dank des Java API der Criteria API ist dies mit der
Criteria API einfacher
111
NACHTEILE DER CRITERIA API
• Die Criteria API scheint etwas "over designed"
• Dadurch ist der Einstieg schwieriger als bei JPQL
• Und die Lesbarkeit der Abfragen leidet
• Die Criteria API alleine reicht für eine vollständige
Typsicherheit noch nicht aus
112
METAMODEL API
• Aufgrund der Mappings kann JPA eine Metamodel
generieren
• Dieses Metamodel kann in den Abfragen verwendet
werden und erhöht die Typsicherheit
• Der Name der Metamodell Klassen wird aus dem
Entity Namen und dem Suffix _ gebildet
• Employee Æ Employee_
• Die Generierung übernimmt der Persistence
Provider z.B. mit einem Annotation Processor
113
GENERIERTES METAMODEL
@Generated(value="EclipseLink-2.5.0.v20130507-rNA",
date="2013-11-05T10:51:00")
@StaticMetamodel(Employee.class)
public class Employee_ {
public static volatile
SingularAttribute<Employee, Long> id;
}
114
METAMODEL VERWENDUNG
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Employee> cq =
cb.createQuery(Employee.class);
Root<Employee> employee = cq.from(Employee.class);
cq.select(employee)
.where(cb.equal(Employee_.name), "John Smith";
115
116
10 ADVANCED
OBJECT-RELATIONAL
MAPPING
117
EMBEDDED OBJECTS
• entspricht Komposition
• Eingebettete Objekte haben
keine eigene Identität
• Mutterobjekt und
eingebettetes Objekt
sind in derselben Tabelle
abgelegt
118
EMBEDDED OBJECTS, BEISPIEL
@Embeddable
public class Address {
private String street;
private String city;
private String state;
private String zip;
}
@Entity
public class Employee {
@Id private int id;
private String name;
private long salary;
@Embedded private Address address;
}
119
ENHANCED EMBEDDABLES
(JPA 2.0)
/* Verschachtelung von Embeddables und Embeddables
mit Beziehungen */
@Embeddable
public class Assembly {
...
@Embedded
ShippingDetail shipDetails;
@ManyToOne
Supplier supplier;
...
}
120
ZUSAMMENGESETZTE
PRIMÄRSCHLÜSSEL
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;
}
121
COMPOSITE PRIMARY KEY WITH
RELATIONSHIPS (JPA 2.0)
@Entity @IdClass(PartPK.class)
public class Part {
@Id int partNo;
@Id @ManyToOne
Supplier supplier;
}
public class PartPK {
int partNo;
int supplier;
}
122
READ-ONLY MAPPINGS UND
OPTIONAL
/* Read-Only */
@Column(insertable = false, updateable = false)
/* Es ist nicht möglich eine ganze Entity als
read-only zu deklarieren */
/* Optional */
@ManyToOne(optional = true) // Default
123
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. */
@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
124
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
125
SINGLE_TABLE
@Entity @Inheritance public abstract class Project
@Entity public class DesignProject extends Project
@Entity public class QualityProject extends Project
126
JOINED
@Entity @Inheritance(strategy=InheritanceType.JOINED)
public abstract class Project
@Entity public class DesignProject extends Project
@Entity public class QualityProject extends Project
127
TABLE_PER_CLASS (Optional)
@Entity @Inheritance(strategy=TABLE_PER_CLASS)
public abstract class Project
@Entity public class DesignProject extends Project
@Entity public class QualityProject extends Project
128
MAPPED_SUPERCLASS
@MappedSuperclass
public abstract class BaseEntity {
@Id @GeneratedValue
protected Integer id;
protected Integer version;
protected Timestamp createdAt;
protected String createdFrom;
protected Timestamp updatedAt;
protected String updatedFrom;
}
@Entity
public class Phone extends BaseEntity {
}
129
ÜBUNG: ADVANCED ORM
• Probieren Sie die verschiedenen
Vererbungsmappings bei Project aus.
• Achtung! Generierte Tabellen beim Wechsel löschen
• Erstellen Sie ein Klasse BaseEntity für alle Entities
und verwenden Sie für diese MAPPED_SUPERCLASS.
• Probieren Sie die Java Persistence Query Language
in Bezug auf die Vererbung aus
130
KLASSENMODELL
131
132
11 ADVANCED TOPICS
133
SQL QUERIES
EntityManager.createNativeQuery(String sql)
EntityManager.createNativeQuery(String sql,
Class resultClass)
// Kann auch als NamedQuery definiert werden
@NamedNativeQuery(
name = "employeeReporting",
query = "SELECT * FROM emp WHERE id = ?",
resultClass = Employee.class)
// Ausführen des NamedQueries und Parameterübergabe
Query q = em.createNamedQuery("employeeReporting");
q.setParameter(1, employeeId);
List<Employee> list = q.getResultList();
134
RESULT SET MAPPING
// Definition
@SqlResultSetMapping(
name = "employeeResult",
entities = @EntityResult(entityClass = Employee.class)
// Verwendung
Query q = em.createNativeQuery(
"SELECT * FROM EMPLOYEE", "employeeResult");
/* Mapping Foreign Keys
Wenn die Foreign Keys im Resultat der Abfrage enthalten sind,
werden die einfachen Beziehungen ebenfalls mitgeführt */
135
MULITPLE RESULT MAPPING
SELECT e.*, a.* FROM emp e, address a
WHERE e.adress_id = a.id
@SqlResultSetMapping(
name = "EmployeeWithAddress",
entities = {@EntityResult(entityClass = Employee.class),
@EntityResult(entityClass = Address.class)}
136
MAPPING INHERITANCE
SELECT id, name, start_date, daily_rate, term, vacation,
hourly_rate, salary, pension, type FROM employee_stage
@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")
}))
137
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
•
•
•
•
•
•
@Entity
public class ImageMessage extends Message {
@PrePersist @PreUpdate
protected void compress(){ ... }
@PostLoad @PostUpdate
protected void uncompress() { ... }
138
Entity Listeners
/* Wenn Sie dieselbe Funktionalität bei Callbacks von
verschiedenen Entities verweden wollen, können Sie einen
Entity Listener erstellen: /*
public class BaseEntityDebugListener {
@PrePersist
public void debugPrePersist(BaseEntity e) {
log.debug("PrePresist: " + e);
}
}
// Entity Listener verwenden:
@Entity
@EntityListeners({BaseEntityDebugListener.class})
public class Employee extends BaseEntity
139
VERERBUNG UND
LIFECYCLE EVENTS
• Prüfen ob Default Listeners existieren
• Höchste Ebene der Vererbung auf @EntityListeners
Annotations prüfen
• Wiederhole Schritt 2 für die nächst tiefere Ebene
• Höchste Ebene der Vererbung auf Methoden mit
zum Event passender Annotation prüfen
• Wiederhole Schritt 4 für die nächst tiefere Ebene
140
ENTITY ZUSTAND REFRESH
• Sind Sie nicht sicher, ob der Zustand Ihrer Entität mit
dem Zustand in der Datenbank übereinstimmt, kann
mit der Methode refresh() im EntityManager das
Entity erneut geladen werden
• Ist das zu aktualisierende Entity nicht im Zustand
managed wird eine IllegalArgumentException
geworfen
141
FRAGEN ZUM
TRANSAKTIONSMANAGEMENT
• Ist der Objektzustand nach dem Lesen durch die
Applikation in der Datenbank eingefroren, während
dem die Transaktion läuft (mit welchem
Isolationsgrad wird gearbeitet)?
• Ein Objekt wird geändert: Zu welchem Zeitpunkt
wird es in der Datenbank gesperrt?
• Kann entdeckt werden, ob Daten beim Commit in
der Zwischenzeit von anderen Prozessen geändert
wurden auf der DB?
142
LOST UPDATE PROBLEM
143
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
144
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 vom Typ int, Integer, short, Short, long,
Long oder java.sql.Timestamp sein
@Entity public class Employee {
@Version protected long version;
}
145
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
verwendetem.lock(LockModeType.WRITE)
146
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
• Kombination Opitmistic/Pessimistic möglich!
147
ENHANCED LOCKING (JPA 2.0)
// Beispiel mit 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);
}
}
148
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
public class Message {
@Column(unique = false, nullable=false,
columnDefinition="varchar", lenghth=64 )
public BigDecimal sender;
149
ÜBUNG: ADVANCED TOPICS
• Verwenden Sie SQL
• Erweiteren Sie die BaseEntity um die Attribute
createdAt und updatedAt und verwenden Sie
Lifecycle Callbacks, um diese Attribute vor dem
Insert und Update entsprechend abzufüllen
• Erweitern Sie Ihre BaseEntity mit Optimistic Locking
und testen Sie das Verhalten
• Erweitern Sie ihr Mapping an beliebiger Stelle mit
Angaben zur Schema Generierung (@Column)
150
12 XML MAPPING
151
THE METADATA PUZZLE
• Reihenfolge bei der Verarbeitung der Metadaten:
• Annotations verarbeiten
• Klassen aus XML Mapping hinzufügen
• Attribute aus XML Mapping hinzufügen
• Defaultwerte setzen
152
DAS MAPPING FILE
<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">
...
</entity-mappings>
153
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
154
QUERIES UND GENERATORS
sequence-generator
table-generator
named-query
named-native-query
sql-result-set-mapping
155
ENTITY MAPPING MIT XML
<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>
156
ÜBUNG: XML MAPPING
• Verwenden Sie für einen Teil ihres Models XML für
das Mapping
• Lagern Sie ihre Named Queries in XML aus
• Erstellen Sie eine globalen EntityListener um
Veränderungen an den Daten zu loggen
157
158
13 PACKAGING AND
DEPLOYMENT
159
CONFIGURING
PERSISTENCE UNITS
• Persistence Unit Name
<persistence-unit name="EmployeeService" />
• Transaction Type
RESOURCE_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>
160
MANAGED CLASSES
• Lokale Klassen
Alle annotierten Klassen im Deployment Unit in
welcher das persistence.xml gepackt ist
• Klassen in Mapping Files
Mit XML gemappte Klassen
• Explicitly Listed Classes
Im persistence.xml eingetragene Klassen
• Zusätzliche JARs mit Managed Classes
Im persistence.xml unter jar-file eingetragene JARs
161
PROPERITES ZUR LAUFZEIT
ÜBERGEBEN
/* Die Properties im persistence.xml können
ebenfalls zur Laufzeit beim Erstellen der
EntityManagerFactory übergeben werden */
Map props = new HashMap();
props.put("javax.persistence.jdbc.user", "emp");
props.put("javax.persistence.jdbc.password", "emp");
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(
"EmployeeService", props);
162
JPA 2.1
163
WHAT‘S NEW?
• Converters - allowing custom code conversions between database and
object types
• Criteria Update/Delete - allows bulk updates and deletes through the
Criteria API
• Stored Procedures - allows queries to be defined for database stored
procedures
• ConstructorResult support for SQLResultSetMapping
• Runtime creation of named queries
• Injectable EntityListeners
• Unsynchronized persistence contexts
• DDL generation - automatic table, index and schema generation.
• Entity Graphs - allow partial or specified fetching or merging of objects.
• JPQL/Criteria enhancements - arithmetic sub-queries, generic database
functions, join ON clause, TREAT option.
164
VARIOUS
165
JSR 303: BEAN VALIDATION
• Validierung und gewisse Elemente der DDL
Generierung werden mit JSR 303 ersetzt
• @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
166
VERSCHIEDENES
• 2nd Level Cache Mechanismen
• Standardisierung von häufig gebrauchen Properties
im persistence.xml
•
•
•
•
javax.persistence.jdbc.driver
javax.persistence.jdbc.url
javax.persistence.jdbc.user
javax.persistence.jdbc.password
• Bootstraping im Java SE Umfeld mittels
ServiceLoader (ab Java 1.6)
167
REFERENZEN UND LINKS
• Pro JPA 2:
Mastering the Java Persistence API
Mike Keith and Merrick Schincariol
ISBN-13: 978-1-4302-1956-9
• JSR 317: Java Persistence 2.0
www.jcp.org/en/jsr/detail?id=317
• EclipseLink (Reference implementation)
www.eclipse.org/eclipselink
168
Herunterladen