Transcript
Page 1: Real life persistence

Arne Limburg | open knowledge GmbH

Real Life Persistence

Page 2: Real life persistence

Arne LimburgHead of Architecture and Technologyopen knowledge GmbH

@ArneLimburg@_openknowledge

www.openknowledge.de

Meine Person

Page 3: Real life persistence

Beispiel

Page 4: Real life persistence

N + 1 SELECTS

Page 5: Real life persistence

Lazy Loading

Page 6: Real life persistence

Lazy Loading

Problemstellung:

Wann werden die Daten aus der Datenbank geladen?

Beispiel:

Customer customer = entityManager.find(Customer.class, id);Address address = customer.getAddress();String street = address.getStreet();

//Wann wird die Adresse aus der Datenbank geladen?

Page 7: Real life persistence

Lazy Loading

Möglichkeit 1: Wenn ein User geladen wird, werden alle angehängten Objekte mitgeladen!

Problem: Wenn alle Objekte zusammenhängen, wird bei jedem Select der gesamte Datenbank-Inhalt geladen!

Page 8: Real life persistence

Lazy Loading

Möglichkeit 2: Anhängende Objekte werden nie mitgeladen!

Problem:

Customer customer = entityManager.find(Customer.class, id);Address address = customer.getAddress();String street = address.getStreet();//führt zu LazyInitializationException

Page 9: Real life persistence

Lazy Loading

Möglichkeit 3: Anhängende Objekte werden nachgeladen, wenn sie gebraucht werden!Vorgehen von JPA bei geöffnetem

EntityManagerBei geschlossenem EntityManager führt Zugriff

auf nicht geladene Entitäten zu einem Fehler

Page 10: Real life persistence

Lazy Loading

Beeinflussungsmöglichkeiten des Nachladens

>Mapping

>Query

>Manuell (Test über PersistenceUnitUtil)

>Entity Graph Neu ab JPA 2.1

Page 11: Real life persistence

Lazy Loading

Nachladen beeinflussen über Mapping

>fetch-Attribut an

>@ManyToOne (default EAGER)

>@OneToOne (default EAGER)

>@OneToMany (default LAZY)

>@ManyToMany (default LAZY)

Page 12: Real life persistence

Lazy Loading

Nachladen beeinflussen über Query

>Angabe von join fetch in JPQL

>Angabe von root.fetch(…)in Criteria

Page 13: Real life persistence

Lazy Loading

Manuell

>Zugriff auf Objekt führt zu Nachladen

>Überprüfen des Ladezustandes mit PersistenceUnitUtil>Über EntityManagerFactory

>Zusätzlich Möglichkeit, die Id zu erhalten

Neu seit JPA 2

Page 14: Real life persistence

Entity Graph

>Spezifikation des Fetch-Verhaltens

>Find-Operationen (via Map)

>Queries (via setHint)

>Angabe über

>javax.persistence.fetchgraph Alle nicht enthaltenen Attribute lazy

>javax.persistence.loadgraph Alle nicht enthaltenen Attribute default

Neu seit JPA 2.1

Page 15: Real life persistence

@NamedEntityGraph( name = "User.fetchRoles", attributeNodes = { @NamedAttributeNode("name"), @NamedAttributeNode(value = "roles", subgraph = "role") }, subgraphs = { @NamedSubgraph(name = "role", attributeNodes = …)}) public class User {

Entity Graph

Page 16: Real life persistence

EntityGraph<User> userGraph = entityManager .createEntityGraph(User.class);userGraph.addAttributeNode(User_.name);Subgraph<Role> role = userGraph.addSubgraph(User_.roles);role.addAttributeNode(…);

Entity Graph

Page 17: Real life persistence

Proxy vs. Enhancement

Page 18: Real life persistence

Proxy vs. Enhancement

Aufpassen bei

>equals>Subclassing

>Serialisierung

>Lazy to-one-Beziehungen

Page 19: Real life persistence

New

Managed Detached

Removed

entityManager.persistentityManager.remove

entityManager.detachentityManager.clearentityManager.close

entityManager.mergeentityManager.findquery.getResultList()query.getSingleResult()

Entity-Lebenszyklus

entityManager.merge

Page 20: Real life persistence

New

Managed

Removed

entityManager.persistentityManager.merge

entityManager.remove

entityManager.detachentityManager.close

entityManager.mergeentityManager.findquery.getResultList()query.getSingleResult()

Entity-Lebenszyklus

Detached

Achtung:

Lazy-Initialization nicht im Zustand „detached“

Page 21: Real life persistence

Wann wird der EntityManagereigentlich geschlossen?

Page 22: Real life persistence

Fragestellungen

>EntityManager

>Container- vs. Application-Managed

>Transactional vs. Extended

>Transaction

>JTA vs. Resource Local

>Synchronized vs. Unsynchronized

>Datasource

>JNDI vs. local

>JTA vs. Non-JTA

Page 23: Real life persistence

Application-Managed

>Erzeugung via emf.createEntityManager(…)

>Transaktionsbehandlung (Manuell)

>JTA em.joinTransaction()>RESOURCE_LOCAL em.getTransaction().begin() em.getTransaction().commit()

>Scope EXTENDED (Manuelle Verwaltung)

Page 24: Real life persistence

Application-Managed

>Erzeugung via emf.createEntityManager(…)

>Transaktionsbehandlung (Manuell)

>JTA em.joinTransaction()>RESOURCE_LOCAL em.getTransaction().begin() em.getTransaction().commit()

>Scope EXTENDED (Manuelle Verwaltung)

Nachteil:

Keine PerstenceContext-Propagation!

Page 25: Real life persistence

Container-Managed

Variante 1

>Session Bean (Stateful oder Stateless)

>Transaktionsgrenze: Business-Methode (Transaction-Propagation)

>Beeinflussung durch @TransactionAttribute

>Scope:

>Transactional

>Mit Persistence-Context-Propagation

Page 26: Real life persistence

@Stateless public class UserDaoEjb { @PersistenceContext private EntityManager em; …

}

Transaction-Scoped

Page 27: Real life persistence

@Stateless public class UserDaoEjb { @PersistenceContext private EntityManager em; …

}

@Stateless public class UserDaoEjb { @PersistenceContext private EntityManager em; …

public void businessMethod() { // EntityManager available } }

Transaction-Scoped

Page 28: Real life persistence

@Stateless public class UserDaoEjb { @PersistenceContext private EntityManager em; …

}

@Stateless public class UserDaoEjb { @PersistenceContext private EntityManager em; …

public void businessMethod() { // EntityManager available } }

@Stateless public class UserDaoEjb { @PersistenceContext private EntityManager em; … @TransactionAttribute(NEVER) public void businessMethod() { // EntityManager not available } }

Transaction-Scoped

Page 29: Real life persistence

Transaktions-grenze

Vorsicht mit Lazy-Initialization

Java-EE-5 Architektur

Page 30: Real life persistence

Container-Managed

Variante 2

>Stateful Session Bean

>EXTENDED EntityManager

>Transaktionsgrenze

wie bei Variante 1

>Lesen ohne Transaktion

Lazy-Loading möglich

>Scope Session

Page 31: Real life persistence

@Stateful public class UserDaoEjb { @PersistenceContext(type = EXTENDED) private EntityManager em; …

}

@Stateful public class UserDaoEjb { @PersistenceContext(type = EXTENDED) private EntityManager em; …

public void businessMethod() { // EntityManager available } }

@Stateful public class UserDaoEjb { @PersistenceContext(type = EXTENDED) private EntityManager em; … @TransactionAttribute(NEVER) public void businessMethod() { // EntityManager available } }

Session-Scoped

Page 32: Real life persistence

@Stateful public class UserDaoEjb { @PersistenceContext( synchronization = UNSYNCHRONIZED) private EntityManager em; …

}

@Stateful public class UserDaoEjb { @PersistenceContext( synchronization = UNSYNCHRONIZED) private EntityManager em; … public void businessMethod() {

// no flush after invocation } }

@Stateful public class UserDaoEjb { @PersistenceContext( synchronization = UNSYNCHRONIZED) private EntityManager em; … public void businessMethod() { em.joinTransaction(); // flush‘n‘commit after invocation } }

Neu seit JPA 2.1

Unsynchronized

Page 33: Real life persistence

Container-Managed

Zusatz-Feature Java EE 6

>Service-Schicht als EJBs

>DAO-Schicht als CDI Beans

>EJB stellt EntityManager zur Verfügung @Produces

>Injection des EntityManagers in CDI-Beans @Inject

Page 34: Real life persistence

Producer für CDI

@Stateless public class UserServiceEjb { @Produces @PersistenceContext private EntityManager em; … }

public class UserDao { @Inject private EntityManager em; }

Page 35: Real life persistence

Fazit EJB-Integration

>Injection in Session Beans (stateful und stateless)

>Transaktionsgrenze

>Methodenaufruf der Session Bean (inklusive Transaction-Propagation)

>Scopes

>Transaction (alle Session Beans)

>Session (Stateful Session Beans)

Page 36: Real life persistence

public class MyEntityListener { @Inject @Current private User user;

@PrePersist public void setCreator(MyEntity e) { e.setCreator(user); } }

Neu seit JPA 2.1

CDI-Integration

Page 37: Real life persistence

public class MyEntityListener { @Inject @Current private User user;

@PrePersist public void setCreator(MyEntity e) { e.setCreator(user); } }

Achtung:

Verhalten bei Zugriff auf andere Entitäten oder Verändern von Beziehungen ist nicht

standardisiert.

Neu seit JPA 2.1

CDI-Integration

Page 38: Real life persistence

CDI bietet viele Scopes und ausgefeiltes

Lifecycle-Management!

Kann das nicht für den EntityManager genutzt werden?

CDI-Integration außerhalb des Standards

Page 39: Real life persistence

@ApplicationScopedpublic class MyPersistenceUnit { @Produces @RequestScoped public EntityManager createEntityManager( EntityManagerFactory factory) { return factory.createEntityManager(); } …}

Request-Scoped EntityManager

Page 40: Real life persistence

@ApplicationScopedpublic class MyPersistenceUnit { …

public void closeEntityManager( @Disposes EntityManager entityManager) {

entityManager.close(); }}

Lifecycle-Management von CDI

Page 41: Real life persistence

EntityManagerlifecycle

Lazy-Initializationmöglich

Architektur mit CDI

Page 42: Real life persistence

EntityManagerlifecycle

Lazy-Initializationmöglich

Offen:

Transaktionsgrenze

Architektur mit CDI

Page 43: Real life persistence

@Transactional @Interceptorpublic class MyTransactionalInterceptor { @Inject private EntityManager em;

…}

CDI-Interceptor

Page 44: Real life persistence

… @AroundInvoke public Object startTransaction( InvocationContext context) throws … { em.getTransaction().begin(); try { return context.proceed(); } finally { em.getTransaction().commit(); } }

CDI-Interceptor

Page 45: Real life persistence

@ApplicationScopedpublic class MyUserDao { @Inject private EntityManager em;

@Transactional public void persist(User user) { em.persist(user); }}

CDI-Interceptor

Page 46: Real life persistence

@ApplicationScopedpublic class MyPersistenceUnit { @Produces @RequestScoped public EntityManager createEntityManager( EntityManagerFactory factory) { return factory.createEntityManager(); } …}

Weitere Scopes

Page 47: Real life persistence

@ApplicationScopedpublic class MyPersistenceUnit { @Produces @ConversationScoped public EntityManager createEntityManager( EntityManagerFactory factory) { return factory.createEntityManager(); } …}

Conversation-Scope?

Page 48: Real life persistence

@Stateful @ConversationScoped public class UserServiceEjb { @Produces @RequestScoped @PersistenceContext(type = EXTENDED) private EntityManager em; … }

Producer für CDI

Page 49: Real life persistence

@Stateful @ConversationScoped public class UserServiceEjb { @Produces @RequestScoped @PersistenceContext(type = EXTENDED) private EntityManager em; … }

Passivation nur in einigen Containern

Producer für CDI

Page 50: Real life persistence

Asynchronität

Page 51: Real life persistence

By default, session bean invocationsthrough the Remote, Local, and no-

interface views are synchronous.Clients can achieve asynchronous

invocation behavior by invoking session bean methods that

have been designed to support asynchrony.

@Asynchronous

Zitat: EJB Spezifikation, v 3.1

Page 52: Real life persistence

@Asynchronous

EJB 3.1 Asynchronität

>Leichtgewichtig (analog zu Java SE) java.util.concurrent.Future

>Markierung via @Asynchronous>Methodensignatur

>Parameter beliebig

>Rückgabewert Future oder void

Page 53: Real life persistence

@Asynchronous

@Asynchronouspublic void broadcast(List<Email> receipients, String message) { …}

@Asynchronouspublic Future<Result> compute(…) { … return new AsynchResult<Result>(…);}

Page 54: Real life persistence

java.util.concurrent.Future

public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}

Page 55: Real life persistence

@Asynchronous Pro & Contra

>Einfacher Mechanismus >Separate Transaktion >Separater EntityManager

>Potentiell „gefährlich“

>Anzahl gestarteter Threads nicht limitierbar

>Thread Leaks (Threads die nicht enden bis zum

Restart des Containers)

>EntityManager ist Single-Threaded> 7

6

Page 56: Real life persistence

Locking

Page 57: Real life persistence

Locking

Optimistic

>@VersionProgrammatisches Locken

>EntityManager - lock , find , refresh>Query - setLockMode>@NamedQuery - lockMode-Element

Page 58: Real life persistence

Lock-Modes

>READ (deprecated)

>WRITE (deprecated)

>OPTIMISTIC

>OPTIMISTIC_FORCE_INCREMENT

>PESSIMISTIC_READ

>PESSIMISTIC_WRITE

>PESSIMISTIC_FORCE_INCREMENT

>NONE

Page 59: Real life persistence

Caching

Page 60: Real life persistence

Caching

Der First-Level-Cache

>EntityManager-Cache

>Caching von Entitäten

Page 61: Real life persistence

Caching

Der Second-Level-Cache

>EntityManagerFactory-Cache

>Implementierung provider-spezifisch

>Zugriff über Ids

Page 62: Real life persistence

Konfiguration

persistence.xml<persistence ...> <persistence-unit name="Weblog" ...>

<class>...</class>

<shared-cache-mode>ALL</shared-cache-mode>

<!– alternativ --> <properties> <property name="javax.persistence.sharedCache.mode" value="ALL" /> </properties> </persistence-unit></persistence>

Page 63: Real life persistence

SharedCacheMode

>ALL>NONE>ENABLE_SELECTIVE>DISABLE_SELECTIVE>UNSPECIFIED

Page 64: Real life persistence

@Entity @Cachable // = @Cachable(true) public class User { … }

Caching

Page 65: Real life persistence

@Entity @Cachable(false) public class User { … }

Caching

Page 66: Real life persistence

@Entity // Keine Cache-Annotation public class User { … }

Caching

Page 67: Real life persistence

Caching

EntityManagerFactory.getCache()Abfragen und Löschen des Cache-Inhalts

Beeinflussen des Cache-Verhaltens bei einzelnen Operationen:

>javax.persistence.cache.retrieveMode>javax.persistence.cache.storeMode

Page 68: Real life persistence

Caching

>CacheRetrieveMode

>USE (default)

>BYPASS>CacheStoreMode

>USE (default)

>BYPASS>REFRESH

Page 69: Real life persistence

JPA vs. NoSQL

Page 70: Real life persistence

JPA vs. NoSQL

JPA

>Halten der Daten im Heap

>Verwaltung von Objekten mit Klassenstruktur (Java-Objekte)

NoSQL

>Verwalten großer Datenmengen

>Verwalten von unstrukturierten Objekten (Dokumente, JSON-Objekte)

Page 71: Real life persistence

JPA und NoSQL

Page 72: Real life persistence

JPA und NoSQL

>Abfragen beider Datastores

>Relational für strukturierte Daten

>NoSQL für unstrukturierte Daten

>Zusammenführen beider Ergebnisse im Speicher

>Übertragen der NoSQL-Daten in Map

Page 73: Real life persistence

Vielen Dank für Ihre Zeit.

Kontakt:

open knowledge GmbHBismarckstr. 1326122 Oldenburg

[email protected]

@ArneLimburg @_openknowledge

Questions & Answers


Top Related