Your SlideShare is downloading. ×
0
Optimierung von JPA-Anwendungen
Dirk Weil, GEDOPLAN GmbH
Dirk Weil
GEDOPLAN GmbH, Bielefeld
Java EE seit 1998
Konzeption und
Realisierung
Vorträge
Seminare
Veröffentlichungen
Opti...
Optimierung von JPA-Anwendungen
Laufzeit
Memory
Providerunabhängig
EclipseLink
Hibernate
…
Optimierung von JPA-Anwendungen...
Id-Generierung
Entity-Klassen müssen Id haben
PK in der DB
Feld oder
Property
mit @Id
Empfehlenswert: Technische Id
Proble...
Id-Generierung
JPA-Feature: @GeneratedValue
Nutzt DB-Sequenzen,
Identity Columns oder
Sequenz-Tabellen
Probleme:
Id erst n...
Id-Generierung
Alternative: BYO-ID (selbst machen, i. a. im Konstruktor)
Id auch in transitiven Objekten gesetzt
Insert oh...
Id-Generierung
@GeneratedValue signifikant langsamer
(OOTB)
Derby
EclipseLink
MySQL
EclipseLink
Oracle
EclipseLink
Derby
H...
Id-Generierung
Tuning: Höhere Allocation Size
Leider nicht verfügbar bei IDENTITY
@Id
@GeneratedValue(strategy = Generatio...
Id-Generierung
0
10.000
20.000
30.000
40.000
50.000
60.000
70.000
80.000
1 10 100 1000
Laufzeit vs. Allocation Size
Optimi...
Relationship Loading
Relationen werden durch Felder mit @OneToOne, …,
@ManyToMany repräsentiert
@Entity
public class Book
...
Relationship Loading
Relationen-Parameter: fetch
Referenzierte Entities direkt laden?
EAGER: Direkt
LAZY: Später bei Bedar...
Relationship Loading
Bsp.: Auftragsposition bearbeiten
Ist Owner der n:1-Relation zu Artikel
Kunde Auftrag
Auftrags
Positi...
Relationship Loading
Annahme:
Verwendet nur
AuftragsPosition
AuftragsPosition aufPos
= em.find(AuftragsPosition.class, id)...
Relationship Loading
Annahme:
Verwendet auch
Artikel
AuftragsPosition aufPos
= em.find(AuftragsPosition.class, id);
Artike...
Relationship Loading
Bsp.: Kunde bearbeiten
Ist Owner der 1:n-Relation zu Auftrag
Kunde Auftrag
Auftrags
Position
ArtikelL...
Relationship Loading
Annahme:
Verwendet
nur Kunde
Kunde kunde
= em.find(Kunde.class, id);…
select …
from Kunde
where …
sel...
Relationship Loading
Messergebnis
(1000 Interationen, Hibernate, MySQL)
EAGER LAZY
Nur AuftragsPosition 2.967 ms 2.505 ms ...
Relationship Loading
Fazit:
Zugriffsverhalten genau analysieren
Default ist schon recht gut
Besser: Immer LAZY verwenden u...
Relationship Loading
Fetch Joins mit JPQL
leider nur einstufig erlaubt
select ap from Auftragsposition ap
left join fetch ...
Relationship Loading
Fetch Joins mit Criteria Query
CriteriaQuery<Auftrag> cQuery
= builder.createQuery(Auftrag.class);
Ro...
Fetch Tuning
ToMany-Fetching: "N+1"-Problem
z.B. Lesen der User inkl. Groups + Permissions
SELECT ... FROM USER
SELECT ......
Fetch Tuning
Lösungsansatz 1: Join Fetching
erzeugt 1 (!) SELECT
Achtung: Volumen!
CriteriaBuilder criteriaBuilder = entit...
Fetch Tuning
Lösungsansatz 2: Batch Fetching
erzeugt 1 SELECT pro 'Ebene'
@ManyToMany(fetch = FetchType.LAZY, …)
@BatchFet...
Basic Attribute Loading
Fetch-Strategie auch für einfache Werte wählbar
Lazy Loading sinnvoll bei
selten genutzten Werten
...
Basic Attribute Loading
Messergebnis
Lesen von Kunden
10 'ungenutzte' Strings à 150 chars
1000 Interationen, EclipseLink, ...
Lazy-Load-Verfahren
Proxy
@OneToMany
private Set<Auftrag> auftraege
get(…)
?
DB
Optimierung von JPA-Anwendungen 26
Lazy-Load-Verfahren
Instrumentierung
@Basic(fetch = FetchType.LAZY)
private String longAdditionalInfo;
get(…)
?
DB
Optimie...
Bytecode-Instrumentierung
 = Standard
 = Providerspezifische Konfiguration erforderlich
Eclipselink
Verfahren SE EE
@Bas...
JPA Provider
Caching
EntityManager
DB
2nd
Level
Cache
1st
Level
Cache
Query
Cache
Optimierung von JPA-Anwendungen 29
First Level Cache
Standard
Je EntityManager
Enthält in Sitzung geladene Objekte
Achtung: Speicherbedarf!
ggf. explizit ent...
First Level Cache
Arbeitet
sitzungs-
bezogen
// Kunden mit bestimmter Id laden
EntityManager em1 = emf.createEntityManager...
First Level Cache
HashMap-Semantik
benötigt Key
wird für Queries nicht benutzt
// Kunden mit bestimmter Id laden
EntityMan...
Query Cache
Provider-spezifisch
Speichert Result Set IDs zu Queries
TypedQuery<Kunde> query
= em.createQuery("select k fro...
Query Cache
Trotz mehrfacher Query
nur ein DB-Zugriff
while (…)
{
TypedQuery<Kunde> query
= em.createQuery("select k from ...
Query Cache
EclipseLink
Hibernate:
(Aktivierung in der Konfiguration notwendig)
TypedQuery<Kunde> query = em.createQuery(…...
Second Level Cache
JPA 2.0 unterstützt 2nd Level Cache
nur rudimentäre Konfiguration
Providerspezifische
Konfiguration
in ...
Second Level Cache
Providerspezifische Implementierung
Cache-Provider
Infinispan, EHCache, OSCache, …
Cache-Strategien
rea...
Second Level Cache
Wirkt applikationsweit
Semantik ähnlich HashMap
Ladereihenfolge:
1st Level Cache (EntityManager)
2nd Le...
Second Level Cache
Vorteil bei häufig genutzten Daten
Konstanten
selten veränderte Daten
nur von dieser Anwendung veränder...
Second Level Cache
Bsp.: Stammdaten-Entity Land
wird n:1 von Kunde
referenziert
nur wenige Land-Werte
Länder ändern sich n...
Second Level Cache
Konfiguration lt. Spec
<persistence-unit name="…">
<provider>…</provider>
<shared-cache-mode>ENABLE_SEL...
Second Level Cache
EclipseLink
Default: DISABLE_SELECTIVE
Hibernate bis Version 3.x
ignoriert Standard-Konfig
benötigt eig...
Second Level Cache
Messergebnis
(1000 Interationen, EclipseLink, Oracle)
ohne 2nd Level Cache: 10.883 ms
mit 2nd Level Cac...
Paginierung
Queries mit großer Ergebnismenge
'häppchenweise' verarbeiten
TypedQuery<Artikel> query
= em.createQuery("selec...
Paginierung
Eingeschränkt oder effektlos bei 1:n/m:n-Relationen mit:
Eager Loading
Fetch Joins
Join erzeugt kartesisches P...
Inheritance
Mehrere Abbildungen denkbar:
Alles in einer Tabelle
Eine Tabelle pro Klasse
Eine Tabelle pro konkreter Klasse
...
Inheritance
SINGLE_TABLE
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class Vehicle
{
…
Opt...
Inheritance
JOINED
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Vehicle
{
…
Optimierung von...
Inheritance
TABLE_PER_CLASS
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Vehicle
{...
Inheritance
Laufzeitvergleich für Queries
auf Basisklasse
auf abgeleitete Klasse
(1000 Iterationen, Ergebnis ca. 100 Eintr...
Inheritance
Optimale Performanz liefern
SINGLE_TABLE und TABLE_PER_CLASS
Aber: Auch andere Implikationen
Genaue Analyse no...
Providerabhängiges
Lazy-Varianten
Cache-Strategien
Prepared Statement Cache
Change Detection
DB Dialects
…
Optimierung von...
Fazit
Viele Optimierungen providerunabhängig möglich
Wesentlich:
Lazy Loading
Caching
Genaue Analyse notwendig
Messen
Kein...
More
Seminare zum Thema, z. B.
Java Persistence API (JPA)
Power Workshop Java EE 6/7
http://ips-it-schulungen.de/Kurse/Jav...
Upcoming SlideShare
Loading in...5
×

Optimierung von JPA-Anwendungen

90

Published on

War Persistenz in Java EE früher schwergewichtig und unflexibel, so steht nun der leichtgewichtige Standard JPA mit Providern wie EclipseLink und Hibernate zur Verfügung. Die Einfachheit ist bestechend, verleitet aber auch zu unbedachtem Einsatz mit teilweise enttäuschender Performanz. Dieser Vortrag zeigt, wie JPA-Anwendungen auf den nötigen Durchsatz hin optimiert werden können.

Sie hätten diesen Vortrag gerne in Ihrem Hause? Sprechen Sie uns an: dirk.weil(at)gedoplan.de

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
90
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Optimierung von JPA-Anwendungen"

  1. 1. Optimierung von JPA-Anwendungen Dirk Weil, GEDOPLAN GmbH
  2. 2. Dirk Weil GEDOPLAN GmbH, Bielefeld Java EE seit 1998 Konzeption und Realisierung Vorträge Seminare Veröffentlichungen Optimierung von JPA-Anwendungen 2
  3. 3. Optimierung von JPA-Anwendungen Laufzeit Memory Providerunabhängig EclipseLink Hibernate … Optimierung von JPA-Anwendungen 3
  4. 4. Id-Generierung Entity-Klassen müssen Id haben PK in der DB Feld oder Property mit @Id Empfehlenswert: Technische Id Problem: Erzeugung eindeutiger Werte @Entity public class SomeEntity { @Id private int id; … Optimierung von JPA-Anwendungen 4
  5. 5. Id-Generierung JPA-Feature: @GeneratedValue Nutzt DB-Sequenzen, Identity Columns oder Sequenz-Tabellen Probleme: Id erst nach persist gesetzt  equals?, hashCode? Id-Übernahme kostet Zeit @Id @GeneratedValue private int id; Optimierung von JPA-Anwendungen 5
  6. 6. Id-Generierung Alternative: BYO-ID (selbst machen, i. a. im Konstruktor) Id auch in transitiven Objekten gesetzt Insert ohne Zusatzaufwand Achtung: i. A. nicht trivial Z. B.: UUID @Id private String id = new com.eaio.uuid.UUID().toString(); Optimierung von JPA-Anwendungen 6
  7. 7. Id-Generierung @GeneratedValue signifikant langsamer (OOTB) Derby EclipseLink MySQL EclipseLink Oracle EclipseLink Derby Hibernate MySQL Hibernate Oracle Hibernate BYO-ID 19.864 11.659 22.478 19.240 9.684 7.126 AUTO 21.034 13.537 23.663 74.804 12.214 70.814 0 10.000 20.000 30.000 40.000 50.000 60.000 70.000 80.000 Millisekunden Insert 50.000 einfache Entries in 1.000er Batches Optimierung von JPA-Anwendungen 7
  8. 8. Id-Generierung Tuning: Höhere Allocation Size Leider nicht verfügbar bei IDENTITY @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ArtikelIdGenerator") @SequenceGenerator(name = "ArtikelIdGenerator", allocationSize = 1000) private int id;@Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "ArtikelIdGenerator") @TableGenerator(name = "ArtikelIdGenerator", allocationSize = 1000) private int id; Optimierung von JPA-Anwendungen 8
  9. 9. Id-Generierung 0 10.000 20.000 30.000 40.000 50.000 60.000 70.000 80.000 1 10 100 1000 Laufzeit vs. Allocation Size Optimierung von JPA-Anwendungen 9
  10. 10. Relationship Loading Relationen werden durch Felder mit @OneToOne, …, @ManyToMany repräsentiert @Entity public class Book { @ManyToOne public Publisher publisher; @Entity public class Publisher { @OneToMany(mappedBy="publisher") public List<Book> books; Optimierung von JPA-Anwendungen 10
  11. 11. Relationship Loading Relationen-Parameter: fetch Referenzierte Entities direkt laden? EAGER: Direkt LAZY: Später bei Bedarf @ManyToOne(fetch = FetchType.LAZY) private Artikel artikel; Optimierung von JPA-Anwendungen 11
  12. 12. Relationship Loading Bsp.: Auftragsposition bearbeiten Ist Owner der n:1-Relation zu Artikel Kunde Auftrag Auftrags Position ArtikelLand 1 * 1 * * 1 1* @Entity public class AuftragsPosition { @ManyToOne private Artikel artikel; Optimierung von JPA-Anwendungen 12
  13. 13. Relationship Loading Annahme: Verwendet nur AuftragsPosition AuftragsPosition aufPos = em.find(AuftragsPosition.class, id); … select … from AuftragsPosition where … select … from AuftragsPosition left outer join Artikel where … @ManyToOne private Artikel artikel; @ManyToOne(fetch=FetchType.LAZY) private Artikel artikel; Optimierung von JPA-Anwendungen 13
  14. 14. Relationship Loading Annahme: Verwendet auch Artikel AuftragsPosition aufPos = em.find(AuftragsPosition.class, id); Artikel artikel = aufPos.getArtikel(); … select … from AuftragsPosition where … select … from Artikel where … select … from AuftragsPosition left outer join Artikel where … @ManyToOne private Artikel artikel; @ManyToOne(fetch=FetchType.LAZY) private Artikel artikel; Optimierung von JPA-Anwendungen 14
  15. 15. Relationship Loading Bsp.: Kunde bearbeiten Ist Owner der 1:n-Relation zu Auftrag Kunde Auftrag Auftrags Position ArtikelLand 1 * 1 * * 1 1* @Entity public class Kunde { @OneToMany(mappedBy="kunde") private Set<Auftrag> auftraege; Optimierung von JPA-Anwendungen 15
  16. 16. Relationship Loading Annahme: Verwendet nur Kunde Kunde kunde = em.find(Kunde.class, id);… select … from Kunde where … select … from Kunde left outer join Auftrag left outer join AuftragsPosition where … @ManyToOne(fetch=FetchType.EAGER) private Set<Auftrag> auftraege; @ManyToOne private Set<Auftrag> auftraege; Optimierung von JPA-Anwendungen 16
  17. 17. Relationship Loading Messergebnis (1000 Interationen, Hibernate, MySQL) EAGER LAZY Nur AuftragsPosition 2.967 ms 2.505 ms - 15 % Auch Artikel 2.959 ms 4.305 ms + 45 % Nur Kunde 30.295 ms 4.848 ms - 84 % = Default-Einstellung Optimierung von JPA-Anwendungen 17
  18. 18. Relationship Loading Fazit: Zugriffsverhalten genau analysieren Default ist schon recht gut Besser: Immer LAZY verwenden und bei Bedarf nachladen providerspezifische Mittel left join fetch Load/Fetch Graph (ab JPA 2.1) Optimierung von JPA-Anwendungen 18
  19. 19. Relationship Loading Fetch Joins mit JPQL leider nur einstufig erlaubt select ap from Auftragsposition ap left join fetch ap.artikel ... Optimierung von JPA-Anwendungen 19
  20. 20. Relationship Loading Fetch Joins mit Criteria Query CriteriaQuery<Auftrag> cQuery = builder.createQuery(Auftrag.class); Root<Auftrag> a = cQuery.from(Auftrag.class); a.fetch(Auftrag_.auftragsPositionen) .fetch(AuftragsPosition_.artikel); … Optimierung von JPA-Anwendungen 20
  21. 21. Fetch Tuning ToMany-Fetching: "N+1"-Problem z.B. Lesen der User inkl. Groups + Permissions SELECT ... FROM USER SELECT ... FROM USER_GROUP t0, GROUP t1 WHERE t0.USER_ID=? AND … SELECT ... FROM PERMISSION WHERE GROUP_ID=? SELECT ... FROM PERMISSION WHERE GROUP_ID=? SELECT ... FROM USER_GROUP t0, GROUP t1 WHERE t0.USER_ID=? AND … SELECT ... FROM USER_GROUP t0, GROUP t1 WHERE t0.USER_ID=? AND … Optimierung von JPA-Anwendungen 21
  22. 22. Fetch Tuning Lösungsansatz 1: Join Fetching erzeugt 1 (!) SELECT Achtung: Volumen! CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class); Root<User> u = criteriaQuery.from(User.class); u.fetch(User_.groups, JoinType.LEFT).fetch(Group_.permissions, JoinType.LEFT); criteriaQuery.select(u).distinct(true); List<User> users = entityManager.createQuery(criteriaQuery).getResultList(); Optimierung von JPA-Anwendungen 22
  23. 23. Fetch Tuning Lösungsansatz 2: Batch Fetching erzeugt 1 SELECT pro 'Ebene' @ManyToMany(fetch = FetchType.LAZY, …) @BatchFetch(value = BatchFetchType.IN, size = 10) private Set<Group> groups; Annotation Relationsauflösung EclipseLink @BatchFetch IN, EXISTS, JOIN Hibernate @BatchSize IN, EXISTS OpenJPA @EagerFetchMode (nur für EAGER!) JOIN (='PARALLEL') Optimierung von JPA-Anwendungen 23
  24. 24. Basic Attribute Loading Fetch-Strategie auch für einfache Werte wählbar Lazy Loading sinnvoll bei selten genutzten Werten umfangreichen Daten @Basic(fetch = FetchType.LAZY) private String longAdditionalInfo; Optimierung von JPA-Anwendungen 24
  25. 25. Basic Attribute Loading Messergebnis Lesen von Kunden 10 'ungenutzte' Strings à 150 chars 1000 Interationen, EclipseLink, Oracle EAGER LAZY 7.204 ms 6.820 ms -5 % = Default-Einstellung Optimierung von JPA-Anwendungen 25
  26. 26. Lazy-Load-Verfahren Proxy @OneToMany private Set<Auftrag> auftraege get(…) ? DB Optimierung von JPA-Anwendungen 26
  27. 27. Lazy-Load-Verfahren Instrumentierung @Basic(fetch = FetchType.LAZY) private String longAdditionalInfo; get(…) ? DB Optimierung von JPA-Anwendungen 27
  28. 28. Bytecode-Instrumentierung  = Standard  = Providerspezifische Konfiguration erforderlich Eclipselink Verfahren SE EE @Basic Entity Instrumentation   @xxxToOne Entity Instrumentation   @xxxToMany Collection Proxy   Hibernate Verfahren SE EE @Basic Entity Instrumentation   @xxxToOne Attribute Proxy   @xxxToMany Collection Proxy   Optimierung von JPA-Anwendungen 28
  29. 29. JPA Provider Caching EntityManager DB 2nd Level Cache 1st Level Cache Query Cache Optimierung von JPA-Anwendungen 29
  30. 30. First Level Cache Standard Je EntityManager Enthält in Sitzung geladene Objekte Achtung: Speicherbedarf! ggf. explizit entlasten (clear, detach) EntityManager 1st Level Cache Optimierung von JPA-Anwendungen 30
  31. 31. First Level Cache Arbeitet sitzungs- bezogen // Kunden mit bestimmter Id laden EntityManager em1 = emf.createEntityManager(); Kunde k1 = em1.find(Kunde.class, id); // Gleichen Kunden in 2. Session verändern EntityManager em2 = emf.createEntityManager(); em2.getTransaction().begin(); Kunde k2 = em2.find(Kunde.class, id); k2.setName("…"); em2.getTransaction().commit(); // Gleichen Kunden in 1. Session erneut laden Kunde k3 = em1.find(Kunde.class, id); // ist unverändert! Optimierung von JPA-Anwendungen 31
  32. 32. First Level Cache HashMap-Semantik benötigt Key wird für Queries nicht benutzt // Kunden mit bestimmter Id laden EntityManager em = emf.createEntityManager(); Kunde k1 = em.find(Kunde.class, id); // Query nach gleichem Kunden geht erneut zur DB! Kunde k2 = em.createQuery("select k from Kunde k " + "where k.id=:id", Kunde.class) .setParameter("id", id) .getSingleResult(); Optimierung von JPA-Anwendungen 32
  33. 33. Query Cache Provider-spezifisch Speichert Result Set IDs zu Queries TypedQuery<Kunde> query = em.createQuery("select k from Kunde k where k.name=:name", Kunde.class); query.setParameter("name", "OPQ GbR"); … // Query Cache einschalten Kunde kunde = query.getSingleResult(); ["select k from Kunde k where k.name=:name", "OPQ GbR"]  [id1] Optimierung von JPA-Anwendungen 33
  34. 34. Query Cache Trotz mehrfacher Query nur ein DB-Zugriff while (…) { TypedQuery<Kunde> query = em.createQuery("select k from Kunde k where k.name=:name", Kunde.class); query.setParameter("name", "OPQ GbR"); query.setHint(…) // Query Cache einschalten (providerabh.!) Kunde kunde = query.getSingleResult(); … } Optimierung von JPA-Anwendungen 34
  35. 35. Query Cache EclipseLink Hibernate: (Aktivierung in der Konfiguration notwendig) TypedQuery<Kunde> query = em.createQuery(…); query.setHint("org.hibernate.cacheable", true); … TypedQuery<Kunde> query = em.createQuery(…); query.setHint("eclipselink.cache-usage", "CheckCacheThenDatabase"); … Optimierung von JPA-Anwendungen 35
  36. 36. Second Level Cache JPA 2.0 unterstützt 2nd Level Cache nur rudimentäre Konfiguration Providerspezifische Konfiguration in der Praxis unabdingbar JPA Provider EntityManager 2nd Level Cache 1st Level Cache Optimierung von JPA-Anwendungen 36
  37. 37. Second Level Cache Providerspezifische Implementierung Cache-Provider Infinispan, EHCache, OSCache, … Cache-Strategien read-only, read-write, … Storage Memory, Disk, Cluster, … Optimierung von JPA-Anwendungen 37
  38. 38. Second Level Cache Wirkt applikationsweit Semantik ähnlich HashMap Ladereihenfolge: 1st Level Cache (EntityManager) 2nd Level Cache, falls enabled DB Optimierung von JPA-Anwendungen 38
  39. 39. Second Level Cache Vorteil bei häufig genutzten Daten Konstanten selten veränderte Daten nur von dieser Anwendung veränderte Daten Optimierung von JPA-Anwendungen 39
  40. 40. Second Level Cache Bsp.: Stammdaten-Entity Land wird n:1 von Kunde referenziert nur wenige Land-Werte Länder ändern sich nahezu nie Länder können dauerhaft im Cache verbleiben Kunde Land 1 * Optimierung von JPA-Anwendungen 40
  41. 41. Second Level Cache Konfiguration lt. Spec <persistence-unit name="…"> <provider>…</provider> <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> … Cache aktiv für … ALL alle Entities NONE keine Klasse ENABLE_SELECTIVE nur @Cacheable(true) DISABLE_SELECTIVE alle außer @Cacheable(false) @Entity @Cacheable(true) public class Land { … Optimierung von JPA-Anwendungen 41
  42. 42. Second Level Cache EclipseLink Default: DISABLE_SELECTIVE Hibernate bis Version 3.x ignoriert Standard-Konfig benötigt eigene Annotation @Entity @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) public class Land { … Optimierung von JPA-Anwendungen 42
  43. 43. Second Level Cache Messergebnis (1000 Interationen, EclipseLink, Oracle) ohne 2nd Level Cache: 10.883 ms mit 2nd Level Cache für Land: 6.549 ms Optimierung von JPA-Anwendungen 43
  44. 44. Paginierung Queries mit großer Ergebnismenge 'häppchenweise' verarbeiten TypedQuery<Artikel> query = em.createQuery("select a from Artikel a", Artikel.class); query.setFirstResult(50); query.setMaxResults(10); List<Artikel> result = query.getResultList(); select … from Artikel where … and rownum>=50 and rownum<60 Optimierung von JPA-Anwendungen 44
  45. 45. Paginierung Eingeschränkt oder effektlos bei 1:n/m:n-Relationen mit: Eager Loading Fetch Joins Join erzeugt kartesisches Produkt Providerabhängige Lösung: Ausführung im Memory Ausführung mehrerer SQL-Befehle Optimierung von JPA-Anwendungen 45
  46. 46. Inheritance Mehrere Abbildungen denkbar: Alles in einer Tabelle Eine Tabelle pro Klasse Eine Tabelle pro konkreter Klasse Strategie-Auswahl mit @Inheritance <abstract> Vehicle Car Ship Optimierung von JPA-Anwendungen 46
  47. 47. Inheritance SINGLE_TABLE @Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) public abstract class Vehicle { … Optimierung von JPA-Anwendungen 47
  48. 48. Inheritance JOINED @Entity @Inheritance(strategy=InheritanceType.JOINED) public abstract class Vehicle { … Optimierung von JPA-Anwendungen 48
  49. 49. Inheritance TABLE_PER_CLASS @Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public abstract class Vehicle { … Optimierung von JPA-Anwendungen 49
  50. 50. Inheritance Laufzeitvergleich für Queries auf Basisklasse auf abgeleitete Klasse (1000 Iterationen, Ergebnis ca. 100 Einträge, Hibernate, MySQL) SINGLE_ TABLE TABLE_ PER_CLASS JOINED Basisklasse 2.705 ms 29.359 ms 3.434 ms Subklasse 2.505 ms 1.435 ms 3.377 ms Optimierung von JPA-Anwendungen 50
  51. 51. Inheritance Optimale Performanz liefern SINGLE_TABLE und TABLE_PER_CLASS Aber: Auch andere Implikationen Genaue Analyse notwendig Optimierung von JPA-Anwendungen 51
  52. 52. Providerabhängiges Lazy-Varianten Cache-Strategien Prepared Statement Cache Change Detection DB Dialects … Optimierung von JPA-Anwendungen 52
  53. 53. Fazit Viele Optimierungen providerunabhängig möglich Wesentlich: Lazy Loading Caching Genaue Analyse notwendig Messen Kein Selbstzweck Optimierung von JPA-Anwendungen 53
  54. 54. More Seminare zum Thema, z. B. Java Persistence API (JPA) Power Workshop Java EE 6/7 http://ips-it-schulungen.de/Kurse/Java http://javaeeblog.wordpress.com/ http://expertenkreisjava.blogspot.de/  dirk.weil@gedoplan.de @dirkweil dirk.weil@gedoplan.deOptimierung von JPA-Anwendungen 54
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×