SlideShare una empresa de Scribd logo
1 de 51
Descargar para leer sin conexión
Dirk Weil | GEDOPLAN GmbH 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Dirk Weil 
•GEDOPLAN GmbH, Bielefeld 
•Java EE seit 1998 
•Konzeption und Realisierung 
•Seminare 
•Vorträge 
•Veröffentlichungen 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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; 
… 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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; 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Id-Generierung 
•Alternative: BYO-ID (selbst machen) 
–Id auch in transitiven Objekten gesetzt 
–Insert ohne Zusatzaufwand 
–Achtung: i. A. nicht trivial 
–Z. B.: UUID 
this.id = UUID.randomUUID().toString(); // oder: new com.eaio.uuid.UUID().toString() 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Id-Generierung 
•@GeneratedValue langsamer (OOTB) 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Id-Generierung 
•Tuning: Höhere Allocation Size 
@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; 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Id-Generierung 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Relationship Loading 
•Relationen werden durch Attribute mit @…To… repräsentiert 
@Entity public class Book { @ManyToOne public Publisher publisher; 
@Entity 
public class Publisher 
{ 
@OneToMany(mappedBy="publisher") 
public List<Book> books; 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Relationship Loading 
•Relationen-Parameter: fetch 
•Referenzierte Entities direkt laden? 
–EAGER: Direkt 
–LAZY: Später bei Bedarf 
@ManyToOne(fetch = FetchType.LAZY) private Artikel artikel; 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Relationship Loading 
•Bsp.: Auftragsposition bearbeiten 
–n:1-Relation zu Artikel 
Kunde 
Auftrag 
Auftrags Position 
Artikel 
Land 
1 
* 
1 
* 
* 
1 
1 
* 
@Entity 
public class AuftragsPosition 
{ 
@ManyToOne 
private Artikel artikel; 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Relationship Loading 
•Annahme: Verwendet nur AuftragsPosition 
AuftragsPosition aufPos = em.find(AuftragsPosition.class, id); 
… 
select … from AuftragsPosition where … 
@ManyToOne 
private Artikel artikel; 
@ManyToOne(fetch=FetchType.LAZY) 
private Artikel artikel; 
select … from AuftragsPosition where … select … from Artikel where … 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Relationship Loading 
•Annahme: Verwendet auch Artikel 
AuftragsPosition aufPos = em.find(AuftragsPosition.class, id); … 
Artikel artikel = aufPos.getArtikel(); 
… 
@ManyToOne private Artikel artikel; 
@ManyToOne(fetch=FetchType.LAZY) 
private Artikel artikel; 
select … from AuftragsPosition where … select … from Artikel where … 
select from AuftragsPosition where … … 
select … from Artikel where … 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Relationship Loading 
•Messergebnis (1000 Items, Hibernate, MySQL) 
EAGER 
LAZY 
AuftragsPosition ohne Artikel 
2.967 ms 
2.505 ms 
- 15 % 
AuftragsPosition mit Artikel 
2.959 ms 
4.305 ms 
+ 45 % 
Kunde ohne Auftrag 
30.295 ms 
4.848 ms 
- 84 % 
= Default 
Kunde 
Auftrag 
Auftrags Position 
Artikel 
Land 
1 
* 
1 
* 
* 
1 
1 
* 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Relationship Loading 
•Fazit: 
–Zugriffsverhalten genau analysieren 
–Default ist schon recht gut 
–Besser: Immer LAZY verwenden und bei Bedarf Fetch Joins oder Entity Graphs nutzen 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Relationship Loading 
•Fetch Joins 
–mit JPQL 
–Achtung: Kartesisches Produkt! 
select ap from Auftragsposition ap left join fetch ap.artikel ... 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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, JoinType.LEFT) .fetch(AuftragsPosition_.artikel, JoinType.LEFT); … 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Relationship Loading 
•Entity Graphs 
TBD 
@Entity @NamedEntityGraph( name = "Kunde.auftraege", attributeNodes = @NamedAttributeNode(value = "auftraege"))) public class Kunde { @OneToMany(mappedBy="kunde") private Set<Auftrag> auftraege; 
TypedQuery<Kunde> query = entityManager.createQuery(…); 
EntityGraph<?> entityGraph = entityManager.getEntityGraph("Kunde.auftraege"); 
query.setHint("javax.persistence.loadgraph", entityGraph); 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Fetch Tuning 
•ToMany-Fetching: "N+1"-Problem 
–z.B. Lesen einiger User inkl. Groups + Permissions 
SELECT ... FROM USER 
SELECT ... FROM GROUP WHERE USER_ID=? 
SELECT ... FROM PERMISSION WHERE GROUP_ID=? 
SELECT ... FROM PERMISSION WHERE GROUP_ID=? 
SELECT ... FROM GROUP WHERE USER_ID=? 
SELECT ... FROM GROUP WHERE USER_ID=? 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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(); 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Fetch Tuning 
•Lösungsansatz 2: Batch Fetching 
@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 
SELECT ... FROM USER 
SELECT ... FROM GROUP WHERE USER_ID IN (?,?,…) 
SELECT ... FROM PERMISSION WHERE GROUP_ID IN (?,?,…) 
SELECT ... FROM PERMISSION WHERE GROUP_ID IN (?,?,…) 
SELECT ... FROM GROUP WHERE USER_ID IN (?,?,…) 
N+1 (N/B)+1 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Basic Attribute Loading 
•Fetch-Strategie auch für einfache Werte wählbar 
•Lazy Loading ggf. sinnvoll bei 
–selten genutzten Werten 
–umfangreichen Daten 
@Basic(fetch = FetchType.LAZY) 
private String longAdditionalInfo; 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Basic Attribute Loading 
•Messergebnis 
–Lesen von Kunden 
–10 'ungenutzte' Strings à 150 chars 
–1000 Interationen, Hibernate, MySQL 
EAGER 
LAZY 
6.782 ms 
6.440 ms 
-5 % 
= Default-Einstellung 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Tupel-Selects 
•Selektion einzelner Attribute 
–als Tupel 
–mit Constructor Expression 
•Messergebnis (ms für 10000 Items) 
select k.id, k.name from Kunde k 
select new IdAndName(k.id, k.name) from Kunde k 
Entity komplett 
Object[] 
Ctor Expression 
11.211 ms 
3.890 ms 
4.010 ms 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Query-Parameter 
–JPQL Injection 
–Prepared Statement Reuse 
em.createQuery("select k from Kunde k " + "where k.name='" + someString + "'") 
em.createQuery("select k from Kunde k " + "where k.name=:name") 
.setParameter("name", someString) 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Caching 
JPA Provider 
EntityManager 
DB 
2nd Level Cache 
1st Level Cache 
Query Cache 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
First Level Cache 
•Standard 
•Je EntityManager 
•Enthält in Sitzung geladene Objekte 
–Achtung: Speicherbedarf! 
–sinnvolle EM-Lebensdauer nutzen 
–flush/clear ist i. A. Antipattern! 
•ausser im Batch – dort häufig sinnvoll 
EntityManager 
1st Level Cache 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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! 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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(); 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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] 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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(); … } 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Query Cache 
•EclipseLink: 
•Hibernate: 
TypedQuery<Kunde> query = em.createQuery(…); query.setHint("org.hibernate.cacheable", true); … 
TypedQuery<Kunde> query = em.createQuery(…); query.setHint("eclipselink.cache-usage", "CheckCacheThenDatabase"); … 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Second Level Cache 
•JPA 2.x unterstützt 2nd Level Cache 
–nur rudimentäre Konfiguration 
–Providerspezifische Konfiguration in der Praxis unabdingbar 
JPA Provider 
EntityManager 
2nd Level Cache 
1st Level Cache 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Second Level Cache 
•Providerspezifische Implementierung 
–Cache-Provider Infinispan, EHCache, OSCache, … 
–Cache-Strategien read-only, read-write, … 
–Storage Memory, Disk, Cluster, … 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Second Level Cache 
•Wirkt applikationsweit 
•Semantik ähnlich HashMap 
•Ladereihenfolge: 
–1st Level Cache (EntityManager) 
–2nd Level Cache, falls enabled 
–DB 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Second Level Cache 
•Vorteil bei häufig genutzten Daten 
–Konstanten 
–selten veränderte Daten 
–nur von dieser Anwendung veränderte Daten 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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 
* 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Second Level Cache 
•Konfiguration lt. Spec 
<persistence-unit name="…"> 
<provider>…</provider> 
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> 
… 
Cache aktiv für … 
Default bei … 
ALL 
alle Entities 
NONE 
keine Klasse 
Hibernate 
ENABLE_SELECTIVE 
nur @Cacheable(true) 
DISABLE_SELECTIVE 
alle außer @Cacheable(false) 
EclipseLink 
@Entity 
@Cacheable(true) 
public class Land 
{ 
… 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Second Level Cache 
•Messergebnis (1000 Interationen, Hibernate, MySQL) ohne L2C: 8.975 ms mit L2C für Land: 5.401 ms 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Second Level Cache 
•L2C für Anwendungscode transparent 
•find liefert Kopie des Cache-Eintrags 
•Für komplett konstante Werte kann ein weiterer Cache in der Anwendung sinnvoll sein 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Inheritance 
•SINGLE_TABLE 
@Entity 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
public abstract class Vehicle 
{ 
… 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Inheritance 
•JOINED 
@Entity 
@Inheritance(strategy=InheritanceType.JOINED) 
public abstract class Vehicle 
{ 
… 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Inheritance 
•TABLE_PER_CLASS 
@Entity 
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) 
public abstract class Vehicle 
{ 
… 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
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 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Inheritance 
•Optimale Performanz liefern SINGLE_TABLE und TABLE_PER_CLASS 
•Aber: Auch andere Implikationen 
•Genaue Analyse notwendig 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Wenn‘s dennoch nicht reicht 
•Native Queries 
•Stored Procedure Queries 
•User Functions 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
Fazit 
•Viele Optimierungen providerunabhängig möglich 
•Wesentlich: 
–Lazy Loading 
–Caching 
•Genaue Analyse notwendig 
•Messen 
•Kein Selbstzweck 
Speeding up Java Persistence
Dirk Weil | GEDOPLAN GmbH 
More 
•http://www.gedoplan-it-training.de Seminare in Berlin, Bielefeld, Inhouse 
•http://www.gedoplan-it-consulting.de Reviews, Coaching, … 
•http://javaeeblog.wordpress.com/ 
•http://expertenkreisjava.blogspot.de/ 
• dirk.weil@gedoplan.de 
• @dirkweil 
Speeding up Java Persistence

Más contenido relacionado

Destacado

Speeding up Java Persistence
Speeding up Java PersistenceSpeeding up Java Persistence
Speeding up Java Persistencegedoplan
 
Leichtgewichtige Microservices mit Java EE 7
Leichtgewichtige Microservices mit Java EE 7Leichtgewichtige Microservices mit Java EE 7
Leichtgewichtige Microservices mit Java EE 7gedoplan
 
javaPersistenceInActionFeaturesJenseitsDesEntryLevels
javaPersistenceInActionFeaturesJenseitsDesEntryLevelsjavaPersistenceInActionFeaturesJenseitsDesEntryLevels
javaPersistenceInActionFeaturesJenseitsDesEntryLevelsgedoplan
 
WildFly als Plattform moderner Enterprise-Anwendungen
WildFly als Plattform moderner Enterprise-AnwendungenWildFly als Plattform moderner Enterprise-Anwendungen
WildFly als Plattform moderner Enterprise-Anwendungengedoplan
 
Infinispan / JBoss Data Grid - Schneller Zugriff auf große Datenmengen im Cl...
 Infinispan / JBoss Data Grid - Schneller Zugriff auf große Datenmengen im Cl... Infinispan / JBoss Data Grid - Schneller Zugriff auf große Datenmengen im Cl...
Infinispan / JBoss Data Grid - Schneller Zugriff auf große Datenmengen im Cl...gedoplan
 
Java EE 7 - Enterprise-Anwendungen ohne Ballast
Java EE 7 - Enterprise-Anwendungen ohne BallastJava EE 7 - Enterprise-Anwendungen ohne Ballast
Java EE 7 - Enterprise-Anwendungen ohne Ballastgedoplan
 
Apache camel
Apache camelApache camel
Apache camelgedoplan
 
Java EE 7 - Enterprise-Anwendungen ohne Ballast
Java EE 7 - Enterprise-Anwendungen ohne BallastJava EE 7 - Enterprise-Anwendungen ohne Ballast
Java EE 7 - Enterprise-Anwendungen ohne Ballastgedoplan
 
Versionierung mit GIT
Versionierung mit GITVersionierung mit GIT
Versionierung mit GITgedoplan
 
Java Batch – Der Standard für's Stapeln
Java Batch – Der Standard für's StapelnJava Batch – Der Standard für's Stapeln
Java Batch – Der Standard für's Stapelngedoplan
 
Jpa queries
Jpa queriesJpa queries
Jpa queriesgedoplan
 
Wie viel Client braucht das Web?JSF, Vaadin und AngularJS im Vergleich
Wie viel Client braucht das Web?JSF, Vaadin und AngularJS im VergleichWie viel Client braucht das Web?JSF, Vaadin und AngularJS im Vergleich
Wie viel Client braucht das Web?JSF, Vaadin und AngularJS im Vergleichgedoplan
 

Destacado (13)

Speeding up Java Persistence
Speeding up Java PersistenceSpeeding up Java Persistence
Speeding up Java Persistence
 
Leichtgewichtige Microservices mit Java EE 7
Leichtgewichtige Microservices mit Java EE 7Leichtgewichtige Microservices mit Java EE 7
Leichtgewichtige Microservices mit Java EE 7
 
javaPersistenceInActionFeaturesJenseitsDesEntryLevels
javaPersistenceInActionFeaturesJenseitsDesEntryLevelsjavaPersistenceInActionFeaturesJenseitsDesEntryLevels
javaPersistenceInActionFeaturesJenseitsDesEntryLevels
 
WildFly als Plattform moderner Enterprise-Anwendungen
WildFly als Plattform moderner Enterprise-AnwendungenWildFly als Plattform moderner Enterprise-Anwendungen
WildFly als Plattform moderner Enterprise-Anwendungen
 
Infinispan / JBoss Data Grid - Schneller Zugriff auf große Datenmengen im Cl...
 Infinispan / JBoss Data Grid - Schneller Zugriff auf große Datenmengen im Cl... Infinispan / JBoss Data Grid - Schneller Zugriff auf große Datenmengen im Cl...
Infinispan / JBoss Data Grid - Schneller Zugriff auf große Datenmengen im Cl...
 
Java EE 7 - Enterprise-Anwendungen ohne Ballast
Java EE 7 - Enterprise-Anwendungen ohne BallastJava EE 7 - Enterprise-Anwendungen ohne Ballast
Java EE 7 - Enterprise-Anwendungen ohne Ballast
 
Apache camel
Apache camelApache camel
Apache camel
 
Java EE 7 - Enterprise-Anwendungen ohne Ballast
Java EE 7 - Enterprise-Anwendungen ohne BallastJava EE 7 - Enterprise-Anwendungen ohne Ballast
Java EE 7 - Enterprise-Anwendungen ohne Ballast
 
Versionierung mit GIT
Versionierung mit GITVersionierung mit GIT
Versionierung mit GIT
 
Java Batch – Der Standard für's Stapeln
Java Batch – Der Standard für's StapelnJava Batch – Der Standard für's Stapeln
Java Batch – Der Standard für's Stapeln
 
Jpa queries
Jpa queriesJpa queries
Jpa queries
 
AngularJS
AngularJSAngularJS
AngularJS
 
Wie viel Client braucht das Web?JSF, Vaadin und AngularJS im Vergleich
Wie viel Client braucht das Web?JSF, Vaadin und AngularJS im VergleichWie viel Client braucht das Web?JSF, Vaadin und AngularJS im Vergleich
Wie viel Client braucht das Web?JSF, Vaadin und AngularJS im Vergleich
 

Similar a Speeding up Java Persistence

Datenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence ApiDatenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence ApiChristian Baranowski
 
Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen
Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-AnwendungenJava Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen
Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungengedoplan
 
Effiziente datenpersistierung mit JPA 2.1 und Hibernate
Effiziente datenpersistierung mit JPA 2.1 und HibernateEffiziente datenpersistierung mit JPA 2.1 und Hibernate
Effiziente datenpersistierung mit JPA 2.1 und HibernateThorben Janssen
 
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...gedoplan
 
JSF und JPA effizient kombinieren (W-JAX 2011)
JSF und JPA effizient kombinieren (W-JAX 2011)JSF und JPA effizient kombinieren (W-JAX 2011)
JSF und JPA effizient kombinieren (W-JAX 2011)Michael Kurz
 
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...gedoplan
 
Go Fullstack: Webanwendungen mit Java EE 6 bauen (W-JAX 2011)
Go Fullstack: Webanwendungen mit Java EE 6 bauen (W-JAX 2011)Go Fullstack: Webanwendungen mit Java EE 6 bauen (W-JAX 2011)
Go Fullstack: Webanwendungen mit Java EE 6 bauen (W-JAX 2011)Michael Kurz
 
JEE-Microservices mit Quarkus – eine Einführung
JEE-Microservices mit Quarkus – eine EinführungJEE-Microservices mit Quarkus – eine Einführung
JEE-Microservices mit Quarkus – eine Einführunggedoplan
 
Workshop zu Hibernate 3.2.2 GA
Workshop zu Hibernate 3.2.2 GAWorkshop zu Hibernate 3.2.2 GA
Workshop zu Hibernate 3.2.2 GAOliver Belikan
 
Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!OPEN KNOWLEDGE GmbH
 
DB-Schema-Evolution mit LiquiBase
DB-Schema-Evolution mit LiquiBaseDB-Schema-Evolution mit LiquiBase
DB-Schema-Evolution mit LiquiBasegedoplan
 
2008 - Basta!: DAL DIY
2008 - Basta!: DAL DIY2008 - Basta!: DAL DIY
2008 - Basta!: DAL DIYDaniel Fisher
 
Enterprise Java Batch mit Spring
Enterprise Java Batch mit SpringEnterprise Java Batch mit Spring
Enterprise Java Batch mit Springdenschu
 
DWX 2022 - Top 10 Best-Practices für YAML-Pipelines in Azure DevOps
DWX 2022 - Top 10 Best-Practices für YAML-Pipelines in Azure DevOpsDWX 2022 - Top 10 Best-Practices für YAML-Pipelines in Azure DevOps
DWX 2022 - Top 10 Best-Practices für YAML-Pipelines in Azure DevOpsMarc Müller
 
JPA – Der Persistenz-­Standard in der Java EE und SE
JPA – Der Persistenz-­Standard in der Java EE und SEJPA – Der Persistenz-­Standard in der Java EE und SE
JPA – Der Persistenz-­Standard in der Java EE und SEhwilming
 
Creasoft - Windows powershell
Creasoft - Windows powershellCreasoft - Windows powershell
Creasoft - Windows powershellCreasoft AG
 
Grails im Überblick und in der Praxis
Grails im Überblick und in der PraxisGrails im Überblick und in der Praxis
Grails im Überblick und in der PraxisTobias Kraft
 
Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Joachim Baumann
 
Day CQ 5.3 WCM - Was ist neu
Day CQ 5.3 WCM - Was ist neuDay CQ 5.3 WCM - Was ist neu
Day CQ 5.3 WCM - Was ist neuCédric Hüsler
 

Similar a Speeding up Java Persistence (20)

Datenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence ApiDatenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence Api
 
Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen
Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-AnwendungenJava Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen
Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen
 
Effiziente datenpersistierung mit JPA 2.1 und Hibernate
Effiziente datenpersistierung mit JPA 2.1 und HibernateEffiziente datenpersistierung mit JPA 2.1 und Hibernate
Effiziente datenpersistierung mit JPA 2.1 und Hibernate
 
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
 
JSF und JPA effizient kombinieren (W-JAX 2011)
JSF und JPA effizient kombinieren (W-JAX 2011)JSF und JPA effizient kombinieren (W-JAX 2011)
JSF und JPA effizient kombinieren (W-JAX 2011)
 
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
 
Go Fullstack: Webanwendungen mit Java EE 6 bauen (W-JAX 2011)
Go Fullstack: Webanwendungen mit Java EE 6 bauen (W-JAX 2011)Go Fullstack: Webanwendungen mit Java EE 6 bauen (W-JAX 2011)
Go Fullstack: Webanwendungen mit Java EE 6 bauen (W-JAX 2011)
 
JEE-Microservices mit Quarkus – eine Einführung
JEE-Microservices mit Quarkus – eine EinführungJEE-Microservices mit Quarkus – eine Einführung
JEE-Microservices mit Quarkus – eine Einführung
 
Workshop zu Hibernate 3.2.2 GA
Workshop zu Hibernate 3.2.2 GAWorkshop zu Hibernate 3.2.2 GA
Workshop zu Hibernate 3.2.2 GA
 
Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!
 
DB-Schema-Evolution mit LiquiBase
DB-Schema-Evolution mit LiquiBaseDB-Schema-Evolution mit LiquiBase
DB-Schema-Evolution mit LiquiBase
 
2008 - Basta!: DAL DIY
2008 - Basta!: DAL DIY2008 - Basta!: DAL DIY
2008 - Basta!: DAL DIY
 
Enterprise Java Batch mit Spring
Enterprise Java Batch mit SpringEnterprise Java Batch mit Spring
Enterprise Java Batch mit Spring
 
DWX 2022 - Top 10 Best-Practices für YAML-Pipelines in Azure DevOps
DWX 2022 - Top 10 Best-Practices für YAML-Pipelines in Azure DevOpsDWX 2022 - Top 10 Best-Practices für YAML-Pipelines in Azure DevOps
DWX 2022 - Top 10 Best-Practices für YAML-Pipelines in Azure DevOps
 
JPA – Der Persistenz-­Standard in der Java EE und SE
JPA – Der Persistenz-­Standard in der Java EE und SEJPA – Der Persistenz-­Standard in der Java EE und SE
JPA – Der Persistenz-­Standard in der Java EE und SE
 
Query Result Caching
Query Result CachingQuery Result Caching
Query Result Caching
 
Creasoft - Windows powershell
Creasoft - Windows powershellCreasoft - Windows powershell
Creasoft - Windows powershell
 
Grails im Überblick und in der Praxis
Grails im Überblick und in der PraxisGrails im Überblick und in der Praxis
Grails im Überblick und in der Praxis
 
Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)
 
Day CQ 5.3 WCM - Was ist neu
Day CQ 5.3 WCM - Was ist neuDay CQ 5.3 WCM - Was ist neu
Day CQ 5.3 WCM - Was ist neu
 

Speeding up Java Persistence

  • 1. Dirk Weil | GEDOPLAN GmbH Speeding up Java Persistence
  • 2. Dirk Weil | GEDOPLAN GmbH Dirk Weil •GEDOPLAN GmbH, Bielefeld •Java EE seit 1998 •Konzeption und Realisierung •Seminare •Vorträge •Veröffentlichungen Speeding up Java Persistence
  • 3. Dirk Weil | GEDOPLAN GmbH 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; … Speeding up Java Persistence
  • 4. Dirk Weil | GEDOPLAN GmbH 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; Speeding up Java Persistence
  • 5. Dirk Weil | GEDOPLAN GmbH Id-Generierung •Alternative: BYO-ID (selbst machen) –Id auch in transitiven Objekten gesetzt –Insert ohne Zusatzaufwand –Achtung: i. A. nicht trivial –Z. B.: UUID this.id = UUID.randomUUID().toString(); // oder: new com.eaio.uuid.UUID().toString() Speeding up Java Persistence
  • 6. Dirk Weil | GEDOPLAN GmbH Id-Generierung •@GeneratedValue langsamer (OOTB) Speeding up Java Persistence
  • 7. Dirk Weil | GEDOPLAN GmbH Id-Generierung •Tuning: Höhere Allocation Size @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; Speeding up Java Persistence
  • 8. Dirk Weil | GEDOPLAN GmbH Id-Generierung Speeding up Java Persistence
  • 9. Dirk Weil | GEDOPLAN GmbH Relationship Loading •Relationen werden durch Attribute mit @…To… repräsentiert @Entity public class Book { @ManyToOne public Publisher publisher; @Entity public class Publisher { @OneToMany(mappedBy="publisher") public List<Book> books; Speeding up Java Persistence
  • 10. Dirk Weil | GEDOPLAN GmbH Relationship Loading •Relationen-Parameter: fetch •Referenzierte Entities direkt laden? –EAGER: Direkt –LAZY: Später bei Bedarf @ManyToOne(fetch = FetchType.LAZY) private Artikel artikel; Speeding up Java Persistence
  • 11. Dirk Weil | GEDOPLAN GmbH Relationship Loading •Bsp.: Auftragsposition bearbeiten –n:1-Relation zu Artikel Kunde Auftrag Auftrags Position Artikel Land 1 * 1 * * 1 1 * @Entity public class AuftragsPosition { @ManyToOne private Artikel artikel; Speeding up Java Persistence
  • 12. Dirk Weil | GEDOPLAN GmbH Relationship Loading •Annahme: Verwendet nur AuftragsPosition AuftragsPosition aufPos = em.find(AuftragsPosition.class, id); … select … from AuftragsPosition where … @ManyToOne private Artikel artikel; @ManyToOne(fetch=FetchType.LAZY) private Artikel artikel; select … from AuftragsPosition where … select … from Artikel where … Speeding up Java Persistence
  • 13. Dirk Weil | GEDOPLAN GmbH Relationship Loading •Annahme: Verwendet auch Artikel AuftragsPosition aufPos = em.find(AuftragsPosition.class, id); … Artikel artikel = aufPos.getArtikel(); … @ManyToOne private Artikel artikel; @ManyToOne(fetch=FetchType.LAZY) private Artikel artikel; select … from AuftragsPosition where … select … from Artikel where … select from AuftragsPosition where … … select … from Artikel where … Speeding up Java Persistence
  • 14. Dirk Weil | GEDOPLAN GmbH Relationship Loading •Messergebnis (1000 Items, Hibernate, MySQL) EAGER LAZY AuftragsPosition ohne Artikel 2.967 ms 2.505 ms - 15 % AuftragsPosition mit Artikel 2.959 ms 4.305 ms + 45 % Kunde ohne Auftrag 30.295 ms 4.848 ms - 84 % = Default Kunde Auftrag Auftrags Position Artikel Land 1 * 1 * * 1 1 * Speeding up Java Persistence
  • 15. Dirk Weil | GEDOPLAN GmbH Relationship Loading •Fazit: –Zugriffsverhalten genau analysieren –Default ist schon recht gut –Besser: Immer LAZY verwenden und bei Bedarf Fetch Joins oder Entity Graphs nutzen Speeding up Java Persistence
  • 16. Dirk Weil | GEDOPLAN GmbH Relationship Loading •Fetch Joins –mit JPQL –Achtung: Kartesisches Produkt! select ap from Auftragsposition ap left join fetch ap.artikel ... Speeding up Java Persistence
  • 17. Dirk Weil | GEDOPLAN GmbH 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, JoinType.LEFT) .fetch(AuftragsPosition_.artikel, JoinType.LEFT); … Speeding up Java Persistence
  • 18. Dirk Weil | GEDOPLAN GmbH Relationship Loading •Entity Graphs TBD @Entity @NamedEntityGraph( name = "Kunde.auftraege", attributeNodes = @NamedAttributeNode(value = "auftraege"))) public class Kunde { @OneToMany(mappedBy="kunde") private Set<Auftrag> auftraege; TypedQuery<Kunde> query = entityManager.createQuery(…); EntityGraph<?> entityGraph = entityManager.getEntityGraph("Kunde.auftraege"); query.setHint("javax.persistence.loadgraph", entityGraph); Speeding up Java Persistence
  • 19. Dirk Weil | GEDOPLAN GmbH Fetch Tuning •ToMany-Fetching: "N+1"-Problem –z.B. Lesen einiger User inkl. Groups + Permissions SELECT ... FROM USER SELECT ... FROM GROUP WHERE USER_ID=? SELECT ... FROM PERMISSION WHERE GROUP_ID=? SELECT ... FROM PERMISSION WHERE GROUP_ID=? SELECT ... FROM GROUP WHERE USER_ID=? SELECT ... FROM GROUP WHERE USER_ID=? Speeding up Java Persistence
  • 20. Dirk Weil | GEDOPLAN GmbH 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(); Speeding up Java Persistence
  • 21. Dirk Weil | GEDOPLAN GmbH Fetch Tuning •Lösungsansatz 2: Batch Fetching @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 SELECT ... FROM USER SELECT ... FROM GROUP WHERE USER_ID IN (?,?,…) SELECT ... FROM PERMISSION WHERE GROUP_ID IN (?,?,…) SELECT ... FROM PERMISSION WHERE GROUP_ID IN (?,?,…) SELECT ... FROM GROUP WHERE USER_ID IN (?,?,…) N+1 (N/B)+1 Speeding up Java Persistence
  • 22. Dirk Weil | GEDOPLAN GmbH Basic Attribute Loading •Fetch-Strategie auch für einfache Werte wählbar •Lazy Loading ggf. sinnvoll bei –selten genutzten Werten –umfangreichen Daten @Basic(fetch = FetchType.LAZY) private String longAdditionalInfo; Speeding up Java Persistence
  • 23. Dirk Weil | GEDOPLAN GmbH Basic Attribute Loading •Messergebnis –Lesen von Kunden –10 'ungenutzte' Strings à 150 chars –1000 Interationen, Hibernate, MySQL EAGER LAZY 6.782 ms 6.440 ms -5 % = Default-Einstellung Speeding up Java Persistence
  • 24. Dirk Weil | GEDOPLAN GmbH Tupel-Selects •Selektion einzelner Attribute –als Tupel –mit Constructor Expression •Messergebnis (ms für 10000 Items) select k.id, k.name from Kunde k select new IdAndName(k.id, k.name) from Kunde k Entity komplett Object[] Ctor Expression 11.211 ms 3.890 ms 4.010 ms Speeding up Java Persistence
  • 25. Dirk Weil | GEDOPLAN GmbH Query-Parameter –JPQL Injection –Prepared Statement Reuse em.createQuery("select k from Kunde k " + "where k.name='" + someString + "'") em.createQuery("select k from Kunde k " + "where k.name=:name") .setParameter("name", someString) Speeding up Java Persistence
  • 26. Dirk Weil | GEDOPLAN GmbH Caching JPA Provider EntityManager DB 2nd Level Cache 1st Level Cache Query Cache Speeding up Java Persistence
  • 27. Dirk Weil | GEDOPLAN GmbH First Level Cache •Standard •Je EntityManager •Enthält in Sitzung geladene Objekte –Achtung: Speicherbedarf! –sinnvolle EM-Lebensdauer nutzen –flush/clear ist i. A. Antipattern! •ausser im Batch – dort häufig sinnvoll EntityManager 1st Level Cache Speeding up Java Persistence
  • 28. Dirk Weil | GEDOPLAN GmbH 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! Speeding up Java Persistence
  • 29. Dirk Weil | GEDOPLAN GmbH 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(); Speeding up Java Persistence
  • 30. Dirk Weil | GEDOPLAN GmbH 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] Speeding up Java Persistence
  • 31. Dirk Weil | GEDOPLAN GmbH 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(); … } Speeding up Java Persistence
  • 32. Dirk Weil | GEDOPLAN GmbH Query Cache •EclipseLink: •Hibernate: TypedQuery<Kunde> query = em.createQuery(…); query.setHint("org.hibernate.cacheable", true); … TypedQuery<Kunde> query = em.createQuery(…); query.setHint("eclipselink.cache-usage", "CheckCacheThenDatabase"); … Speeding up Java Persistence
  • 33. Dirk Weil | GEDOPLAN GmbH Second Level Cache •JPA 2.x unterstützt 2nd Level Cache –nur rudimentäre Konfiguration –Providerspezifische Konfiguration in der Praxis unabdingbar JPA Provider EntityManager 2nd Level Cache 1st Level Cache Speeding up Java Persistence
  • 34. Dirk Weil | GEDOPLAN GmbH Second Level Cache •Providerspezifische Implementierung –Cache-Provider Infinispan, EHCache, OSCache, … –Cache-Strategien read-only, read-write, … –Storage Memory, Disk, Cluster, … Speeding up Java Persistence
  • 35. Dirk Weil | GEDOPLAN GmbH Second Level Cache •Wirkt applikationsweit •Semantik ähnlich HashMap •Ladereihenfolge: –1st Level Cache (EntityManager) –2nd Level Cache, falls enabled –DB Speeding up Java Persistence
  • 36. Dirk Weil | GEDOPLAN GmbH Second Level Cache •Vorteil bei häufig genutzten Daten –Konstanten –selten veränderte Daten –nur von dieser Anwendung veränderte Daten Speeding up Java Persistence
  • 37. Dirk Weil | GEDOPLAN GmbH 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 * Speeding up Java Persistence
  • 38. Dirk Weil | GEDOPLAN GmbH Second Level Cache •Konfiguration lt. Spec <persistence-unit name="…"> <provider>…</provider> <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> … Cache aktiv für … Default bei … ALL alle Entities NONE keine Klasse Hibernate ENABLE_SELECTIVE nur @Cacheable(true) DISABLE_SELECTIVE alle außer @Cacheable(false) EclipseLink @Entity @Cacheable(true) public class Land { … Speeding up Java Persistence
  • 39. Dirk Weil | GEDOPLAN GmbH Second Level Cache •Messergebnis (1000 Interationen, Hibernate, MySQL) ohne L2C: 8.975 ms mit L2C für Land: 5.401 ms Speeding up Java Persistence
  • 40. Dirk Weil | GEDOPLAN GmbH Second Level Cache •L2C für Anwendungscode transparent •find liefert Kopie des Cache-Eintrags •Für komplett konstante Werte kann ein weiterer Cache in der Anwendung sinnvoll sein Speeding up Java Persistence
  • 41. Dirk Weil | GEDOPLAN GmbH 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 Speeding up Java Persistence
  • 42. Dirk Weil | GEDOPLAN GmbH 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 Speeding up Java Persistence
  • 43. Dirk Weil | GEDOPLAN GmbH 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 Speeding up Java Persistence
  • 44. Dirk Weil | GEDOPLAN GmbH Inheritance •SINGLE_TABLE @Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) public abstract class Vehicle { … Speeding up Java Persistence
  • 45. Dirk Weil | GEDOPLAN GmbH Inheritance •JOINED @Entity @Inheritance(strategy=InheritanceType.JOINED) public abstract class Vehicle { … Speeding up Java Persistence
  • 46. Dirk Weil | GEDOPLAN GmbH Inheritance •TABLE_PER_CLASS @Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public abstract class Vehicle { … Speeding up Java Persistence
  • 47. Dirk Weil | GEDOPLAN GmbH 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 Speeding up Java Persistence
  • 48. Dirk Weil | GEDOPLAN GmbH Inheritance •Optimale Performanz liefern SINGLE_TABLE und TABLE_PER_CLASS •Aber: Auch andere Implikationen •Genaue Analyse notwendig Speeding up Java Persistence
  • 49. Dirk Weil | GEDOPLAN GmbH Wenn‘s dennoch nicht reicht •Native Queries •Stored Procedure Queries •User Functions Speeding up Java Persistence
  • 50. Dirk Weil | GEDOPLAN GmbH Fazit •Viele Optimierungen providerunabhängig möglich •Wesentlich: –Lazy Loading –Caching •Genaue Analyse notwendig •Messen •Kein Selbstzweck Speeding up Java Persistence
  • 51. Dirk Weil | GEDOPLAN GmbH More •http://www.gedoplan-it-training.de Seminare in Berlin, Bielefeld, Inhouse •http://www.gedoplan-it-consulting.de Reviews, Coaching, … •http://javaeeblog.wordpress.com/ •http://expertenkreisjava.blogspot.de/ • dirk.weil@gedoplan.de • @dirkweil Speeding up Java Persistence