41
Java Persistence in Action Einsatz von JPA 2.x in Java-EE-Anwendungen Dirk Weil | GEDOPLAN

Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

Embed Size (px)

DESCRIPTION

Präsentation zum Vortrag von Dirk Weil (GEDOPLAN, http://www.gedoplan.de) auf der W-JAX 2012: Der überwiegende Teil von Unternehmensanwendungen nutzt O/R-Mapper zum Zugriff auf Datenbanken. Reicht dafür der Standard JPA 2.0 oder braucht man zwingend spezielle Eigenschaften von Hibernate/EclipseLink/OpenJPA? Soll man transaktionsgebunden oder konversationsorientiert arbeiten? Welche Neuerungen sind für JPA 2.1 geplant? Dieser Talk beantwortet die Fragen anhand diverser Beispiele aus der Praxis.

Citation preview

Page 1: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

Java Persistence in ActionEinsatz von JPA 2.x in Java-EE-Anwendungen

Dirk Weil | GEDOPLAN

Page 2: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Dirk Weil• GEDOPLAN GmbH, Bielefeld• Java EE seit 1998• Konzeption und

Realisierung• Vorträge• Seminare• Veröffentlichungen

Java Persistence in Action2

Page 3: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

ZEILEN

Java Persistence in Action3

Page 4: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Java Persistence in EE-Anwendungen• Basics:

– META-INF/persistence.xml referenziert Datasource

– EntityManager-Bereitstellung per Injektion

<persistence …>

<persistence-unit name="beantrial">

<jta-data-source>jdbc/beantrial</jta-data-source>

@PersistenceContext(unitName = "beantrial")

EntityManager entityManager;

Java Persistence in Action4

Page 5: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Java Persistence in EE-Anwendungen• The CDI way: public class EntityManagerProducer {

@PersistenceContext(unitName = "beantrial")

@Produces

EntityManager entityManager;

public class PersonRepository {

@Inject

EntityManager entityManager;

public class FirmaRepository {

@Inject

EntityManager entityManager;

public class ProjektRepository {

@Inject

EntityManager entityManager;

Java Persistence in Action5

Page 6: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Entity Manager Lifecycle• EM-Lebensdauer � Entity-Management-Zeit

– Entities werden detached– Nachladen von Lazy-Werten etc. nicht mehr möglich

alle evtl. benötigten Werte müssen geladen sein

• Remote-Anwendung (Swing, Java FX, …)– Entities im Client sind stets detached

• Web-Anwendung (JSF, …)– Render-Phase, Folgerequests?

Java Persistence in Action6

Page 7: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Entity Manager Lifecycle

@Model

public class PersonModel {

public List<Person> getPersonen() {

… personRepository.findAll() …

<h:dataTable value="#{personModel.personen}" var="person">

<h:… value="#{person.hobbies}" />

@Entity

public class Person {

@ElementCollection(fetch = FetchType.LAZY)

private List<String> hobbies;

LazyLoadException

?

Java Persistence in Action7

Page 8: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Entity Manager Lifecycle• EM-Optionen:

– Transaction-scoped– (Extended)*– Application-managed

• Patterns– Eager Loading– Open Entity Manager in View– Conversational Entity Manager

*nur Stateful EJBs – nicht weiter betrachtet

Java Persistence in Action8

verschiedene Kombinationen möglich

Page 9: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Transaction-scoped Entity Manager• Standard für container-managed Entity Manager

@Transactional

public class PersonRepository {

@Inject

EntityManager entityManager;

public void persist(Person entity) { … }

public List<Person> findAll() { … }

public class EntityManagerProducer {

@PersistenceContext(unitName = "beantrial")

@Produces

EntityManager entityManager;

Java Persistence in Action9

Page 10: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Transaction-scoped Entity Manager• Start: Erste Nutzung des EM in einer TX• Ende: TX-Ende � alle Entities werden detached

• TX-Steuerung– per CDI Interceptor @Transactional

– per EJB– mittels UserTransaction

– häufig für (Teil-)Geschäftsprozesse(nur für CRUD wäre ein Antipattern)

Java Persistence in Action10

Page 11: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Transaction-scoped Entity Manager

@Model

public class PersonModel {

public List<Person> getPersonen() {

… personRepository.findAll() …

<h:dataTable value="#{personModel.personen}" …>

<h:… value="#{person.hobbies}" />

@Transactional

public class PersonRepository {

public List<Person> findAll() { … }

DB

View

Model

ServiceTX

deta

ched

man

aged

Java Persistence in Action11

Page 12: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Transaction-scoped Entity Manager• Eager Loading nötig

– deklarativ

– oder durch explizitenZugriff

@ElementCollection(fetch = FetchType.EAGER)

private List<String> hobbies;

public void loadLazyAttributes() {

this.hobbies.size();

Java Persistence in Action12

Page 13: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Transaction-scoped Entity Manager• Code Browsing:

Personenverwaltung mit detached Entities

Java Persistence in Action13

(Download: www.gedoplan.de� Blog

Page 14: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Transaction-scoped Entity Manager• Alternative: Transaction per Request

@Model

public class PersonModel {

public List<Person> getPersonen() {

… personRepository.findAll() …

<h:dataTable value="#{personModel.personen}" …>

<h:… value="#{person.hobbies}" />

View

Model

TX

Java Persistence in Action14

Page 15: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Transaction-scoped Entity Manager• Transaction per Request

– mittels Servlet Filter– mittels JSF Phase Listener

– Seam Transaction / Seam FacesAchtung: Per Default aktiv !(Abschalten: Siehe www.gedoplan.de� Blog)

Java Persistence in Action15

Page 16: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Transaction-scoped Entity Manager• Einfaches Verfahren

• Eager Loading– ist aufwändig– hebelt Lazy-Optimierungen aus

• TX per Request– durchbricht 'normale' Architektur– nicht für Multi-Request-Fälle geeignet

Java Persistence in Action16

Page 17: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Application-managed Entity Manager• Nutzung von EntityManagerFactory

• Lifecycle wird von Anwendung bestimmtpublic class EntityManagerProducer {

@PersistenceUnit(unitName = "beantrial")

EntityManagerFactory entityManagerFactory;

@Produces

public EntityManager createEntityManager() {

return this.entityManagerFactory.createEntityManager();

}

public void closeEntityManager(@Disposes @Any EntityManager em) {

if (em.isOpen())

em.close();

}

Java Persistence in Action17

Page 18: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Application-managed Entity Manager• persist, merge, remove auch ohne TX erlaubt

• Änderungen werden erst durch Commit abgelegt• Entity Manager nicht automatisch TX-gebunden

@Transactional

public void saveAll() {

this.entityManager.joinTransaction();

}

Java Persistence in Action18

Page 19: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Request-scoped Entity Manager• Request

Scope= Open Entity Manager in View

@Produces

@RequestScoped

public EntityManager createEntityManager() {

Ent

ityM

anag

er

@Model

public class PersonModel {

public List<Person> getPersonen() {

… personRepository.findAll() …

<h:dataTable value="#{personModel.personen}" …>

<h:… value="#{person.hobbies}" />

@Transactional

public class PersonRepository {

public void saveAll() { … }

DB

View

Model

Service

TX

Java Persistence in Action19

Page 20: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

EM

EM

Conversation-scoped Entity Manager• Conversational

Entity Manager

@Produces

@ConversationScoped

public EntityManager createEntityManager() {

Request 2Conversation.begin()

Request 1

Request 3

Request 4Conversation.end()

Java Persistence in Action20

Page 21: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Conversation-scoped Entity Manager• ABER:

– Conversation Scope ist passivating– Objekte in ihm müssen serialisierbar sein– EntityManager nicht notwendigerweiseSerializable

• Abhilfe: Serializable-Wrapper

Java Persistence in Action21

Page 22: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Conversation-scoped Entity Manager• Serializable-Wrapper:

@Produces

@ConversationScoped

public EntityManager createEntityManager() {

EntityManager em = entityManagerFactory.createEntityManager();

if (!(em instanceof Serializable)) {

ClassLoader loader = em.getClass().getClassLoader();

Class<?>[] ifs = { EntityManager.class, Serializable.class };

EMInvocationHandler handler = new EMInvocationHandler(em);

em = (EntityManager) Proxy.newProxyInstance(loader, if, handler);

}

return em;

}

Java Persistence in Action22

Page 23: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Conversation-scoped Entity Manager• Serializable-Wrapper:

class EMInvocationHandler implements InvocationHandler, Serializable {

private transient EntityManager em;

public EntityManagerInvocationHandler(EntityManager em) {

this.em = em;

}

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

if (this.entityManager == null)

throw new IllegalStateException("EntityManager is null");

return method.invoke(this.em, args);

}

}

Java Persistence in Action23

Page 24: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Conversation-scoped Entity Manager• Serializable-Wrapper:

– Prinzip Hoffnung:Wahrscheinlich keine Passivierung;wenn doch, ordentliche Fehlermeldung.

– Ungeeignet für Replikation

Java Persistence in Action24

Page 25: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

Conversation-scoped Entity Manager• Code Browsing:

Personenverwaltung mit attached Entities

Java Persistence in Action25

(Download: www.gedoplan.de� Blog

Page 26: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

SQL-Zugriffe im Beispiel

Aktion TX-scoped EM Conv-scoped EM

Anzeige aller PersonenSELECT ID, ... FROM PERSON dito

Auswahl einer Person zum EditierenSELECT ID, ... FROM PERSON WHERE (ID = ?)

SELECT TEL, ... FROM PERSON_TELWHERE (PERSON_TEL.Person_ID = ?)

dito

SELECT HOBBY, ... FROM PERSON_HOBBYWHERE (PERSON_HOBBY.Person_ID = ?)

Java Persistence in Action26

Page 27: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

SQL-Zugriffe im Beispiel

Aktion TX-scoped EM Conv-scoped EM

Ändern des Vornamens und Speichern der PersonSELECT ID, ... FROM PERSONWHERE (ID = ?)

SELECT TEL, ... FROM PERSON_TELWHERE (PERSON_TEL.Person_ID = ?)

SELECT HOBBY, ... FROM PERSON_HOBBYWHERE (PERSON_HOBBY.Person_ID = ?)

UPDATE PERSON SET VORNAME = ?WHERE (ID = ?)

dito

Java Persistence in Action27

Page 28: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

TX- oder Conversation-scoped?• Transaction-scoped EM

� einfaches Vorgehen� speichert nur das, was explizit übergeben wird

• Conversation-scoped EM� vermeidet Lazy-Load-Effekte im Web-Anwendungen� erzeugt weniger DB-Zugriffe

� speichert immer alle Änderungen

� benötigt mehr Speicher� funktioniert nicht im Cluster oder für Remote-Clients

Java Persistence in Action28

Page 29: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – What's coming?• Query-Erweiterungen

– ON: Join-Filter

– TREAT: Downcast (inkl. Filterung)

– FUNCTION: Aufruf von DB-Funktionen

select p.name, count(b)

from Publisher p

left join p.books b

on b.bookType = BookType.PAPERBACK

group by p.name

select s from StorageLocation s

where treat(s.product as Book).bookType = BookType.HARDCOVER

select c from Customer c

where function('hasGoodCredit', c.balance, c.creditLimit)

Java Persistence in Action29

Page 30: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – What's coming?• Bulk Update/Delete für Criteria Query

• Stored Procedure Queries

CriteriaUpdate<Product> criteriaUpdate

= criteriaBuilder.createCriteriaUpdate(Product.class);

Root<Product> p = criteriaUpdate.from(Product.class);

Path<Number> price = p.get(Product_.price);

criteriaUpdate.set(price, criteriaBuilder.prod(price, 1.03));

entityManager.createQuery(criteriaUpdate).executeUpdate();

StoredProcedureQuery query

= entityManager.createStoredProcedureQuery("findMissingProducts");

Java Persistence in Action30

Page 31: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – What's coming?• ConstructorResult für native Queries

Query query = entityManager.createNativeQuery(

"select name, price from product", "NameAndPriceResult");

List<NameAndPrice> result = query.getResultList();

@Entity

@SqlResultSetMapping(name = "NameAndPriceResult",

classes = { @ConstructorResult(

targetClass = NameAndPrice.class,

columns = { @ColumnResult(name = "name"),

@ColumnResult(name = "price")

})

})

public abstract class Product {

public class NameAndPrice {

public NameAndPrice(String name, double price)

Java Persistence in Action31

Page 32: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – What's coming?• Konverter

@Converter

public class YesNoConverter implements AttributeConverter<Boolean, String> {

public String convertToDatabaseColumn(Boolean fieldValue) {

if (fieldValue == null) return null;

return fieldValue ? "Y" : "N";

}

public Boolean convertToEntityAttribute(String columnValue) {

if (columnValue == null) return null;

return columnValue.equals("Y");

@Entity

public abstract class Product

{

@Convert(converter = YesNoConverter.class)

private boolean active;

Java Persistence in Action32

Page 33: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – What's coming?• CDI Injection in Entity Listener

public class CountryListener {

@Inject

private AuditService auditService;

@PreUpdate

public void preUpdate(Object entity) {

this.auditService.logUpdate(entity);

}

@Entity

@EntityListeners(CountryListener.class)

public class Country {

Java Persistence in Action33

Page 34: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – What's coming?• Unsynchronisierter Persistence Context

– keine automatische TX-Bindung– API zum Binden an TX:EntityManager.joinTransaction()EntityManager.isJoinedWithTransaction()

@PersistenceContext(

name = "default",

synchronization = SynchronizationType.UNSYNCHRONIZED)

private EntityManager entityManager;

Java Persistence in Action34

Page 35: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – What's coming?• Dynamische Erzeugung von Named Queries• DDL Handling

Java Persistence in Action35

Page 36: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – (bisher nur) vorgeschlagen• Fetch groups• Immutable attributes, readonly entities• UUID generator• Multitenancy• Dirty detection• Mapping between JPQL and criteria queries.

Java Persistence in Action36

Page 37: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – Reicht das?• Ja

– für neue Anwendungen– in 90%+ der Fälle

• Aber:– Legacy Databases– Performance

Java Persistence in Action37

Page 38: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – Reicht das?• Legacy Databases

EclipseLink Hibernate OpenJPA

Optimistic Locking ohne Version � �

weitere Generatoren � � �

Inheritance ohne DiskriminatorColumn

� � �

Polymorphe Assoziationen � �

Custom CRUD SQL � �

Java Persistence in Action38

Page 39: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – Reicht das?• Performance

EclipseLink Hibernate OpenJPA

R/O Entities � �

Index � � �

Eager Load Tuning � � �

Batch Fetching � �

Partitioning � �

Cascading Delete in DB � �

Java Persistence in Action39

Page 40: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

[email protected]

JPA 2.1 – Reicht das?• Wunschliste ist nicht leer

– Vieles bereits proprietär vorhanden

• Portabilität ist hohes Gut� Standard weiter entwickeln!

Java Persistence in Action40

Page 41: Java Persistence in Action – Einsatz von JPA 2.x in Java-EE-Anwendungen

Schön, dass Sie da waren!

Di, 20:30: Java EE Day Panel

Mi, 16:30: Gute Zeilen, schlechte ZeilenMi, 19:45: Java on Tracks

[email protected]