Effiziente datenpersistierung mit JPA 2.1 und Hibernate

69
Effiziente Datenpersistierung mit JPA 2.1 www.thoughts-on-java.org

Transcript of Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Page 1: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Effiziente Datenpersistierungmit JPA 2.1

www.thoughts-on-java.org

Page 2: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Thorben Janssen

• Senior Entwickler und Architekt @ Qualitype GmbH

• CDI 2.0 (JSR 365) Expert Group Mitglied

• Twitter: @thjanssen123

• Blog: www.thoughts-on-java.org

www.thoughts-on-java.org

Page 3: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Beispielanwendung

www.thoughts-on-java.org

Page 4: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

www.thoughts-on-java.org

An

wen

du

ng

Page 5: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Was bedeutet Effizienz?

www.thoughts-on-java.org

Page 6: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Performance

SpeicherplatzProduktivität Xwww.thoughts-on-java.org

X

Effi

zien

z

Page 7: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Performance

www.thoughts-on-java.org

Page 8: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Frühzeitiges Erkennen von Performanceproblemen

• Typische Ursachen von Performanceproblemen

• Performanceprobleme beheben und vermeiden

www.thoughts-on-java.org

Perf

orm

ance

Page 9: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Auftreten von Performanceproblemen

www.thoughts-on-java.org

Page 10: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Ein Kunde meldet ein langsames System

• Der DBA fragt nach dem Grund für sehr viele (ähnliche) Abfragen

• Schlechte Performance beim Test der Anwendung

• Entwickler sieht auffällige Statistiken im Log

www.thoughts-on-java.org

Perf

orm

ance

pro

ble

me

Page 11: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Hibernate Statistics

www.thoughts-on-java.org

Page 12: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Über Systemproperty aktivieren:

hibernate.generate_statistics = true

• Logging konfigurieren:

org.hibernate.stat = DEBUG

www.thoughts-on-java.org

Hib

ern

ate

Stat

isti

cs

Page 13: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt Model)

www.thoughts-on-java.org

Page 14: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Ursachen von Performanceproblemen

www.thoughts-on-java.org

Page 15: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Langsame Select-Statements

• Falsche Fetch-Strategie

• Fehlendes Caching

• Laden nicht benötigter Daten

• Datensätze einzeln löschen oder ändern

• Logik in der Anwendung anstatt der Datenbank/Abfrage

www.thoughts-on-java.org

Häu

fige

Urs

ach

en

Page 16: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

1. Langsame Select-Statements

www.thoughts-on-java.org

Page 17: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Meistens kein „echtes“ JPA- oder Hibernateproblem

• Erzeugtes SQL überprüfen

• Indexe überprüfen

• Ausführungsplan des Statements überprüfen

• Ggf. Ergebnismenge beschränken (paging)

• Statement optimieren

• Native SQL-Statements verwenden, wenn JPQL nicht ausreicht

www.thoughts-on-java.org

Lan

gsam

e Se

lect

s

Page 18: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Schnellere Abfragen durch echtes SQL

• JPQL unterstützt nur ein Subset von SQL

• Datenbankspezifische SQL-Features

• Native Query liefert Object[] für jede Ergebniszeile

• Erfordert programmatisches oder deklaratives Mapping

www.thoughts-on-java.org

Nat

ive

Qu

ery

Page 19: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Deklaratives Mapping für Abfrageergebnisse

• Unterstützte Zieltypen:

• Entities

• Value Objekte

• Skalare

www.thoughts-on-java.org

Res

ult

SetM

app

ing

Page 20: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt NativeQuery)

www.thoughts-on-java.org

Page 21: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

2. Fetch-Strategien

www.thoughts-on-java.org

Page 22: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Statische Definition im Mapping

• Fragestellungen

• Wann soll geladen werden? FetchType

• Wie soll geladen werden? FetchMode

www.thoughts-on-java.org

Fetc

h-S

trat

gien

Page 23: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

2.1 FetchType

www.thoughts-on-java.org

Page 24: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Lazy

• Relation wird bei erstem Zugriff geladen

• Default für to-many Relationen

• Verwendet Proxies für to-one Relationen

• Eager

• Relation wird sofort geladen

• Default für to-one Relationen

www.thoughts-on-java.org

Fetc

hTy

pe

Page 25: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Hibernate erzeugt Proxy für lazy to-one-Relationen

• Proxy ist Subklasse der Entity

• Instanceof möglich

• Typecast auf Subklasse nicht möglich

• Alternative: bytecode enhancement ohne Proxy

www.thoughts-on-java.org

To-o

ne

mit

Pro

xy

Page 26: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt EagerLoading)

www.thoughts-on-java.org

Page 27: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

2.2 FetchMode

www.thoughts-on-java.org

Page 28: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Hibernate spezifisch

• Definiert wie Relationen geladen werden

• JOIN = im selben SELECT

• SELECT = 1 SELECT je Entity der Relation

• SUBSELECT = 1 SELECT für alle Entities der Relation

• BATCH = mehrere Entities der Relation je SELECT

www.thoughts-on-java.org

Fetc

hM

od

e

Page 29: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt EagerLoading)

www.thoughts-on-java.org

Page 30: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• To-many-Relationen

• Default in Annotationen belassen (meist FetchType.LAZY)

• Eager fetching, wenn benötigt für Query definieren

• To-one-Relationen

• Einzeln prüfen, meist ist der default OK

www.thoughts-on-java.org

Emp

feh

lun

g

Page 31: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

2.3 QueryspezifischesFetching

www.thoughts-on-java.org

Page 32: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Entsteht, wenn lazy Relationen beim Zugriff nachgeladen werden

List<Author> authors = this.em.createQuery("SELECT a FROM Author a",

Author.class).getResultList();

for (Author a : authors) {

System.out.println("Author " + a.getFirstName() + " " + a.getLastName() + " wrote " + a.getBooks().stream().map(b -> b.getTitle()).collect(Collectors.joining(", ")));

}

www.thoughts-on-java.org

N+1

Sel

ects

Page 33: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt LazyLoading)

www.thoughts-on-java.org

Page 34: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Besser, benötigte Relationen direkt mit laden:

• (FetchType.EAGER)

• Fetch Join

• @NamedEntityGraph

• EntityGraph

www.thoughts-on-java.org

N+1

Sel

ects

Page 35: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Verwendung von JOIN FETCH anstatt JOIN in Abfrage

List<Author> authors = this.em.createQuery("SELECT DISTINCT a FROM Author a JOIN FETCH a.books b", Author.class).getResultList();

for (Author a : authors) {

System.out.println("Author " + a.getFirstName() + " " + a.getLastName() + " wrote " + a.getBooks().stream().map(b -> b.getTitle()).collect(Collectors.joining(", ")));

}

www.thoughts-on-java.org

Fetc

hJo

in

Page 36: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt LazyLoading)

www.thoughts-on-java.org

Page 37: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Vorteile:

• EntityManager lädt Relation in der selben Abfrage

• Nachteile:

• Spezielle Abfrage für jeden Use Case erforderlich

• Bildet kartesisches Produkt

www.thoughts-on-java.org

Fetc

hJo

in

Page 38: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Neu in JPA 2.1

• Definiert einen zu ladenden Entitätsgraphen

• @NamedEntityGraph

• @NamedAttributeNode

• @NamedSubGraph

www.thoughts-on-java.org

Nam

edEn

tity

Gra

ph

Page 39: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Fetchgraph

• Elemente des Graphen werden EAGER geladen

• Alle anderen werden LAZY geladen

• Loadgraph

• Elemente des Graphen werden EAGER geladen

• Alle anderen werden mit ihrem jeweiligen FetchType geladen

• ACHTUNG: Hibernate behandelt beides gleich!• HHH-8776

www.thoughts-on-java.org

Nam

edEn

tity

Gra

ph

Page 40: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt LazyLoading)

www.thoughts-on-java.org

Page 41: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Vorteile:

• Queryspezifisches EAGER-loading

• Definition des Graphen unabhängig von der Abfrage

• Nachteile:

• Bildet kartesisches Produkt

www.thoughts-on-java.org

Nam

edEn

tity

Gra

ph

Page 42: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Neu in JPA 2.1

• Dynamische Variante des @NamedEntityGraph

• Definition mittels Java API

• EntityManager.createEntityGraph(Class entity)

• EntityGraph

• SubGraph

www.thoughts-on-java.org

Enti

tyG

rap

h

Page 43: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt LazyLoading)

www.thoughts-on-java.org

Page 44: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Vorteile:

• Queryspezifisches EAGER-loading

• Definition des Graphen unabhängig von der Abfrage

• Graph kann zur Laufzeit definiert werden

• Nachteile:

• Bildet kartesisches Produkt

www.thoughts-on-java.org

Enti

tyG

rap

h

Page 45: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

3. Caching

www.thoughts-on-java.org

Page 46: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

www.thoughts-on-java.org

DB

2nd Level Cache

1st Level Cache

HibernateSession

QueryCache

1st Level Cache

HibernateSession

Cac

hes

Page 47: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• 1st Level Cache

• An Session gebunden

• Per default aktiviert

• 2nd Level Cache

• Sessionübergreifend

• Konfiguration erforderlich

• Query Cache

• Sessionübergreifend

• Konfiguration erforderlich

www.thoughts-on-java.org

Cac

hes

Page 48: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

3.1 1st Level Cache

www.thoughts-on-java.org

Page 49: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Automatisch aktiviert

• Sessioninterner Speicher verwendeter Entities

• Zugriff erfolgt transparent

www.thoughts-on-java.org

1st

Lev

el C

ach

e

Page 50: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt 1stLevelCaching)

www.thoughts-on-java.org

Page 51: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

3.2 2nd Level Cache

www.thoughts-on-java.org

Page 52: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Sessionübergreifender Speicher für Entities

• Im default deaktiviert

• persistence.xml oder EntityManagerFactory

• Zugriff erfolgt transparent

• Muss nicht durch den Persistence Provider bereitgestellt werden

• u.U. nicht portierbar

www.thoughts-on-java.org

2n

d L

evel

Cac

he

Page 53: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Shared Cache Mode

• ALL alle Entities werden gecached

• NONE keine Entities werden gecached

• ENABLE_SELECTIVE Caching muss für Entities aktiviert werden

• DISABLE_SELECTIVE Caching kann für Entities deaktiviert werden

• UNSPECIFIED Verwendet das default caching des PersistenceProviders

www.thoughts-on-java.org

2n

d L

evel

Cac

he

Page 54: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Speichert die Entities in ‚dehydrated‘-Form

• Nur die Eigenschaften der Entity, nicht die Entity selbst

• 1 [„Joshua“, „Bloch“, 0]

• Relationen werden nicht mit gespeichert

• Caching mit @org.hibernate.annotations.Cache möglich

www.thoughts-on-java.org

2n

d L

evel

Cac

he

Page 55: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt 2ndLevelCaching)

www.thoughts-on-java.org

Page 56: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Verwendung des Cache konfigurieren

• Cache Retrieve Mode

• Definiert wie Daten aus dem Cache gelesen werden

• Cache Store Mode

• Definiert wie Daten in den Cache geschrieben werden

www.thoughts-on-java.org

2n

d L

evel

Cac

he

Page 57: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Cache Retrieve Mode

• CacheRetrieveMode.USE (default)

• Daten werden aus Cache gelesen

• CacheRetrieveMode.BYPASS

• Daten werden aus DB gelesen

www.thoughts-on-java.org

2n

d L

evel

Cac

he

Page 58: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Cache Store Mode

• CacheStoreMode.USE (default)

• Cache wird beim commit erzeugt oder aktualisiert

• Aktualisierung wird bei nur lesendem Zugriff nicht erzwungen

• CacheStoreMode.BYPASS

• Cache wird nur aktualisiert, nicht angelegt

• CacheStoreMode.REFRESH

• Cache wird beim commit erzeugt oder aktualisiert

• Aktualisierung wird bei nur lesendem Zugriff erzwungen

www.thoughts-on-java.org

2n

d L

evel

Cac

he

Page 59: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt 2ndLevelCaching)

www.thoughts-on-java.org

Page 60: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Concurrency Strategy

• JPA: Definition erfolgt global

• Hibernate: Definition erfolgt spezifisch für jede Entity

• @org.hibernate.annotations.Cache

www.thoughts-on-java.org

2n

d L

evel

Cac

he

Page 61: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Concurrency Strategy

• Read-only

• Read-write• Nicht für serializable transaction isolation verwendbar

• Nonstrict-read-write• Keine strict transaction isolation

• Transactional• Benötigt JTA• Z.B. Infinispan, EHCache

www.thoughts-on-java.org

2n

d L

evel

Cac

he

Page 62: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

3.3 Query Cache

www.thoughts-on-java.org

Page 63: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Hibernate spezifisch

• Sessionübergreifender Speicher von Abfrageergebnissen

• Im default deaktiviert

• persistence.xml: hibernate.cache.use_query_cache = true

• Caching muss für Query aktiviert werden• org.hibernate.Query.setCacheable(true)

• @NamedQuery(… hints = @QueryHint(name="org.hibernate.cacheable", value="true"))

www.thoughts-on-java.org

Qu

ery

Cac

he

Page 64: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Speichert Ergebnis für Abfrage mit Parametern

• [„FROM Author WHERE id=?“, 1] [1]

• Speichert nur Referenzen auf Entitäten oder Skalare

• Immer mit 2nd Level Cache kombinieren

www.thoughts-on-java.org

Qu

ery

Cac

he

Page 65: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Demo (Projekt QueryCaching)

www.thoughts-on-java.org

Page 66: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Nur Daten mit geringer Änderungsrate cachen

• Cache nicht ohne Benchmark einführen

• Query Cache und 2nd Level Cache gemeinsam nutzen

• Konfigurationen aufeinander abstimmen

www.thoughts-on-java.org

Emp

feh

lun

g

Page 67: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• JSR 338: JavaTM Persistence API, Version 2.1 http://download.oracle.com/otndocs/jcp/persistence-2_1-fr-eval-spec/index.html

• Hibernate Reference Documentationhttp://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/

• Hibernate Developer Guide http://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/

• Hibernate ORM: Tips, Tricks and Performance Techniques by Brett Meyer http://de.slideshare.net/brmeyer/hibernate-orm-performance-31550150

• Java Persistence with Hibernate Second Edition by Christian Bauer, Gaving King, Gary Gregory

www.thoughts-on-java.org

Qu

elle

n

Page 68: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

• Java Platform, Enterprise Edition: The Java EE Tutorial https://docs.oracle.com/javaee/7/tutorial/index.html

• Hibernate: Truly Understanding the Second-Level and Query Caches http://www.javalobby.org/java/forums/t48846.html

www.thoughts-on-java.org

Qu

elle

n

Page 69: Effiziente datenpersistierung mit JPA 2.1 und Hibernate

Noch Fragen?

www.thoughts-on-java.org