Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

27
Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation

Transcript of Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Page 1: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Architecture

Persistente Domänenmodelle mit JPA 2.0 und Bean Validation

Page 2: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

2

Java EE 6 Integration

Page 3: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

3

JSF 2.0 und Bean Validation

<h:inputText id="name" value="#{employeeBean.employee.name}"> <f:validateBean for="name"/></h:inputText>

<h:message for="name" />

Page 4: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

4

JSF und NULL Werte

Leere Input Felder werden von JSF als «» (leerer String) behandelt

Dies ist evtl. ein Problem für die BeanValidation @NotNull Constraint greift nicht

Lösung:<context-param> <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name> <param-value>true</param-value> </context-param>

Achtung vor allfälligen «Nebenwirkungen»!

Page 5: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

5

EJB 3.x Dependency Injection

@PersistenceUnit Liefert eine Referenz zur EntityMangerFactory

@PersistenceContext Liefert eine Referenz zum EntityManger

@PersistenceContextprivate EntityManager em;

@PersistenceUnitprivate EntityManagerFactory emf;

Page 6: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

6

JPA 2.0 und JSR 303

@NotNull statt @Column(nullable=false) @Size.max statt @Column.length @Digits statt @Column.precision/.scale @Min / @Max bei numerischen Columns @Future / @Past bei Datumstypen @Size für Collections und Arrays

Page 7: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

7

Stateless Session Beans

@Statelesspublic class EmployeeService {

@PersistenceContext( type=PersistenceContextType.TRANSACTION) private EntityManager em;

public Employee findById(Integer id) { Employee e = em.find(Employee.class, id);

return e; }}

Page 8: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

8

Stateful Session Beans

@Statefulpublic class EmployeeService {

@PersistenceContext( type=PersistenceContextType.EXTENDED) private EntityManager em;

public Employee findById(Integer id) { Employee e = em.find(Employee.class, id);

return e; }}

Page 9: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

9

Persistence Unit

<persistence> <persistence-unit name="jpa.sbb" transaction-type="JTA">

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

</persistence-unit></persistence>

Page 10: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

10

JPA 2.0 und JSR 303

@NotNull statt @Column(nullable=false) @Size.max statt @Column.length @Digits statt @Column.precision/.scale @Min / @Max bei numerischen Columns @Future / @Past bei Datumstypen @Size für Collections und Arrays

Page 11: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

11

Patterns

Page 12: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Data Access Object (DAO)

ProblemYou want to encapsulate data access and manipulation in a separate layer

SolutionUse a Data Access Object to encapsulate all access to the persistent store. The Data Access Object manages the connection with the data source to obtain and store data

DAOs werden als einfache, zustandslose Klassen realisiert, die den Zugriff auf eine Datenquelle kapseln

Ziele: Trennung von Business Logik und technischer Zugriffslogik Kapselung von Zugriff auf Datenbank oder Fremdsystem

Page 13: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

DAO Klassendiagramm

Client Data Access Object Datenquelle

ResultSetTransfer Object

uses

uses createscreates

accesses

creates /uses

Page 14: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

DAO und JPA

Häufig überflüssig dank EntityManager Wenn schon DAO dann generisch

public interface GenericDAO { <T extends BaseEntity> T create(T t); <T extends BaseEntity> T find(Class<T> type, Serializable id); <T extends BaseEntity> T update(T t); void delete(Object t); List findByNamedQuery(String queryName); List findByNamedQuery(String queryName, Map<String, Object> parameters);}

Page 15: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Transfer Object (TO)

ProblemYou want to transfer multiple data elements over a tier

SolutionUse a Transfer Object to carry multiple data across a tier

Daten werden in Datencontainern zusammengefasst und über Tier-Grenzen transportiert

Das Konzept sollte generell zwischen den Schichten eingesetzt werden

Ziel: Verringerung der übertragenen Datenmenge

Page 16: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

TO und JPA

Mit Constructor Expressions existiert eine einfache Möglichkeit direkt aus den Resultaten Transfer Objects zu erzeugen. public class EmpMenu { public EmpMenu(String employeeName, String deptName){...}}

List result = em.createQuery( "SELECT NEW jpa.util.EmpMenu(e.name, e.department.name) " + "FROM Project p JOIN p.employees e " + "where p.name = "ZLD").getResultList();

for (EmpMenu menu : result) { log.info(menu.employeeName + "," + menu.deptName);}

Page 17: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Schichtung und Verteilung

Applikationsserver DB Server

Datenzugriff

Business

Client oder Webserver

Präsentations-schicht

Datenhaltung

Service Fassade

3rd Party

Applikation XY

TOs und Entities

Ausschliesslich TOs

Page 18: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Client/Server

Ausschliesslich TOs

Entities

Page 19: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Lazy Loading und Verteilung

Lazy Loading deaktivieren Vorteil: einfach, für wenig Daten nutzbar Nachteil: bei vielen Daten aus Performance Gründen nicht nutzbar

Open Session in View Pattern geht davon aus, dass in einer Webappliaktion die Session erst geschlossen wird, wenn der Request beendet ist. Vorteil: Die Daten werden bei Bedarf nachgeladen Nachteil: Funktioniert nur bei einer Webapplikation, Änderungen der Daten

auf dem GUI-Level unter Umgehung der Businesslogik, saubere Trennung der Layer nicht möglich.

Preload Pattern: Der Aufrufer einer DAO-Methode übergibt Informationen, welche Daten vorgeladen werden sollen. Vorteil: Abhängig von der Situation kann Lazy Loading eingesetzt oder

umgangen werden Nachteil: Kann zu einer Schwemme von DAO-Methoden führen um die

möglichen Kombinationen anzubieten.

19Java Persistence API

Page 20: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Open Session in View

20Java Persistence API

HTTP Session

Transaktion 1 Transaktion 2

O1 O1

Lazy

Page 21: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Preload Pattern nach Jürgen Kohl (1)

Jürgen Kohl beschreibt in der Ausgabe 4/2008 des Java Magazins sein Preload Pattern, dass in einigen Praxisprojekten erfolgreich eingesetzt wurde. Hierbei liegt der Fokus darauf die Methodenschwemme zu vermeiden und weiterhin die Nutzung eines GenericDAO zu erlauben.

Seine Anforderungen sind: generischer Mechanismus keine Verkomplizierung der Backend-Methoden bei

steigender Komplexität des Domain Models Anwender der Backend-Methoden können denkbare

Preload-kombinationen selbst definieren.

21Java Persistence API

Page 22: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Preload Pattern nach Jürgen Kohl (2)

22Java Persistence API

public class Preload { private Class modelClass; private String property;

public Preload(Class modelClass, String property) { this.modelClass = modelClass; this.property = property; }}

Page 23: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Preload Pattern nach Jürgen Kohl (3)

23Java Persistence API

public abstract class GenericDAO<T, ID> {

private Class<T> persistentClass;

private String getPropertyGetterName(String property ) { String propertyUpper = property.toUpperCase().substring(0, 1); return "get" + propertyUpper + property.substring(1); }

private Object invokeGetter(Object entity, Preload preload) { String getterName = getPropertyGetterName(preload.getProperty()); try { Method method = preload.getModelClass().getMethod( getterName, (Class[]) null); return method.invoke(entity, (Object[]) null); } catch (Exception ex) { throw new RuntimeException("Can't invoke getter for property: " + preload.getProperty(), ex); } }

Page 24: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Preload Pattern nach Jürgen Kohl (4)

24Java Persistence API

// Fortsetzung GenericDAO

protected void preload(Object entity, Preload[] preloads) { if (entity instanceof Collection) { for (Object resultEntity : (Collection) entity) { preload(resultEntity, preloads); } } else { for (Preload preload : preloads) { if (preload.getModelClass().isInstance(entity)) { Object getterResult = invokeGetter(entity, preload); preload( getterResult, preloads); } }}

Page 25: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Preload Pattern nach Adam Bien

Idee: Verwendung JXPath für die Initiatlisierung von Lazy Loading Beziehungen

Beispielklasse mit Lazy OneToOne Beziehung:

Aufruf der Getter-Methode mit JXPath:

25Java Persistence API

@Entitypublic class Master { ... @OneToOne(fetch=FetchType.LAZY) private Detail detail; ...}

JXPathContext.newContext(master).getValue("/detail");

Page 26: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Batch

Problematik Sequenzielle Verarbeitung von grossen

Datenmengen Verwendung von Cursors mit JPA nicht möglich

Lösung Pagination

Vorsicht Persistence Context kann gross werden und

sollte regelmässig aufgeräumt werden (EntitManager.clear())

Page 27: Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.

Clustering

Zur Erhöhung der Verfügbarkeit und der Verbesserung der Performance werden Application Server häufig geclustert

Problem Persistence Context auf mehreren Knoten

vorhanden Synchronität mit Datenbank nicht gegeben

Lösung Synchronisation (Providerabhängig) Referesh der Entitäten bei Bedarf