Vermeidung von Performance-Problemen beim Einsatz von JPA

Fallstricke bei der Verwendung von Eager Loading für Listen referenzierter Objekte

14. Mai 2014Dr. Rafael Schirru

Die Java Persistence API (JPA) ist eine weit verbreitete Schnittstelle zur Verwaltung der Persistenz von Java-Objekten in relationalen Datenbanken (Lösung der objektrelationalen Abbildung). Als Entwickler mögen wir JPA, da es uns das manuelle Erstellen des Datenbankschemas erspart, dabei Unabhängigkeit vom Datenbank-Provider verspricht und wir in unseren Projekten schnell zu vorzeigbaren Ergebnissen kommen. Ein Fallstrick dieser Technologie sind Performance-Probleme, von denen immer wieder berichtet wird. Insbesondere für Web-Anwendungen ist es essenziell, diese zu vermeiden, da kurze Antwortzeiten zur Realisierung einer positiven Benutzererfahrung unverzichtbar sind. In diesem Beitrag diskutiere ich die Verwendung von Eager Loading für Listen referenzierter Objekte und zeige auf, wie Performance-Probleme beim Einsatz der Technologie vermieden werden können.

 

Was ist Eager Loading und wieso kann es zu Performance-Problemen führen?

JPA bietet die Möglichkeit, über Referenzen zwischen unterschiedlichen Objekten zu navigieren. Ein Objekt Bestellung kann beispielsweise in der Variablen bestellpositionen eine Liste mit Objekten vom Typ Bestellposition referenzieren, die über eine entsprechende Getter-Methode zugreifbar ist. Ist für die Variable oder ihren Getter Eager Loading aktiviert, so stellt JPA sicher, dass beim Zugriff auf ein konkretes Objekt vom Typ Bestellung die Variable bestellpositionen mit den referenzierten Objekten initialisiert ist. Jede Bestellposition kann jedoch ihrerseits weitere Referenzen besitzen, z.B. auf ein Produkt, welches seinerseits Hersteller referenziert usw. Abbildung 1 veranschaulicht exemplarisch ein solches Datenmodell mit einer Liste von referenzierten Objekten und weiteren transitiven Referenzen. Sollen nun alle Bestellungen eines Kunden geladen und angezeigt werden, so würde JPA, falls Eager Loading für die Variable bestellpositionen aktiviert ist, alle referenzierten Objekte und deren transitive Abhängigkeiten laden und zur Laufzeit zur Verfügung stellen. Dabei kann das Laden der benötigten Objekte und ihrer Referenzen, welche ggf. in einem konkreten Szenario gar nicht benötigt werden, zahlreiche Datenbankabfragen verursachen und somit die Antwortzeit des Systems deutlich erhöhen.

adessoAG_Blog Fallstricke_JPA
Abbildung 1 Exemplarisches Datenmodell mit einer Liste von referenzierten Objekten und weiteren transitiven Referenzen

 

Wie können Performance-Probleme vermieden werden?

Für den Entwickler ist es wichtig, einen genauen Überblick über die transitiven Objekt-Referenzen, sowie den Umfang der automatisch geladenen Daten zu haben. Im Allgemeinen rate ich von der Benutzung von Eager Loading für Listen referenzierter Objekte ab. Dabei ist jedoch zu beachten, dass die benötigten Daten dann ggf. zur Laufzeit programmatisch nachgeladen werden müssen. Dies erfordert eine genaue Kenntnis, wann welche Daten im Programmablauf benötigt werden. In Fällen, in denen tatsächlich die Daten im vollen Umfang zur Verfügung stehen müssen, aber dennoch harte Anforderungen bzgl. der geforderten Antwortzeiten bestehen, sollte über den Einsatz einer Caching-Strategie nachgedacht werden.

 

Fazit

In den Händen erfahrener Entwickler ist JPA eine wertvolle Technologie zur Lösung des Problems der objektrelationalen Abbildung. Projekte, die JPA einsetzen, sollten bei der Definition des Datenmodells Eager Loading möglichst vermeiden oder nur in begründeten Ausnahmefällen einsetzen. Für den erfolgreichen Einsatz von JPA ist eine genaue Kenntnis, wann welche Daten im Programmablauf benötigt werden, unverzichtbar. Falls Sie beim Einsatz von JPA ebenfalls Performance-Probleme erlebt haben, freue ich mich, wenn Sie Ihre Erfahrungen in den Kommentaren mit uns teilen.

Dr. Rafael Schirru Dr. Rafael Schirru ist seit September 2013 Software Engineer bei adesso. Seine Interessensschwerpunkte sind Empfehlungssysteme, Textmining und Datenbank-Entwicklung mittels Java.
Artikel bewerten:
1 Star2 Stars3 Stars4 Stars5 Stars
Loading...

Kommentare

Martin Aulich 14. Mai 2014 Website des Autors

Sehr guter Beitrag!

Ich würde nur noch hinzufügen, dass die JPA 2.1 mit den EntityGraphs eine Möglichkeit geschaffen hat die Abhängigkeiten nicht statisch als Lazy / Eager zu deklarieren, sondern je nach konkretem Szenario zu entscheiden, welche (transitiven) Abhängigkeiten direkt mitgeladen werden sollen.

Unter: http://docs.oracle.com/javaee/7/tutorial/doc/persistence-entitygraphs001.htm finden sich mehr details.

Gruß
Martin

Sebastian Oerding 15. Mai 2014

Hmm, netter beitrag, aber für Anfänger bei JPA.

Wenn man eager loading diskutieren will, sollte man vielleicht etwas mehr auf die Interna eingehen. Zumindest sollte man erwähnen, dass lazy loading das Gegenstück dazu ist (bzw. siehe vorherigen Kommentar dazu).

Außerdem gibt es ja aufgrund der Manipulation des Bytecodes einige Stolpersteine, z.B. mit Tools (Testabdeckung), potentiell falls man Reflection benutzt bzw. in einer Implementierung von equals nicht die Getter benutzt (war zumindest bei JPA 2.0 / Hibernate mit lazy loading ein Problem, weil das andere Object zum dem Zeitpunkt nur ein proxy war und erst der Zugriff über die Getter zur vollständigen Initialisierung führte).

Gruß Sebastian

Kommentar hinzufügen:

Ihr Kommentar: