real life persistence

Post on 10-May-2015

327 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Mit JPA 2.1 wurde in Java EE 7 ein weiterer Schritt in Richtung Provider-Unabhängigkeit gegangen. Auch wenn damit weitere Möglichkeiten des Einsatzes mit JPA geschaffen wurden, gibt es in der Praxis weiterhin viele Dinge zu beachten.In der Session werden neben klassischen Architekturansetzen zum Einsatz von JPA auch weitergehende Herausforderungen diskutiert. Wie kann JPA im Zusammenhang mit den neuen JSRs für Batch-Verarbeitung und den Concurrency Utilities beleuchtet, die erweitere Möglichkeiten im Bereich Asynchronität bieten?

TRANSCRIPT

Arne Limburg | open knowledge GmbH

Real Life Persistence

Arne LimburgHead of Architecture and Technologyopen knowledge GmbH

@ArneLimburg@_openknowledge

www.openknowledge.de

Meine Person

Beispiel

N + 1 SELECTS

Lazy Loading

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?

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!

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

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

Lazy Loading

Beeinflussungsmöglichkeiten des Nachladens

>Mapping

>Query

>Manuell (Test über PersistenceUnitUtil)

>Entity Graph Neu ab JPA 2.1

Lazy Loading

Nachladen beeinflussen über Mapping

>fetch-Attribut an

>@ManyToOne (default EAGER)

>@OneToOne (default EAGER)

>@OneToMany (default LAZY)

>@ManyToMany (default LAZY)

Lazy Loading

Nachladen beeinflussen über Query

>Angabe von join fetch in JPQL

>Angabe von root.fetch(…)in Criteria

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

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

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

Entity Graph

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

Entity Graph

Proxy vs. Enhancement

Proxy vs. Enhancement

Aufpassen bei

>equals>Subclassing

>Serialisierung

>Lazy to-one-Beziehungen

New

Managed Detached

Removed

entityManager.persistentityManager.remove

entityManager.detachentityManager.clearentityManager.close

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

Entity-Lebenszyklus

entityManager.merge

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“

Wann wird der EntityManagereigentlich geschlossen?

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

Application-Managed

>Erzeugung via emf.createEntityManager(…)

>Transaktionsbehandlung (Manuell)

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

>Scope EXTENDED (Manuelle Verwaltung)

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!

Container-Managed

Variante 1

>Session Bean (Stateful oder Stateless)

>Transaktionsgrenze: Business-Methode (Transaction-Propagation)

>Beeinflussung durch @TransactionAttribute

>Scope:

>Transactional

>Mit Persistence-Context-Propagation

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

}

Transaction-Scoped

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

}

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

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

Transaction-Scoped

@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

Transaktions-grenze

Vorsicht mit Lazy-Initialization

Java-EE-5 Architektur

Container-Managed

Variante 2

>Stateful Session Bean

>EXTENDED EntityManager

>Transaktionsgrenze

wie bei Variante 1

>Lesen ohne Transaktion

Lazy-Loading möglich

>Scope Session

@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

@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

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

Producer für CDI

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

public class UserDao { @Inject private EntityManager em; }

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)

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

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

Neu seit JPA 2.1

CDI-Integration

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

CDI bietet viele Scopes und ausgefeiltes

Lifecycle-Management!

Kann das nicht für den EntityManager genutzt werden?

CDI-Integration außerhalb des Standards

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

Request-Scoped EntityManager

@ApplicationScopedpublic class MyPersistenceUnit { …

public void closeEntityManager( @Disposes EntityManager entityManager) {

entityManager.close(); }}

Lifecycle-Management von CDI

EntityManagerlifecycle

Lazy-Initializationmöglich

Architektur mit CDI

EntityManagerlifecycle

Lazy-Initializationmöglich

Offen:

Transaktionsgrenze

Architektur mit CDI

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

…}

CDI-Interceptor

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

CDI-Interceptor

@ApplicationScopedpublic class MyUserDao { @Inject private EntityManager em;

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

CDI-Interceptor

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

Weitere Scopes

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

Conversation-Scope?

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

Producer für CDI

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

Passivation nur in einigen Containern

Producer für CDI

Asynchronität

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

@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

@Asynchronous

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

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

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;}

@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

Locking

Locking

Optimistic

>@VersionProgrammatisches Locken

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

Lock-Modes

>READ (deprecated)

>WRITE (deprecated)

>OPTIMISTIC

>OPTIMISTIC_FORCE_INCREMENT

>PESSIMISTIC_READ

>PESSIMISTIC_WRITE

>PESSIMISTIC_FORCE_INCREMENT

>NONE

Caching

Caching

Der First-Level-Cache

>EntityManager-Cache

>Caching von Entitäten

Caching

Der Second-Level-Cache

>EntityManagerFactory-Cache

>Implementierung provider-spezifisch

>Zugriff über Ids

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>

SharedCacheMode

>ALL>NONE>ENABLE_SELECTIVE>DISABLE_SELECTIVE>UNSPECIFIED

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

Caching

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

Caching

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

Caching

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

Caching

>CacheRetrieveMode

>USE (default)

>BYPASS>CacheStoreMode

>USE (default)

>BYPASS>REFRESH

JPA vs. NoSQL

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)

JPA und NoSQL

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

Vielen Dank für Ihre Zeit.

Kontakt:

open knowledge GmbHBismarckstr. 1326122 Oldenburg

arne.limburg@openknowledge.de

@ArneLimburg @_openknowledge

Questions & Answers

top related