Kursscript

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, 11.2013
[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("jpa.emp.2008");
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="jpa-testPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<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
4 OBJECT-RELATIONAL
MAPPING
20
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;
}
}
21
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);
}
...
}
22
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;
}
23
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
• JPA 1.0: Collections von etwas anderem als Entities,
also z.B. Wrapperklassen und andere serialiserbare Typen.
24
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
25
LARGE OBJECTS
public class Employee {
@Lob
private byte[] picture;
...
}
26
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 */
27
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;
28
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;
29
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
•
•
•
•
30
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;
}
31
5 COLLECTION MAPPING
32
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!
33
BEZIEHUNGEN - KONZEPTE
• Richtung
• Unidirektional
• Bidirektional
• Kardinalität
•
•
•
•
one-to-one
many-to-one
one-to-many
many-to-many
34
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 gekenntzeichnet
• Bei unidirektonalen Beziehungen fehlt die inverse
Seite
35
ONE-TO-ONE, UNIDIREKTIONAL
// K
Klasse
lass
la
sse
ss
e Employee
@OneToOne
@OneToOne
res
ess;
s;
private Address addr
address;
// entspricht:
@OneToOne
@JoinColumn(name="address_id", referencedColumnName = "id")
private Address address;
36
MANY-TO-ONE, UNIDIREKTIONAL
lass
la
ass
s e Em
E
p oy
pl
o e
ee
e
// K
Klasse
Employee
@One
@O
neTo
ne
ToOn
To
One
On
@OneToOne
private Address address;
// entspricht:
@OneToOne
@JoinColumn(name="address_id", referencedColumnName = "id")
private Address address;
37
ONE-TO-MANY, BIDIREKTIONAL
// Klasse Phone
@ManyToOne(optional = false)
private Employee employee;
// Klasse Employee
@OneToMany(mappedBy = "employee")
private Collection<Phone> phones;
38
MANY-TO-MANY, BIDIREKTIONAL
// Klasse Employee
@ManyToMany(mappedBy = "employees")
private Collection<Project> projects;
// Klasse Project
@ManyToMany
private Collection<Employee> employees;
39
COLLECTIONS OF NON-ENTITES
AND EMBEDDABLES (JPA 2.0)
@Entity
public class Employee {
@ElementCollection
@Column(name="PHONE_NUMBER")
private List<String> phoneNumbers;
}
40
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;
41
PERSISTENT ORDERING (JPA 2.0)
/* DIE REIHENFOLGE EINER LISTE KANN PERSISTIERT WERDEN */
@Entity
public class Employee {
@OneToMany
@OrderColumn(name="PHONE_POS")
List<Phone> phones;
}
42
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;
}
43
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;
44
Ü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
45
KLASSENMODELL
46
6 ENTITY MANAGER
47
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
48
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
49
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
50
ZUSTÄNDE UND ÜBERGÄNGE
52
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)) {
}
53
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
54
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;
}
55
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;
56
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
57
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.
58
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
59
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
60
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
61
Ü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
62
7 USING QUERIES
63
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
64
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
65
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'
66
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
67
PARAMETERÜBERGABE
// Uebergabe eines Named Parameter
q.setParameter("dept", "NA42");
// Uebergabe eines Positional Parameter
q.setParameter(1, "NA42");
68
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
69
QUERIES DEFINIEREN
/* DYNAMISCHE QUERIES */
em.createQuery("SELECT e FROM Employee e");
/* NAMED QUERIES */
// Deklaration
@NamedQuery(name = "Employee.findAll",
query = "SELECT e FROM Employee e")
public class Employee {...}
// Verwendung
Query q = em.createNamedQuery("Employee.findAll");
70
QUERIES AUSFÜHREN
/* ABHOLEN DES RESULTATES MIT METHODEN VON QUERY */
List getResultList()
Object getSingleResult()
int executeUpdate()
// Beispiel
Query q = em.createQuery("SELECT e FROM Employee e");
List<Employee> emps = q.getResultList();
for(Employee e : emps) {
...
}
71
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
Contexttyp TRANSACTION ausgeführt, spricht man von
einem Read-only Query
72
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]);
}
73
CONSTRUCTOR EXPRESSION
/* MIT DER CONSTRUCTOR EXPRESSIONS EXISTIERT EINE EINFACHE MÖGLICHKEIT UM
RESULTATE AUF KLASSEN ZU MAPPEN.
ACHTUNG: KLASSE MUSS VOLLQUALIFIZIERT
ANGEGEBEN WERDEN! */
// Beispiel TransferObject
public class EmployeeTO {
public EmployeeTO(String employeeName, String deptName) {...}
}
// Query ausführen
List result = em.createQuery(
"SELECT NEW jpa.util.EmployeeTO(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);
}
74
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
75
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*/
76
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 {
...
}
77
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
78
8 QUERY LANGUAGE
79
KLASSENMODELL
80
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
81
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 ...
82
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
83
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)
84
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
85
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%')
86
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
87
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)
88
EXISTS
SELECT e
FROM Employee e
WHERE NOT EXISTS
(SELECT p
FROM e.phones p
WHERE p.type = 'Cell')
89
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)
90
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
91
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
92
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
93
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
94
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
95
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
96
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
97
DELETE
DELETE FROM <entity_name> [[AS] <identification_variable>]
[WHERE <condition>]
// Beispiel
DELETE FROM Employee e
WHERE e.department IS NULL
98
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]
99
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
100
Ü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
101
9 CRITERIA API
102
EINFACHES QUERY
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Employee> cq =
cb.createQuery(Employee.class);
Root<Employee> employee = cq.from(Employee.class);
cq.select(employee);
// entspricht JPQL
SELECT e FROM Employee e;
103
PARAMETER
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Employee> cq =
cb.createQuery(Employee.class);
Root<Employee> employee = cq.from(Employee.class);
cq.select(employee);
Parameter<Integer> param =
cb.parameter(Integer.class, "id");
cq.where(cb.equal(employee.get("id"), param));
// entspricht JPQL
SELECT e FROM Employee e WHERE e.id = :id
104
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
105
METAMODEL API
@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;
}
106
METAMODEL API
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object> cq =
cb.createQuery(Object.class);
Root<Employee> employee = cq.from(Employee.class);
cq.multiselect(employee.get(Employee_.id));
// entspricht JPQL
SELECT e.id FROM Employee e
107
10 ADVANCED
OBJECT-RELATIONAL
MAPPING
108
EMBEDDED OBJECTS
• entspricht Komposition
• Eingebettete Objekte haben
keine eigene Identität
• Mutterobjekt und
eingebettetes Objekt
sind in derselben Tabelle
abgelegt
109
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;
}
110
ENHANCED EMBEDDABLES
(JPA 2.0)
/* Verschachtelung von Embeddables und Embeddables
mit Beziehungen */
@Embeddable
public class Assembly {
...
@Embedded
ShippingDetail shipDetails;
@ManyToOne
Supplier supplier;
...
}
111
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;
}
112
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;
}
113
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
114
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
115
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
116
SINGLE_TABLE
@Entity @Inheritance public abstract class Project
@Entity public class DesignProject extends Project
@Entity public class QualityProject extends Project
117
JOINED
@Entity @Inheritance(strategy=InheritanceType.JOINED)
public abstract class Project
@Entity public class DesignProject extends Project
@Entity public class QualityProject extends Project
118
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
119
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 {
}
120
Ü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
121
KLASSENMODELL
122
11 ADVANCED TOPICS
123
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();
124
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 */
125
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)}
126
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")
}))
127
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() { ... }
128
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
129
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
130
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
131
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?
132
LOST UPDATE PROBLEM
133
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
134
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;
}
135
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)
136
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!
137
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);
}
}
138
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;
139
Ü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)
140
12 XML MAPPING
141
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
142
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>
143
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
144
QUERIES UND GENERATORS
sequence-generator
table-generator
named-query
named-native-query
sql-result-set-mapping
145
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>
146
Ü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
147
13 PACKAGING AND
DEPLOYMENT
148
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>
149
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
150
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);
151
VARIOUS
152
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
153
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)
154
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
155
Herunterladen