47
Arne Limburg | open knowledge GmbH @ArneLimburg @_openknowledge

JPA Pitfalls und unknown Features

Embed Size (px)

DESCRIPTION

Der JPA-Standard hat sich mittlerweile in Enterprise-Java-Projekten etabliert. Aber wie kann ich vorgehen, wenn ich ein Projekt nicht auf der grünen Wiese anfange, sondern auf einer Legacy-Datenbank aufsetzen muss, deren Struktur ich nicht verändern darf. Dieser Vortrag zeigt anhand von Praxisbeispielen, wie auch die schrägsten Datenbankschemas mit dem Java-Persistence-Standard realisiert werden können.

Citation preview

Page 1: JPA Pitfalls und unknown Features

Arne Limburg | open knowledge GmbH

@ArneLimburg @_openknowledge

Page 2: JPA Pitfalls und unknown Features

Meine Person Arne Limburg Head of Development open knowledge GmbH

@ArneLimburg @_openknowledge

www.openknowledge.de

Page 3: JPA Pitfalls und unknown Features

equals und hashCode

Page 4: JPA Pitfalls und unknown Features

equals und hashCode •  Object-Identity ≠ Datenbank-Identität •  Equals und HashCode basieren auf Id •  Keine Entitäten ohne Id in

HashSet / HashMap! – Vorher persistieren oder – andere Set- / Map-Implementierung

verwenden

Page 5: JPA Pitfalls und unknown Features

Id-Generierung

Page 6: JPA Pitfalls und unknown Features

Id-Generierung •  Niemals GenerationType.AUTO

verwenden! •  Nur GenerationType.TABLE ist

datenbank-unabhängig!

Page 7: JPA Pitfalls und unknown Features

Subclassing

Page 8: JPA Pitfalls und unknown Features

Subclassing •  Vorsicht bei

– Table-per-Class – Joined

•  Empfehlung Single-Table mit @SecondaryTable

•  Unknown Feature Abfragen der konkreten Klasse in JPQL mit TYPE(...)

Page 9: JPA Pitfalls und unknown Features

Lazy-Loading

Page 10: JPA Pitfalls und unknown Features

New

Managed Detached

Removed

entityManager.persist entityManager.merge

entityManager.remove

entityManager.detach entityManager.close

entityManager.merge entityManager.find query.getResultList() query.getSingleResult()

Entity-Lebenszyklus

Page 11: JPA Pitfalls und unknown Features

New

Managed

Removed

entityManager.persist entityManager.merge

entityManager.remove

entityManager.detach entityManager.close

entityManager.merge entityManager.find query.getResultList() query.getSingleResult()

Entity-Lebenszyklus

Detached

Achtung: Lazy-Initialization nicht im Zustand

„detached“

Page 12: JPA Pitfalls und unknown Features

Lazy Loading •  Explizites Fetchen

– via JPQL – via Criteria – Manuell – Ab JPA 2.1 Fetch-Graphs

•  Unknown Features – JPA Metadaten – PersistenceUnitUtil

Page 13: JPA Pitfalls und unknown Features

Lazy Loading •  Explizites Fetching (wie gesehen) •  Aufpassen mit N+1-SELECTs •  Unknown Features

EntityManager.getReference PersistenceUnitUtil

Page 14: JPA Pitfalls und unknown Features

Wann wird der EntityManager eigentlich geschlossen?

Page 15: JPA Pitfalls und unknown Features

Container-Managed Variante 1 •  Session Bean (Stateful oder Stateless)

– Transaktionsgrenze: Business-Methode (Transaction-Propagation)

– Beeinflussung durch @TransactionAttribute •  Scope:

– Transactional – Mit Persistence-Context-Propagation

Page 16: JPA Pitfalls und unknown Features

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

@Stateless public class UserRepositoryEjb { @PersistenceContext private EntityManager em; … public void businessMethod() { // EntityManager available } }

Transaction-Scoped

Page 17: JPA Pitfalls und unknown Features

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

@Stateless public class UserRepositoryEjb { @PersistenceContext private EntityManager em; … public void businessMethod() { // EntityManager available } }

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

Transaction-Scoped

Page 18: JPA Pitfalls und unknown Features

Java-EE-5-Architektur

Transaktions- grenze

Vorsicht mit Lazy- Initialization

Page 19: JPA Pitfalls und unknown Features

Container-Managed Variante 2 •  Stateful Session Bean •  EXTENDED EntityManager

– Transaktionsgrenze à wie bei Variante 1

– Lesen ohne Transaktion à Lazy-Loading möglich

– Scope Session

Page 20: JPA Pitfalls und unknown Features

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

Session-Scoped

Page 21: JPA Pitfalls und unknown Features

@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 22: JPA Pitfalls und unknown Features

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 23: JPA Pitfalls und unknown Features

Producer für CDI @Stateless public class UserServiceEjb { @Produces @PersistenceContext private EntityManager em; … } public class UserDao { @Inject private EntityManager em; }

Page 24: JPA Pitfalls und unknown Features

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 25: JPA Pitfalls und unknown Features

JPA und CDI

CDI bietet viele Scopes und ausgefeiltes Lifecycle-Management!

Kann das nicht für den EntityManager

genutzt werden?

Page 26: JPA Pitfalls und unknown Features

Application-Managed •  Erzeugung via

entityManagerFactory.createEntityManager(…)

•  Transaktionsbehandlung (Manuell) – JTA entityManager.joinTransaction() – RESOURCE_LOCAL entityManager.getTransaction().begin() entityManager.getTransaction().commit()

•  Scope EXTENDED (Manuelle Verwaltung)

Page 27: JPA Pitfalls und unknown Features

Application-Managed •  Erzeugung via

entityManagerFactory.createEntityManager(…)

•  Transaktionsbehandlung (Manuell) – JTA entityManager.joinTransaction() – RESOURCE_LOCAL entityManager.getTransaction().begin() entityManager.getTransaction().commit()

•  Scope EXTENDED (Manuelle Verwaltung)

Nachteil: Keine PerstenceContext-Propagation!

Page 28: JPA Pitfalls und unknown Features

Request-Scoped EntityManager @ApplicationScoped public class MyPersistenceUnit { @Produces @RequestScoped public EntityManager createEntityManager( EntityManagerFactory factory) { return factory.createEntityManager(); } … }

Page 29: JPA Pitfalls und unknown Features

Lifecycle-Management von CDI @ApplicationScoped public class MyPersistenceUnit { … public void closeEntityManager( @Disposes EntityManager entityManager) { entityManager.close(); } }

Page 30: JPA Pitfalls und unknown Features

Architektur mit CDI EntityManager lifecycle

Lazy-Initialization möglich

Pitfall: transaction-type

Offen: Transaktionsgrenze

Page 31: JPA Pitfalls und unknown Features

CDI Interceptoren @Transactional @Interceptor public class MyTransactionalInterceptor { @Inject private EntityManager em; … }

Page 32: JPA Pitfalls und unknown Features

CDI Interceptoren @InterceptorBinding @Target({TYPE, METHOD, PARAMETER, FIELD}) @RETENTION(RUNTIME) public @interface Transactional { }

Page 33: JPA Pitfalls und unknown Features

CDI Interceptoren @Transactional @Interceptor public class MyTransactionalInterceptor { @Inject private EntityManager em; … }

Page 34: JPA Pitfalls und unknown Features

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

Page 35: JPA Pitfalls und unknown Features

CDI Interceptoren @ApplicationScoped public class MyUserDao { @Inject private EntityManager em; @Transactional public void persist(User user) { em.persist(user); } }

Page 36: JPA Pitfalls und unknown Features

Weitere Scopes? @ApplicationScoped public class MyPersistenceUnit { @Produces @RequestScoped public EntityManager createEntityManager( EntityManagerFactory factory) { return factory.createEntityManager(); } … }

Page 37: JPA Pitfalls und unknown Features

Conversation-Scope? @ApplicationScoped public class MyPersistenceUnit { @Produces @ConversationScoped public EntityManager createEntityManager( EntityManagerFactory factory) { return factory.createEntityManager(); } … }

Page 38: JPA Pitfalls und unknown Features

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

Page 39: JPA Pitfalls und unknown Features

Producer für CDI @Stateful @ConversationScoped public class UserServiceEjb { @Produces @PersistenceContext(type = EXTENDED) private EntityManager em; … }

Funktioniert aktuell nur mit Hibernate!

Page 40: JPA Pitfalls und unknown Features

Architektur mit CDI EntityManager lifecycle

Lazy-Initialization möglich

Page 41: JPA Pitfalls und unknown Features

Proxy vs. Enhancement

Page 42: JPA Pitfalls und unknown Features

Proxy vs. Enhancement •  Aufpassen bei

– equals – Subclassing – Serialisierung – Lazy to-one-Beziehungen

Page 43: JPA Pitfalls und unknown Features

Locking

Page 44: JPA Pitfalls und unknown Features

Locking Programmatisches Locken •  EntityManager

lock , find , refresh •  Query

setLockMode

• @NamedQuery lockMode-Element

Page 45: JPA Pitfalls und unknown Features

LockModeType • OPTIMISTIC (= READ) • OPTIMISTIC_FORCE_INCREMENT (= WRITE)

• PESSIMISTIC_READ • PESSIMISTIC_WRITE • PESSIMISTIC_FORCE_INCREMENT • NONE

Page 46: JPA Pitfalls und unknown Features

Unknown Features • javax.persistence.lock.timeout • javax.persistence.lock.scope

PessimisticLockScope – NORMAL – EXTENDED

Page 47: JPA Pitfalls und unknown Features

Vielen Dank für Ihre Zeit. Kontakt: open knowledge GmbH Bismarckstr. 13 26122 Oldenburg [email protected] @ArneLimburg @_openknowledge

Q&A