THE How real PERSISTENCE break the OF POVERTY vicious cycles
Real life persistence
-
Upload
open-knowledge-gmbh -
Category
Technology
-
view
323 -
download
0
description
Transcript of Real life persistence
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
@ArneLimburg @_openknowledge
Questions & Answers