Persistente Domänenmodelle mit JPA 2.0 und Bean Validation

Slides:



Advertisements
Ähnliche Präsentationen
Object Relational Mapping
Advertisements

Object Relational Mapping
Objektrelationales Mapping mit JPA
Persistente Domänenmodelle mit JPA 2.0 und Bean Validation
Persistente Domänenmodelle mit JPA 2.0 und Bean Validation
Objektrelationales Mapping mit JPA Advanced Topics Jonas Bandi Simon Martinelli.
Objektorientierte Programmierung
ER-Datenmodell und Abfragen in SQL
Kapitel 3: Logische Datenmodelle
JPQL Java Persistence Query Language
Systemüberblick Beispiele: Microsoft Access Oracle Ingres Informix
Objektrelationales Mapping mit JPA Working with Persistent Objects Jonas Bandi Simon Martinelli.
Objektrelationales Mapping mit JPA
Objektrelationales Mapping mit JPA Getting Started Jonas Bandi Simon Martinelli.
Java: Dynamische Datentypen
Indirekte Adressierung
Java: Referenzen und Zeichenketten
Java: Grundlagen der Objektorientierung
XINDICE The Apache XML Project Name: Jacqueline Langhorst
SQL als Abfragesprache
SQL als Abfragesprache
IS: Datenbanken, © Till Hänisch 2000 CREATE TABLE Syntax: CREATE TABLE name ( coldef [, coldef] [, tableconstraints] ) coldef := name type [länge], [[NOT]NULL],
Oracle PL/SQL Server Pages (PSP). © Prof. T. Kudraß, HTWK Leipzig Grundidee: PSP – Internet-Seiten mit dynamischer Präsentation von Inhalten durch Einsatz.
Open Database Connectivity (ODBC). © Prof. T. Kudraß, HTWK Leipzig Open Database Connectivity (ODBC) Idee: – API für eine DBMS, das ein Call-Level-Interface.
Übung Datenbanksysteme SQL-Anfragen (2)
PRJ 2007/1 Stefan Dissmann Motivation Problem: gleiche Datenstrukturen werden für verschiedene Objekte gebraucht: z.B. Listen von Studierenden, Kunden,
JDBC -Java Database Connectivity-. 15./22. April 2004JDBC2 JDBC.... verbindet Java-Programme mit SQL-basierten Datenbanken.. liefert eine generische SQL-API.
DVG Klassen und Objekte
JDBC EDV JDBC.
Abfragen – Tipps und Tricks Buch S102ff (Informatik I, Oldenbourg-Verlag) Nach einer Vorlage von Dieter Bergmann.
Kollektionstypen (1) Es sind polymorphe Typkonstruktoren, jeweils als Sorten- und als Klassenkonstruktor (t,v beliebige Typen): –set, Set :Ungeordnete.
SQL in Visual FoxPro. © 1999 TMN-Systemberatung GmbH SQL Historie n SQL - Structured Query Language n In den 70er Jahren von IBM entwickelt n 1986 zum.
Arbeiten mit SQL in Visual FoxPro 9.0 deutschsprachige FoxPro User Group Rainer Becker Microsoft Visual FoxPro 9.0 Roadshow SQL.
JDBC: JAVA Database Connectivity
Hauptseminar Datenbanksysteme - Datenbanken und XML - Thema: Type-Checking OQL Queries In The ODMG Type Systems.
Was umfaßt die CORBA Core Spezifikation? Welche zusätzlichen Komponenten muß ein ORB Produkt beinhalten? Core: CORBA Objekt Modell CORBA Architektur OMG.
SQL PHP und MySQL Referat von Katharina Stracke und Carina Berning
Betrieb von Datenbanken Marco Skulschus & Marcus Wiederstein
Working With Persistent Objects
Wir bauen uns eine Webapplikation!
Objektrelationales Mapping mit JPA 2.0
PHP und MYSQL am Organisatorisches Der komplette Kurs im Schnelldurchgang Bewertung von wichtig und unwichtig Historisch Kulturwissenschaftliche.
Betrieb von Datenbanken Marco Skulschus & Marcus Wiederstein Datenmanipulation Lehrbuch, Kapitel 4.
Architecture Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.
Entity Mapping Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.
Advanced Mapping Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.
Persistente Domänenmodelle mit JPA 2.0 und Bean Validation
Objektrelationales Mapping mit JPA 2.0
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
OOP-Begriffe Abstraktion Modellieren Klasse Objekt Attribute Methoden
Getting Started Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.
SS 2004 Datenbanken 4W Mi 13:30 – 15:00 G 2.30 Vorlesung #7 SQL (Teil 2)
Datenbanksysteme für hörer anderer Fachrichtungen
Einführung in Datenbankmodellierung und SQL
Aggregatsfunktion SQL = Structured Query Language.
Von Isabelle Spörl und Simon Schausberger
Einfache OQL-Ausdrücke (1) Literale und Objekte können direkt konstruiert werden; gültige Ausdrücke und ihre Typen sind z.B.: "Quader77": string struct(x:1.0,
Hibernate (OR-Mapping)
Datenbankanbindung mit
Verdichten von Daten mit Gruppenfunktionen
Structured Query Language
OQL-Anbindung an Java (1) Java als Beispiel für die Einbettung von OQL in eine Programmiersprache Die OQL-Einbettung in Java ist teilweise mit dynamischem.
WS 2014/15 Datenbanksysteme D0 15:15 – 16:45 R Vorlesung #6 SQL (Teil 3)
11 Zugriffskontrolle (Access Control) Ziele Privilegien Rollen GRANT und REVOKE Befehl Privilegien Rollen GRANT und REVOKE Befehl.
Enterprise-IT-Praktikum Hibernate-Einführung Institut für Telematik Universität zu Lübeck Wintersmester 2012/13 Dennis Boldt David Gregorczyk.
Datenbanken abfragen mit SQL
XML-Erweiterungen in ORDBMS Seminar: DBMS für spezielle Anwendungen Florian Brieler.
Vorlesung #5 SQL (Teil 2).
Nutzung und Modellierung von Datenbanken
(Structured Query Language)
 Präsentation transkript:

Persistente Domänenmodelle mit JPA 2.0 und Bean Validation Querying Persistente Domänenmodelle mit JPA 2.0 und Bean Validation

Entities laden In JPA gibt es verschiedene Optionen Entitäten zu laden: Eine einzelne Instanz über die ID laden Navigation auf dem Objektgraphen Queries in der Java Persistence Query Language (JPQL) Queries in SQL In JPA2 kommt neu die Criteria API hinzu

Entity über die ID laden Der EntityManager stellt zwei Möglichkeiten zur Verfügung: find() und getReference() EntityManager em = … Integer id = 1234; Employee john = em.find(Employee.class, id); Falls die Entität bereits im Persistence Context geladen ist, so wird kein DB-Query ausgeführt. find(): Wenn sich die Entity noch nicht im Persistence Context befindet, so wird sie von der DB geladen. Resultat is null, falls die Entity nicht existiert getReference(): Wenn sich die Entität noch nicht im Persistence Context befindet, so wird ein Proxy zurückgegeben. Es wird vorerst kein DB-Query ausgeführt. Dieses erfolgt erst wenn auf die Entität zugegriffen wird. EntityNotFoundException erst beim Zugriff, falls die Entity nicht existiert.

Navigation des Objektgraphen Ausgehend von einer Entity kann ein Objektgraph traversiert werden. Dabei lätdt JPA transparent alle notwendigen Daten von der DB. Dieses Feature wird “Lazy Loading” genannt Die Entities müssen persistent und der EntityManager muss offen sein Dies ist ein mächtiges Feature, birgt aber auch Gefahren

Queries mit JPQL JPQL ist eine mächtige Abfragesprache basierend auf dem Entitätenmodell: Stark an SQL angelehnt Unabhängig von der darunterliegenden Datenbank Abfragen basieren auf dem Klassenmodell (Entitäten), nicht auf dem Datenmodell (Tabellen) Unterstützt OO-Konstrukte wie Vererbung, Polymorphismus und Pfadausdrücke String queryString = “select e.address from Employee e where e.mainProject.name = ‘JPA Kurs‘“; Query query = em.createQuery(queryString); List<Address> users = query.getResultList();

Verwendung von JPQL Typischerweise wird JPQL verwendet um Entities zu laden. JPQL unterstützt aber auch andere Szenarien: Abfrage von skalaren Werten (Projektionen oder Aggregationen) Bulk Updates und Deletes Reporting Queries: Rückgabe von Daten-Tupels, nutzung von Gruppierungs- und Aggregationsfunktionen der DB Constructor Expressions: Abfüllen von beliebigen Objekten (nicht notwendigerweise Entities) JPQL kann entweder in Dynamischen Queries oder in Named Queries verwendet werden.

Dynamische Queries Bei Dynamischen Queries wird der JPQL String zur Laufzeit erstellt. Kontextabhängige Queries String Concatenation EntityManager em = ... String queryString = “select e from Employee e where e.address.city = ‘Bern‘“; Query query = em.createQuery(queryString); List<Employee> employees = query.getResultList();

Named Queries Named Queries werden statisch definiert und können überall in der Applikation verwendet werden. Die JPA Infrastruktur kann Named Queries vor der eigentlichen Ausführung parsen und kompilieren (Prepared Statements) Parsen/Kompilierung muss nur einmal durchgeführt werden Kann beim Deployen/Startup erfolgen und überprüft werden (Fail Fast) @NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e") public class Employee { ... } Named Query kann bei allen annotierten Klassen angefügt werden Name muss unique sein innerhalb der Persistence Unit Tip: Anstatt Strings Konstanten verwneden EntityManager em = ... Query q = em.createNamedQuery("Employee.findAll"); List<Employee> employees = query.getResultList();

Parameter Binding Queries sollten parametrisert werden. Es gibt zwei Arten der Parametrisierung: Named Parameters Positional Parameters SELECT e FROM Employee e WHERE e.department = :dept AND e.salary > :base Query q = ... q.setParameter("dept", "Taxes"); q.setParameter("base", "3500"); SELECT e FROM Employee e WHERE e.department = ?1 AND e.salary > ?2 Query q = ... q.setParameter(1, "Taxes"); q.setParameter(2, "3500");

Queries ausführen Abholen des Resultates mit Methoden von Query List getResultList() Object getSingleResult() int executeUpdate() Beispiel Query q = em.createQuery("SELECT e FROM Employee e"); List<Employee> emps = q.getResultList(); for(Employee e : emps) { System.out.println(e); } NonUniqueResultException wenn mehrere Resultate bei getSingleResult()

JPQL Sprach-Features JPQL ist eine sehr mächtige und flexible Abfragesprache. Hier nur einige Features: JOINS und Subqueries (IN, EXISTS) Aggregatsfunktionen (AVG, COUNT, MIN, MAX, SUM) GROUP BY und HAVING Funktionen (LOWER, ABS, TRIM ...) LIKE Collection-Abfragen: IS EMPTY, MEMBER ANY, ALL, SOME,

Pfad-Ausdrücke Ein Pfadausdruck ermöglicht die direkte Navigation von einem äusseren zu inneren, referenzierten Objekten: SELECT e.address FROM Employee e SELECT e.address.name FROM Employee e Ein Pfadausdruck kann in einer Collection enden: SELECT e.projects FROM Employee e Ein Pfadausdruck kann nicht über eine Collection hinweg navigieren: SELECT e.projects.name FROM Employee e

Pagination Mit JPA ist Pagination sehr einfach: String queryString = “select e from Employee“; Query query = em.createQuery(queryString); query.setFirstResult(110); query.setMaxResults(10); List<Order> orders = query.getResultList(); JPA schreibt nicht vor, wie Pagination umgesetzt wird! Dies kann von JPA-Implementation und DB-Dialekt abhängen. In der Regel wird das resultierende SQL-Query ist für den entsprechenden SQL-Dialekt optimiert. Achtung: Meist wird das SQL-Rowset limitiert, und nicht die resultierenden Entities!

Fetching & Lazy Loading Die Idee von Lazy Loading ist es, die Daten erst dann von der DB zu laden, wenn sie auch wirklich in der Applikation benötigt werden. Das Laden sollte für den Client transparent sein Dem Programmierer wird viel Arbeit erspart Nachteile: Traversieren eines Objekt-Graphen kann in vielen einzelnen DB-Queries resultieren “N+1 select problem”: Für eine Parent-Child Beziehung wird für jedes Kind ein eigenes DB-Query abgesetzt Das Gegenteil von Lazy Loading ist Eager Loading

Fetching & Lazy Loading In JPA kann das Lade-Verhalten auf zwei Weisen beeinflusst werden: Global Fetch Plan: Konfiguriert in den Entity- Metadaten (Annotationen/XML) Programmatisch beim Erstellen eines Queries mittels Join Fetch @OneToMany(mappedBy = "employee", fetch = FetchType.EAGER) private Set<Phone> phones = new HashSet<Phone>(); SELECT d FROM Department d LEFT JOIN FETCH d.employees

Joins & Fetching Es gibt unterschiedliche Joins in JPQL: Fetch Joins für Eager Loading SELECT d FROM Department d LEFT JOIN FETCH d.employees Explizite Joins für Selektion und Projektion SELECT employee FROM Employee employee JOIN employee.projects project WHERE project.name = 'Arcos' SELECT project FROM Employee employee JOIN employee.projects project WHERE employee.name = 'John' Implizite Joins aus Pfadausdrücken SELECT e FROM Employee e where e.address.city = 'Bern' SELECT e.address FROM Employee e where e.name = 'John'

Polymorphe Queries JPQL unterstützt Polymorphie: Query q = em.createQuery("select p FROM Project p"); List<Project> projects = q.getResultList(); Selektion aufgrund einer Subklasse: SELECT employee FROM Employee employee JOIN employee.projects project, DesignProject dproject WHERE project = dproject AND dproject.innovationLevel > 2 JPA 1: Queries sind immer polymorph! JPA 2: Einschränkungen des Typs mittels Type-Expression möglich SELECT p FROM Project p WHERE TYPE(p) IN (DesignProject)

Reporting Queries Wird mehr als eine Expression in der SELECT Klausel verwendet, wird ein Object[]-Array zurückgegeben: List result = em.createQuery( "SELECT e.name, e.department.name " + "FROM Project p JOIN p.employees e " + "where p.name = "ZLD").getResultList(); for (Iterator i = result.iterator(); i.hasNext()) { Object[] values = (Object[])i.next(); System.out.println(values[0] + "," + values[1]); } Solche Queries werden typischerweise für Reporting verwendet Das Resultat sind keine Entities und wird nicht vom Persistence Context gemanagt!

Constructor Expressions Mit Constructor Expressions existiert eine einfache Möglichkeit um Resultate auf Klassen zu mappen: public class EmployeeDTO { public String employeeName; public String deptName; public EmployeeTO(String employeeName, String deptName) {...} } List result = em.createQuery( "SELECT NEW jpa.util.EmployeeDTO(e.name, e.department.name) " + "FROM Project p JOIN p.employees e " + "where p.name = "ZLD").getResultList(); for (EmployeeTO emp : result) { System.out.println(emp.employeeName + "," + emp.deptName); } Achtung: Klasse muss vollqualifiziert angegeben werden! Kann auch mit Entities verwendet werden. Das Resultat wird nicht vom Persistence Kontext gemanagt.

Bulk Statements In JPQL können UPDATE und DELETE-Statements formuliert werden, welche auf eine Menge von Entities angewendet werden. Query q = em.createQuery("DELETE from Employee e"); int count = q.executeUpdate(); Query q = em.createQuery("UPDATE Employee e " + "SET e.name = 'Simon' " + "WHERE e.name = 'Peter'); int count = q.executeUpdate(); Achtung: Bulk Statements umgehen den Entity Manager! Damit geladene Entities die Veränderungen mitbekommen, müssen sie mit der Datenbank synchronisiert werden.

Vorteile und Nachteile von JPQL Sehr mächtig und flexibel Stark an SQL angelehnt Nachteile JPQL ist eine embedded Language die in Java mittels Stings verwendet wird. Keine Überprüfung beim Kompilieren, keine Typ-Sicherheit Flexible Komposition eines Queries ist nicht elegant möglich (String-Manipulation) Für nicht-triviale Anwendungen ist SQL Knowhow und Verständnis des Datenmodels ist notwendig

SQL Queries JPA ermöglicht die Formulierung von SQL-Queries: Query q = em.createNativeQuery("SELECT * FROM emp WHERE id = ?", Employee.class); q.setParameter(1, employeeId); List<Employee> employees = q.getResultList(); SQL-Queries könne auch als NamedQuery definiert werden: @NamedNativeQuery( name = "employeeReporting", query = "SELECT * FROM emp WHERE id = ?", resultClass = Employee.class) Ausführung analog Named Queries in JPQL Stored Procedures werden in JPA nicht unterstützt. Die meisten JPA- Implementationen bieten jedoch proprietäre Mechanismen zum Einbinden von Stored Procedures.

SQL Queries Update und Delete Statements: Query q = em.createNativeQuery("UPDATE emp SET salary = salary + 1"); int updated = q.executeUpdate(); Flexibles Mapping des Result-Sets @SqlResultSetMapping( name = "EmployeeWithAddress", entities = {@EntityResult(entityClass = Employee.class), @EntityResult(entityClass = Address.class)} String s = "SELECT e.*, a.* FROM emp e, address a" + "WHERE e.adress_id = a.id"; Query q = em.createNativeQuery(s, "EmployeeWithAddress"); List<Employee> employees = q.getResultList();

Criteria API in JPA 2 Mit der Criteria API wird in JPA 2 eine Objekt- Orientierte Schnittstelle zum programmatischen Erstellen von Queries standardisiert. Vorteile: Dynamisches Erstellen von Queries (Komposition) Keine String-Manipulation notwendig OO-Konstrukte zum Erstellen komplexer Queries Gewisse Typsicherheit

Criteria API in JPA 2 Beispiel mit Strings für Referenzen: QueryBuilder qb = ... CriteriaQuery q = qb.create(); Root<Customer> cust = q.from(Customer.class); Join<Order, Item> item = cust.join("orders").join("lineitems"); q.select(cust.get("name")).where( qb.equal(item.get("product").get("productType"), "printer")); Beispiel mit typsicheren, statischem Metamodel: QueryBuilder qb = ... CriteriaQuery q = qb.create(); Root<Customer> cust = q.from(Customer.class); Join<Customer, Order> order = cust.join(Customer_.orders); Join<Order, Item> item = order.join(Order_.lineitems); q.select(cust.get(Customer_.name)) .where(qb.equal(item.get(Item_.product).get(Product_.productType), "printer"));