Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

54
Effiziente Datenpersistierung mit JPA 2.1 und Hibernate JavaLand 2016 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 und Hibernate

JavaLand 2016

www.thoughts-on-java.org

Page 2: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Thor

ben J

anss

en • Independent author and trainer• Senior developer and architect @ Qualitype GmbH

• CDI 2.0 expert group member

• Twitter: @thjanssen123• Blog: www.thoughts-on-java.org

www.thoughts-on-java.org

Page 3: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Performance

www.thoughts-on-java.org

Page 4: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Perfo

rman

ce • Recognize performance problems as early as possible

• Typical causes for performance problems

• Solving performance problems

www.thoughts-on-java.org

Page 5: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Hibernate Statistics

www.thoughts-on-java.org

Page 6: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Hibe

rnat

e Sta

tistic

s• Activate via system property

• hibernate.generate_statistics = true

• Configure logging

• org.hibernate.stat = DEBUG

www.thoughts-on-java.org

Page 7: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Hibe

rnat

e Sta

tistic

s08:24:10,916 DEBUG [org.hibernate.stat.internal.ConcurrentStatisticsImpl] (default task-1) HHH000117: HQL: SELECT a FROM Authora WHERE a.lastName = :lastName, time: 6ms, rows: 1

www.thoughts-on-java.org

Time spend forthis query Number of

returnedrows

Page 8: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Hibe

rnat

e Sta

tistic

s 08:08:04,960 INFO [org.hibernate.engine.internal.StatisticalLoggingSessionEventListener] (default task-2) Session Metrics {

1191522 nanoseconds spent acquiring 4 JDBC connections;433875 nanoseconds spent releasing 4 JDBC connections;4404058 nanoseconds spent preparing 6 JDBC statements;12458725 nanoseconds spent executing 6 JDBC statements;0 nanoseconds spent executing 0 JDBC batches;0 nanoseconds spent performing 0 L2C puts;0 nanoseconds spent performing 0 L2C hits;0 nanoseconds spent performing 0 L2C misses;586896 nanoseconds spent executing 1 flushes (flushing a total

of 2 entities and 2 collections);39434974 nanoseconds spent executing 1 partial-flushes

(flushing a total of 2 entities and 2 collections)

www.thoughts-on-java.org

Number of SQL statements

Cache usage

Time spend for SQL state-ments

Page 9: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Typical causes for performance problems

www.thoughts-on-java.org

Page 10: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Typi

cal C

ause

s• Slow SELECT statements

• Wrong FetchType

• Load same data multiple times

www.thoughts-on-java.org

Page 11: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Slow SELECT-statements

www.thoughts-on-java.org

Page 12: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Slow

SEL

ECTs

• In general no „real“ JPA or Hibernate problem

• Check generated SQL

• Check execution plan of the statement

• Check indexes

• Optimize SELECT statement

• Consider to use a native query

www.thoughts-on-java.org

Page 13: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Nativ

e Que

ry• Reasons to use native queries:

• JPQL supports only a subset of SQL

• Database specific features

• Native queries return an Object[] for each row

• Needs to be mapped programmatically or declaratively

www.thoughts-on-java.org

Page 14: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Resu

ltSet

Mapp

ing • Declarative mapping of query results

www.thoughts-on-java.org

@SqlResultSetMapping(

name = "myResultMapping ",

entities = {@EntityResult(...), …},

classes = {@ConstructorResult (…), …},

columns = {@ColumnResult(…), …}

)

this.em.createNativeQuery(“Select …", "myResultMapping")

Page 15: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Resu

ltSet

Mapp

ing

www.thoughts-on-java.org

@SqlResultSetMapping(

name = "myResultMapping",

entities = {@EntityResult(

entityClass = Author.class,

fields = {

@FieldResult(name = "id", column = „autId"),

…}

),

…},

classes = {@ConstructorResult (…), …},

columns = {@ColumnResult(…), …}

)

Page 16: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Resu

ltSet

Mapp

ing

www.thoughts-on-java.org

@SqlResultSetMapping(

name = "myResultMapping",

entities = {@EntityResult(...), …},

classes = {@ConstructorResult(

targetClass = BookPublisherValue.class,

columns = {

@ColumnResult(name = "title"),

…}

),

…},

columns = {@ColumnResult(…), …}

)

Page 17: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Resu

ltSet

Mapp

ing

www.thoughts-on-java.org

@SqlResultSetMapping(

name = "myResultMapping",

entities = {@EntityResult(...), …},

classes = {@ConstructorResult(...), …},

columns = {@ColumnResult(

name = "bookCount",

type = Long.class),

…},

)

Page 18: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

FetchType

www.thoughts-on-java.org

Page 19: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Fetc

hTyp

e• Defines when the relationship will be fetched

• Static definition in entity mapping

www.thoughts-on-java.org

@ManyToMany(mappedBy="authors", fetch = FetchType.EAGER)

private Set<Book> books;

Page 20: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Fetc

hTyp

e• Lazy

• Relationship gets loaded at first access

• Default for to-many relationships

• Eager

• Loads relationships immediately

• Default for to-one relationships

www.thoughts-on-java.org

Page 21: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Reco

mmen

datio

ns • To-many relationships

• Stick to the default mapping (FetchType.LAZY)

• Use eager fetching for specific queries, if required

• To-one relationships

• Check individually

• Default is fine in most of the cases

www.thoughts-on-java.org

Page 22: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Query Specific Fetching

www.thoughts-on-java.org

Page 23: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

N+1 S

elect

?• Most common cause for performance problems

• Lazy fetching of related entities creates too many queries

www.thoughts-on-java.org

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().size() + “ Books.”));

}

Page 24: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Quer

y spe

cific

fetc

hing

• Fetch all required entities with one query

• Fetch Joins

• @NamedEntityGraph

• EntityGraph

www.thoughts-on-java.org

Page 25: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Fetch Join

www.thoughts-on-java.org

Page 26: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Fetc

hJoin

• Use JOIN FETCH instead of JOIN in JPQL query

www.thoughts-on-java.org

List<Author> authors = this.em.createQuery(

"SELECT DISTINCT a FROM Author a JOIN FETCH a.books b",

Author.class).getResultList();

Page 27: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Fetc

hJoin

• Advantages

• Relationships gets loaded in same query

• Disadvantages

• Requires a special query for each use case

• Creates cartesian product

www.thoughts-on-java.org

Page 28: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

NamedEntityGraph

www.thoughts-on-java.org

Page 29: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Name

dEnt

ityGr

aph

• Introduced in JPA 2.1

• Declaratively defines a graph of entities which will be loaded

• Graph is query independent

www.thoughts-on-java.org

Page 30: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Name

dEnt

ityGr

aph

• Define NamedEntityGraph

www.thoughts-on-java.org

@NamedEntityGraph(

name = "graph.AuthorBooksReviews",

attributeNodes =

@NamedAttributeNode(value = "books")

)

@NamedEntityGraph(

name = "graph.AuthorBooksReviews",

attributeNodes =

@NamedAttributeNode(value = "books", subgraph = "books"),

subgraphs =

@NamedSubgraph(

name = "books",

attributeNodes = @NamedAttributeNode("reviews")

)

)

Page 31: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Name

dEnt

ityGr

aph

• Provide entity graph es hint

www.thoughts-on-java.org

EntityGraph graph = this.em.getEntityGraph("graph.AuthorBooks");

this.em.createQuery("SELECT DISTINCT a FROM Author a")

.setHint("javax.persistence.loadgraph", graph);

Page 32: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Name

dEnt

ityGr

aph

• Fetch graph• Eager loading for all elements of the graph• Lazy loading for all other attributes

• Load graph• Eager loading for all elements of the graph• Loads all other attributes with their defined FetchType

• Hibernate always uses a load graph• HHH-8776

www.thoughts-on-java.org

Page 33: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Name

dEnt

ityGr

aph

• Advantages

• Query specific EAGER loading

• Definition of the graph is independent of the query

• Disadvantages

• Creates cartesian product

www.thoughts-on-java.org

Page 34: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

EntityGraph

www.thoughts-on-java.org

Page 35: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Entit

yGra

ph• Introduced in JPA 2.1

• Dynamic version of @NamedEntityGraph

• Definition via Java API

• Graph is query independent

www.thoughts-on-java.org

Page 36: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Entit

yGra

ph• Define and use EntityGraph

www.thoughts-on-java.org

EntityGraph graph = this.em.createEntityGraph(Author.class);

Subgraph<Book> bookSubGraph = graph.addSubgraph(Author_.books);

bookSubGraph.addSubgraph(Book_.reviews);

this.em.createQuery("SELECT DISTINCT a FROM Author a")

.setHint("javax.persistence.loadgraph", graph);

Page 37: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Entit

yGra

ph• Advantages

• Query specific EAGER loading

• Definition of the graph is independent of the query

• Dynamic creation at runtime

• Disadvantages

• Creates cartesian product

www.thoughts-on-java.org

Page 38: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Caching

www.thoughts-on-java.org

Page 39: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Query Cache

Cach

es

www.thoughts-on-java.org

DB

2nd

Level Cache

1st

Level Cache

HibernateSession

1st

Level Cache

HibernateSession

Page 40: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

1st Level Cache

www.thoughts-on-java.org

Page 41: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

1stLe

vel C

ache • Activated by default

• Linked to the Hibernate session

• Stores all entities that were used within a session

• Transparent usage

www.thoughts-on-java.org

Page 42: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

2nd Level Cache

www.thoughts-on-java.org

Page 43: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

2ndLe

vel C

ache

• Session independent entity store

• Needs to be activated• persistence.xml or EntityManagerFactory

• Transparent usage

• PersistenceProvider doesn‘t need to provide it• Not always portable

www.thoughts-on-java.org

Page 44: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

2ndLe

vel C

ache

• Shared Cache Mode

• ALL cache all entities

• NONE cache no entities

• ENABLE_SELECTIVE cache needs to be activated for specific entities

• DISABLE_SELECTIVE cache can be deactivated for specific entities

• UNSPECIFIED use default settings of the PersistenceProvider

www.thoughts-on-java.org

Page 45: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

2ndLe

vel C

ache

• Cache configuration

• Cache Retrieve Mode

• How to read entities from the cache

• Cache Store Mode

• How to write entities to the cache

• Concurrency Strategy

• How to handle concurrent access

www.thoughts-on-java.org

Page 46: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Query Cache

www.thoughts-on-java.org

Page 47: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Quer

y Cac

he• Hibernate specific

• Stores query result session independent

• Needs to be activated (persistence.xml)• hibernate.cache.use_query_cache = true

• Activate caching for a specific query• org.hibernate.Query.setCacheable(true)• @NamedQuery(… hints =

@QueryHint(name="org.hibernate.cacheable", value="true"))

www.thoughts-on-java.org

Page 48: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Quer

y Cac

he• Stores query results for a query and its parameters

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

• Stores only entity references or scalars

• Always use together with 2nd Level Cache

www.thoughts-on-java.org

Page 49: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Reco

mmen

datio

ns • Only cache data that is seldom updated

• Always benchmark the application when adding or changing caching

• Use Query Cache together with 2nd Level Cache

• Configuration has to fit to each other

www.thoughts-on-java.org

Page 50: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Slides & Cheat Sheet

www.thoughts-on-java.org

Page 51: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Get this presentation and a handy cheat sheet:

http://www.thoughts-on-java.org/javaland2016/

Follow me on twitter:@thjanssen123

www.thoughts-on-java.org

Page 52: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Resources

www.thoughts-on-java.org

Page 53: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Reso

urce

s• 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

www.thoughts-on-java.org

Page 54: Effiziente Datenpersistierung mit JPA 2.1 und Hibernate

Reso

urce

s• Java Persistence with Hibernate Second Edition by Christian

Bauer, Gaving King, Gary Gregory• 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