Effiziente Datenpersistierung
mit JPA 2.1
www.thoughts-on-java.org
Thorben Janssen
• Senior Entwickler und Architekt @ Qualitype GmbH
• CDI 2.0 (JSR 365) Expert Group Mitglied
• Twitter: @t...
Beispielanwendung
www.thoughts-on-java.org
www.thoughts-on-java.org
Anwendung
Was bedeutet Effizienz?
www.thoughts-on-java.org
Performance
SpeicherplatzProduktivität
Xwww.thoughts-on-java.org
X
Effizienz
Performance
www.thoughts-on-java.org
• Frühzeitiges Erkennen von Performanceproblemen
• Typische Ursachen von Performanceproblemen
• Performanceprobleme behebe...
Auftreten von
Performanceproblemen
www.thoughts-on-java.org
• Ein Kunde meldet ein langsames System
• Der DBA fragt nach dem Grund für sehr viele (ähnliche) Abfragen
• Schlechte Perf...
Hibernate Statistics
www.thoughts-on-java.org
• Über Systemproperty aktivieren:
hibernate.generate_statistics = true
• Logging konfigurieren:
org.hibernate.stat = DEBUG...
Demo (Projekt Model)
www.thoughts-on-java.org
Ursachen von
Performanceproblemen
www.thoughts-on-java.org
• Langsame Select-Statements
• Falsche Fetch-Strategie
• Fehlendes Caching
• Laden nicht benötigter Daten
• Datensätze ein...
1. Langsame Select-Statements
www.thoughts-on-java.org
• Meistens kein „echtes“ JPA- oder Hibernateproblem
• Erzeugtes SQL überprüfen
• Indexe überprüfen
• Ausführungsplan des S...
• Schnellere Abfragen durch echtes SQL
• JPQL unterstützt nur ein Subset von SQL
• Datenbankspezifische SQL-Features
• Nat...
• Deklaratives Mapping für Abfrageergebnisse
• Unterstützte Zieltypen:
• Entities
• Value Objekte
• Skalare
www.thoughts-o...
Demo (Projekt NativeQuery)
www.thoughts-on-java.org
2. Fetch-Strategien
www.thoughts-on-java.org
• Statische Definition im Mapping
• Fragestellungen
• Wann soll geladen werden?  FetchType
• Wie soll geladen werden?  F...
2.1 FetchType
www.thoughts-on-java.org
• Lazy
• Relation wird bei erstem Zugriff geladen
• Default für to-many Relationen
• Verwendet Proxies für to-one Relation...
• Hibernate erzeugt Proxy für lazy to-one-Relationen
• Proxy ist Subklasse der Entity
• Instanceof möglich
• Typecast auf ...
Demo (Projekt EagerLoading)
www.thoughts-on-java.org
2.2 FetchMode
www.thoughts-on-java.org
• Hibernate spezifisch
• Definiert wie Relationen geladen werden
• JOIN = im selben SELECT
• SELECT = 1 SELECT je Entity d...
Demo (Projekt EagerLoading)
www.thoughts-on-java.org
• To-many-Relationen
• Default in Annotationen belassen (meist FetchType.LAZY)
• Eager fetching, wenn benötigt für Query d...
2.3 Queryspezifisches
Fetching
www.thoughts-on-java.org
• Entsteht, wenn lazy Relationen beim Zugriff nachgeladen werden
List<Author> authors = this.em.createQuery("SELECT a FROM...
Demo (Projekt LazyLoading)
www.thoughts-on-java.org
• Besser, benötigte Relationen direkt mit laden:
• (FetchType.EAGER)
• Fetch Join
• @NamedEntityGraph
• EntityGraph
www.th...
• Verwendung von JOIN FETCH anstatt JOIN in Abfrage
List<Author> authors = this.em.createQuery("SELECT DISTINCT a FROM Aut...
Demo (Projekt LazyLoading)
www.thoughts-on-java.org
• Vorteile:
• EntityManager lädt Relation in der selben Abfrage
• Nachteile:
• Spezielle Abfrage für jeden Use Case erford...
• Neu in JPA 2.1
• Definiert einen zu ladenden Entitätsgraphen
• @NamedEntityGraph
• @NamedAttributeNode
• @NamedSubGraph
...
• Fetchgraph
• Elemente des Graphen werden EAGER geladen
• Alle anderen werden LAZY geladen
• Loadgraph
• Elemente des Gra...
Demo (Projekt LazyLoading)
www.thoughts-on-java.org
• Vorteile:
• Queryspezifisches EAGER-loading
• Definition des Graphen unabhängig von der Abfrage
• Nachteile:
• Bildet ka...
• Neu in JPA 2.1
• Dynamische Variante des @NamedEntityGraph
• Definition mittels Java API
• EntityManager.createEntityGra...
Demo (Projekt LazyLoading)
www.thoughts-on-java.org
• Vorteile:
• Queryspezifisches EAGER-loading
• Definition des Graphen unabhängig von der Abfrage
• Graph kann zur Laufzei...
3. Caching
www.thoughts-on-java.org
www.thoughts-on-java.org
DB
2nd
Level
Cache
1st
Level
Cache
Hibernate
Session
Query
Cache
1st
Level
Cache
Hibernate
Sessio...
• 1st Level Cache
• An Session gebunden
• Per default aktiviert
• 2nd Level Cache
• Sessionübergreifend
• Konfiguration er...
3.1 1st Level Cache
www.thoughts-on-java.org
• Automatisch aktiviert
• Sessioninterner Speicher verwendeter Entities
• Zugriff erfolgt transparent
www.thoughts-on-java...
Demo (Projekt 1stLevelCaching)
www.thoughts-on-java.org
3.2 2nd Level Cache
www.thoughts-on-java.org
• Sessionübergreifender Speicher für Entities
• Im default deaktiviert
• persistence.xml oder EntityManagerFactory
• Zugri...
• Shared Cache Mode
• ALL alle Entities werden gecached
• NONE keine Entities werden gecached
• ENABLE_SELECTIVE Caching m...
• Speichert die Entities in ‚dehydrated‘-Form
• Nur die Eigenschaften der Entity, nicht die Entity selbst
• 1  [„Joshua“,...
Demo (Projekt 2ndLevelCaching)
www.thoughts-on-java.org
• Verwendung des Cache konfigurieren
• Cache Retrieve Mode
• Definiert wie Daten aus dem Cache gelesen werden
• Cache Stor...
• Cache Retrieve Mode
• CacheRetrieveMode.USE (default)
• Daten werden aus Cache gelesen
• CacheRetrieveMode.BYPASS
• Date...
• Cache Store Mode
• CacheStoreMode.USE (default)
• Cache wird beim commit erzeugt oder aktualisiert
• Aktualisierung wird...
Demo (Projekt 2ndLevelCaching)
www.thoughts-on-java.org
• Concurrency Strategy
• JPA: Definition erfolgt global
• Hibernate: Definition erfolgt spezifisch für jede Entity
• @org....
• Concurrency Strategy
• Read-only
• Read-write
• Nicht für serializable transaction isolation verwendbar
• Nonstrict-read...
3.3 Query Cache
www.thoughts-on-java.org
• Hibernate spezifisch
• Sessionübergreifender Speicher von Abfrageergebnissen
• Im default deaktiviert
• persistence.xml:...
• Speichert Ergebnis für Abfrage mit Parametern
• [„FROM Author WHERE id=?“, 1]  [1]
• Speichert nur Referenzen auf Entit...
Demo (Projekt QueryCaching)
www.thoughts-on-java.org
• Nur Daten mit geringer Änderungsrate cachen
• Cache nicht ohne Benchmark einführen
• Query Cache und 2nd Level Cache gem...
• JSR 338: JavaTM Persistence API, Version 2.1
http://download.oracle.com/otndocs/jcp/persistence-2_1-fr-eval-
spec/index....
• Java Platform, Enterprise Edition: The Java EE Tutorial
https://docs.oracle.com/javaee/7/tutorial/index.html
• Hibernate...
Noch Fragen?
www.thoughts-on-java.org
Nächste SlideShare
Wird geladen in …5
×

Effiziente datenpersistierung mit JPA 2.1 und Hibernate

797 Aufrufe

Veröffentlicht am

Daten mit Hilfe der Java Persistence API in der Datenbank zu speichern stellt den Standard für Java Enterprise Anwendungen dar. Der Applikationsserver stellt alle benötigten Bibliotheken bereits zur Verfügung und die Verwendung ist so einfach, dass sie innerhalb kürzester Zeit erlernt werden kann. Spannend wird es immer erst dann, wenn die Anforderungen steigen, z.B. weil das Domainmodell sehr komplex, die Datenmenge besonders groß oder die geforderten Antwortzeiten sehr kurz sind. Auch hierfür bietet JPA in der Regel gute Lösungen und wenn das nicht ausreicht, können wir immer noch auf Hibernate-spezifische Features zurückgreifen. Dazu sind allerdings deutlich detailliertere Kenntnisse erforderlich. Einige Beispiele dafür sind Caches, Entity Graphen und Attribute Converter. Wir werden uns genauer ansehen, wie wir diese und andere Features nutzen können, um auch komplexere Anforderungen mit Hilfe von JPA umzusetzen und wann wir auf Hibernate-spezifische Features zurückgreifen müssen.
Hierfür werden grundlegende Kenntnisse in der Verwendung von JPA und Hibernate vorausgesetzt.

Veröffentlicht in: Technologie
0 Kommentare
0 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Keine Downloads
Aufrufe
Aufrufe insgesamt
797
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
248
Aktionen
Geteilt
0
Downloads
4
Kommentare
0
Gefällt mir
0
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Effiziente datenpersistierung mit JPA 2.1 und Hibernate

  1. 1. Effiziente Datenpersistierung mit JPA 2.1 www.thoughts-on-java.org
  2. 2. 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
  3. 3. Beispielanwendung www.thoughts-on-java.org
  4. 4. www.thoughts-on-java.org Anwendung
  5. 5. Was bedeutet Effizienz? www.thoughts-on-java.org
  6. 6. Performance SpeicherplatzProduktivität Xwww.thoughts-on-java.org X Effizienz
  7. 7. Performance www.thoughts-on-java.org
  8. 8. • Frühzeitiges Erkennen von Performanceproblemen • Typische Ursachen von Performanceproblemen • Performanceprobleme beheben und vermeiden www.thoughts-on-java.org Performance
  9. 9. Auftreten von Performanceproblemen www.thoughts-on-java.org
  10. 10. • 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 Performanceprobleme
  11. 11. Hibernate Statistics www.thoughts-on-java.org
  12. 12. • Über Systemproperty aktivieren: hibernate.generate_statistics = true • Logging konfigurieren: org.hibernate.stat = DEBUG www.thoughts-on-java.org HibernateStatistics
  13. 13. Demo (Projekt Model) www.thoughts-on-java.org
  14. 14. Ursachen von Performanceproblemen www.thoughts-on-java.org
  15. 15. • 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äufigeUrsachen
  16. 16. 1. Langsame Select-Statements www.thoughts-on-java.org
  17. 17. • 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 LangsameSelects
  18. 18. • 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 NativeQuery
  19. 19. • Deklaratives Mapping für Abfrageergebnisse • Unterstützte Zieltypen: • Entities • Value Objekte • Skalare www.thoughts-on-java.org ResultSetMapping
  20. 20. Demo (Projekt NativeQuery) www.thoughts-on-java.org
  21. 21. 2. Fetch-Strategien www.thoughts-on-java.org
  22. 22. • Statische Definition im Mapping • Fragestellungen • Wann soll geladen werden?  FetchType • Wie soll geladen werden?  FetchMode www.thoughts-on-java.org Fetch-Stratgien
  23. 23. 2.1 FetchType www.thoughts-on-java.org
  24. 24. • 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 FetchType
  25. 25. • 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-onemitProxy
  26. 26. Demo (Projekt EagerLoading) www.thoughts-on-java.org
  27. 27. 2.2 FetchMode www.thoughts-on-java.org
  28. 28. • 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 FetchMode
  29. 29. Demo (Projekt EagerLoading) www.thoughts-on-java.org
  30. 30. • 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 Empfehlung
  31. 31. 2.3 Queryspezifisches Fetching www.thoughts-on-java.org
  32. 32. • 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+1Selects
  33. 33. Demo (Projekt LazyLoading) www.thoughts-on-java.org
  34. 34. • Besser, benötigte Relationen direkt mit laden: • (FetchType.EAGER) • Fetch Join • @NamedEntityGraph • EntityGraph www.thoughts-on-java.org N+1Selects
  35. 35. • 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 FetchJoin
  36. 36. Demo (Projekt LazyLoading) www.thoughts-on-java.org
  37. 37. • 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 FetchJoin
  38. 38. • Neu in JPA 2.1 • Definiert einen zu ladenden Entitätsgraphen • @NamedEntityGraph • @NamedAttributeNode • @NamedSubGraph www.thoughts-on-java.org NamedEntityGraph
  39. 39. • 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 NamedEntityGraph
  40. 40. Demo (Projekt LazyLoading) www.thoughts-on-java.org
  41. 41. • Vorteile: • Queryspezifisches EAGER-loading • Definition des Graphen unabhängig von der Abfrage • Nachteile: • Bildet kartesisches Produkt www.thoughts-on-java.org NamedEntityGraph
  42. 42. • Neu in JPA 2.1 • Dynamische Variante des @NamedEntityGraph • Definition mittels Java API • EntityManager.createEntityGraph(Class entity) • EntityGraph • SubGraph www.thoughts-on-java.org EntityGraph
  43. 43. Demo (Projekt LazyLoading) www.thoughts-on-java.org
  44. 44. • 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 EntityGraph
  45. 45. 3. Caching www.thoughts-on-java.org
  46. 46. www.thoughts-on-java.org DB 2nd Level Cache 1st Level Cache Hibernate Session Query Cache 1st Level Cache Hibernate Session Caches
  47. 47. • 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 Caches
  48. 48. 3.1 1st Level Cache www.thoughts-on-java.org
  49. 49. • Automatisch aktiviert • Sessioninterner Speicher verwendeter Entities • Zugriff erfolgt transparent www.thoughts-on-java.org 1stLevelCache
  50. 50. Demo (Projekt 1stLevelCaching) www.thoughts-on-java.org
  51. 51. 3.2 2nd Level Cache www.thoughts-on-java.org
  52. 52. • 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 2ndLevelCache
  53. 53. • 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 2ndLevelCache
  54. 54. • 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 2ndLevelCache
  55. 55. Demo (Projekt 2ndLevelCaching) www.thoughts-on-java.org
  56. 56. • 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 2ndLevelCache
  57. 57. • Cache Retrieve Mode • CacheRetrieveMode.USE (default) • Daten werden aus Cache gelesen • CacheRetrieveMode.BYPASS • Daten werden aus DB gelesen www.thoughts-on-java.org 2ndLevelCache
  58. 58. • 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 2ndLevelCache
  59. 59. Demo (Projekt 2ndLevelCaching) www.thoughts-on-java.org
  60. 60. • Concurrency Strategy • JPA: Definition erfolgt global • Hibernate: Definition erfolgt spezifisch für jede Entity • @org.hibernate.annotations.Cache www.thoughts-on-java.org 2ndLevelCache
  61. 61. • 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 2ndLevelCache
  62. 62. 3.3 Query Cache www.thoughts-on-java.org
  63. 63. • 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 QueryCache
  64. 64. • 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 QueryCache
  65. 65. Demo (Projekt QueryCaching) www.thoughts-on-java.org
  66. 66. • 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 Empfehlung
  67. 67. • JSR 338: JavaTM Persistence API, Version 2.1 http://download.oracle.com/otndocs/jcp/persistence-2_1-fr-eval- spec/index.html • Hibernate Reference Documentation http://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 Quellen
  68. 68. • 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 Quellen
  69. 69. Noch Fragen? www.thoughts-on-java.org

×