2.07k likes | 2.23k Views
Objektrelationales Mapping mit JPA 2.0. Jonas Bandi Simon Martinelli. Simon Martinelli. email: sm@simas.ch blog : http://simonmartinelli.blogspot.com/ Geschäftsführer der simas GmbH Nebenamtdozent an der Berner Fachhochschule (SWS und Medical Technology Center)
E N D
Objektrelationales Mapping mit JPA 2.0 Jonas Bandi Simon Martinelli
Simon Martinelli • email: sm@simas.ch • blog: http://simonmartinelli.blogspot.com/ • Geschäftsführer der simas GmbH • Nebenamtdozent an der Berner Fachhochschule (SWS und Medical Technology Center) • Software Architekt, Entwickler, Berater und Trainer im Java EE Umfeld mit mehr als 15 Jahren Erfahrung in der Software Entwicklung
Jonas Bandi • email: jonas.bandi@gmail.com • blog: http://blog.jonasbandi.net • Studium der Elektrotechnik und Informationstechnologie an der ETH Zürich • Angestellt bei TechTalk Software AG in Zürich • Seit 10 Jahren in verschiedenen Bereichen der Softwareentwicklung tätig • Mein besonderes Interesse gilt dem Einsatz von modernen Technologien und Methodiken in der Entwicklung von Enterprise Applikationen.
Kursziele • Einführung in Objekt-Relationales Mapping • Einführung in JPA • Fortgeschrittene Themen beim Einsatz von JPA • Unterschiede JPA / JPA2 • Wir versuchen möglichst neutral bezüglich des verwendeten JPA Providers zu sein • Übungen: EclipseLink, Maven • Kursunterlagen: http://code.google.com/p/jpaworkshop/
Über euch • Wer setzt Objekt-Relationales Mapping ein? • Wer arbeitet mit JPA? • Wer setzt Hibernate ein? • Was setzten die andern ein? • Ist JPA 2 ein Thema? • Erwartungen an diesen Workshop? • Wer hat die Übungen angeschaut?
Einführung ORM & JPA Objektrelationales Mapping mit JPA 2.0
Silver Bullet oder unnötiger Overhead? • Objektrelationales Mapping ist ein umstrittenes Thema, das immer wieder Anlass für hitzige Diskussionen bietet. • Hier zwei Beispiele...
Flame Wars • “The Best ORM is No ORM” • “The database is an object.” • “ORM is, for the most part, solving the wrong problem. In fact the problem does not really exist.” • Hibernate should be to programmers what cake mixes are to bakers: beneath their dignity. [...] As professional programmers, we should be more sceptical of generic frameworks like hibernate.
The Vietnam of Computer Science • Ted Neward: “Object/Relational Mapping is the Vietnam of Computer Science” (Juni 2006).Original Blog Post: http://tinyurl.com/heapfPDF: http://www.odbms.org/about_news_20070212.html • “Law of Diminishing Returns” • Schnelle anfängliche Erfolge führen zu grossen Erwartungen • Mit dem Fortschreiten des Unterfangens werden die Erfolge aber immer spärlicher und die dafür notwendigen Investitionen immer grösser • Schlussendlich werden die Investitionen nicht mehr durch den Gewinn gerechtfertigt. Aber es gibt keinen Weg zurück...
Ausgangslage Domain Model • OO verspricht: • bessere Skalierung bei zunehmender Komplexität • bessere Erweiterbarkeit • bessere Wartbarkeit • weniger Redundanz Anwendung von bewährten OO-Techniken für die Implementation der Geschäftslogik: Kapselung, Vererbung, Polymorphie, Design Patterns ...
Ausgangslage: Relationale Datenbanken • Vorherrschende Technologie zum Speichern von Daten im Enterprise-Umfeld. • Gründe: • Grosse Investitionen • Bewährte, ausgereifte Technologie • Flexibilität, Applikationsunabhängigkeit • Daten leben länger als Applikationen • Optimierte Konzepte zum Speichern von Daten
Ausgangslage: Der Konflikt • De facto Standard-Konstellation für Enterprise-Applikationen: • OO-Technologie für die Applikations-entwicklung • Relationale Datenbanken für die Persistenz der Daten • An dieser Ausgangslage wird sich mittelfristig kaum etwas ändern. • Der OO-Ansatz und der relationale Ansatz weisen grundsätzliche Unterschiede auf • Aus diesen Unterschieden resultiert der sog. Object-Relational-Mismatch
Der O/R-Mismatch • Technische Ausprägungen des O/R-Mismatch: • Typen-Systeme • Null • Datum/Zeit • Abbildung von Beziehungen • Richtung • Mehrfachbeziehungen • Vererbung • Identität • Objekte haben eine implizite Identität • Relationen haben eine explizite Identität (Primary Key) • Transaktionen
Der O/R-Mismatch • In heutigen Enterprise Umfeldern ist der O/R-Mismatch ein Fakt. • Der O/R-Mismatch folgt aus konzeptionellen Unterschieden der zugrundeliegenden Technologien. • Es gibt viele verschiedene Möglichkeiten den O/R-Mismatch zu überwinden. • O/R-Mapping resp. O/R-Mapping Frameworks sind ein möglicher Lösungsansatz.
History • Konzepte zum Überbrücken des O/R-Mismatch existieren seit es OO gibt. • Unterschiedliche Ansätze wie der O/R-Mismatch überwunden werden soll • Bekannteste Java Frameworks • Hibernate • TopLink, TopLink Essentials, EclipseLink • KODO, OpenJPA • JPOX , DataNucleus • Java Standardisierung: EJB2, JDO, JPA
Versprechen von O/R-Mapping • Die Applikation wird von der DB entkoppelt • Applikationsentwickler muss kein SQL beherrschen • Das relationale Modell der Datenbank hat keinen Einfluss auf das OO-Design • Automatische Persistenz • Automatisierte Abbildung der Objekte in die relationalen Strukturen • Der Applikationsentwickler muss sich nicht um die “low-level”-Details des CLI (z.B. connections) kümmern. • Transparente Persistenz / Persistence Ignorance • Die Klassen des Domain-Models wissen nicht dass sie persistiert und geladen werden können und haben keine Abhängigkeit zur Persistenz-Infrastruktur.
Versprechen von O/R-Mapping • Abstraktion • Abstraktion ist eines der wichtigsten Werkzeuge um Komplexität zu bewältigen • Separation of Concerns • Bei der Applikationsentwicklung kann man sich ausschliesslich auf die Geschäftsprobleme konzentrieren • Infrastruktur-Probleme können separat gelöst werden und beeinflussen das Design und die Implementation der Geschäftslogik nicht.
Versprechen von O/R-Mapping Frameworks • Umsetzung der Versprechen von O/R-Mapping • Einsatz von bewährten Patterns und Konzepten • Einsparungen von viel Code • Manuell codierter DataAccess-Layer kann einen grossen Code-Anteil ausmachen • Referenzbeispiele zeigen Einsparungen um Faktor 7 • Strukturierung / Layerung des Codes vorgegeben
Pitfalls von O/R-Mapping Frameworks • O/R-Mapping-Frameworks sind komplex und bieten viel Funktionalität. • Hibernate Core: 765k LOC, 206 Personen-Jahre, $11 Mio (Source: Ohloh.net) • O/R-Mapping-Frameworks sind keine Rapid-Application-Development-Tools • Der Einsatz eines O/R-Mapping-Frameworks hat Einfluss auf die Architektur und den Design der gesamten Applikation • Die zugrundeliegenden Konzepte sollten verstanden sein. • Gründliche Auseinandersetzung ist Voraussetzung für den erfolgreichen Einsatz eines O/R-Mapping-Frameworks
Konzeptionelle Probleme beim O/R-Mapping • Folgende konzeptionelle Probleme sollten beim O/R-Mapping beachtet werden: • Location Transparency • Optimiertes SQL • Mengen-Manipulationen • Relationale Suche / Reports / OLAP
Location Transparencey • Alle Daten immer verfügbar • Für die Applikation sollte es keinen Unterschied machen, ob die sich Daten im lokalen Speicher oder auf der entfernten Datenbank befinden. • Wieviele Daten werden geladen? • Zuviele: Speicher, Bandbreite -> Ladezeit! • Zuwenige: Konstantes Nachladen -> Ladezeit! • Stichworte: Lazy-Loading / Eager-Loading
Dynamisch Generiertes SQL • SQL ist nicht so performant wie handgeschriebens, getuntes SQL • Assembler anybody? • Dynamisch generiertes SQL muss auch nicht gewartet werden! • Ausgereifte Frameworks generieren gut optimiertes SQL (torpedo-group.org) • Performance • Stored Procedures sind nicht performanter als dynamisches SQL!
Relationale Suche / Reports • Nutzung von relationalen Konzepten, die keine Entsprechung in der OO-Welt haben • Unproblematische Abfragen: • Alle Personen, welche einen schwarzen Mantel bestellen. • Alle Personen, welche einen schwarzen Mantel bestellen mit all ihren Bestellungen und allen Bestell-Posten
Relationale Suche / Reports • Problematische Abfrage: • Alle Tupel bestehend aus Vorname, Nachname und Produktname
Relationale Suche / Reports Probleme: • KarthesischesProdukt • In der DB sehreffizientumgesetzt • In der OO-Welt keineEntsprechung • Die Struktur des Resultats der Anfrageexistiertnicht in der OO-Welt • EsgibtkeinenTypmit den Attributen (Vorname, Nachname, Produktname) • Die relationale Welt erlaubt flexible (untypisierte) Sichten auf die Daten (Deklarative ad-hoc formulierteAnfragen) • ResultateinerAnfragekannvölligentkoppeltsein von der Strukturwie die Datengespeichertwerden. • Die OO-Welt verlangtdefinierte, stark typisierteStrukturen • Das ‚Flachdrücken‘ / ‚Denormalisieren‘ muss in der OO-Welt manuellausgeführtwerden • AllebeteiligtenObjektemüssengeladenwerden (Performance!)
JPA – Java Persistence API • JPA ist eine Bestrebung OR-Mapping mit Java zu standardisieren • JPA ist ein Teil der EJB 3 Spezifikation welche vom JCP erarbeitet wurde • JSR 220, final release: 2.5.2006 • TopLink Essentials ist die Referenzimplementation • Es gibt verschiedene JPA Implementationen, diese werden auch JPA Providers genannt • JPA 2 ist eine eigenständge Spezifikation, welche auf JPA aufbaut und etliche zusätzliche Features bietet • JSR 317, final release: 10.12.2009 • EclipseLink ist die Referenzimplementation • Die bekannten JPA Providers unterstützen alle JPA2
Technologiestack Session Beans / Java Applikation Java 5+ Java Persistence API JPA Spezifikation Java Persistence API Implementation EclipseLink (TopLink), Hibernate, OpenJPA etc. JDBC API JDBC 4.0 JDBC - Driver Herstellerspezifisch SQL SQL 2003 oder Dialekte RDB
Java API Runtime Exceptions ( ~8 )RollbackException Annotations ( ~64 )EntityIdOneToOneOneToMany Enumerations ( ~10 )InheritanceTypeCascadeTypeFetchType Packagesjavax.persistencejavax.persistence.spi ClassesPersistence InterfacesEntityManagerFactoryEntityManagerEntityTransactionQuery
JPA Providers • Die bekanntesten JPA Providers sind: • Hibernate • Toplink / TopLink Essentials / EclipseLink • KODO / OpenJPA • JPOX / DataNucleus • Weniger bekannt sind: • Apache Cayenne • Resin Amber • CocoBase
Getting Started Objektrelationales Mapping mit JPA 2.0
Entity Überblick • Eine Entity ist persistierbar. Der Zustand kann in einer Datenbank abgespeichert und später wieder darauf zugegriffen werden • Wie jedes andere Java Objekt hat eine Entity eine Objektidentität. Zusätzlich besitzt sie eine Datenbankidentität (Primary Key) • In Zusammenhang mit der Datenbank werden die Entities transaktional verwendet. Die Erstellung, Änderung und das Löschen wird in einer Transaktion durchgeführt
Entity Metadata • Kennzeichnung mit Annotation @Entity oder Mapping mit XML • Klasse kann Basisklasse oder abgeleitet sein • Klasse kann abstrakt oder konkret sein • Serialisierbarkeit ist bezüglich Persistenz nicht erforderlich • Anforderungen: • Standardkonstrukutor muss vorhanden sein. • Klasse darf nicht final, kein Interface und keine Enumeration sein und keine final-Methoden enthalten • Felder müssen private oder protected sein. • Zugriff von Clients auf Felder nur über get/set- oder Business-Methoden erlaubt. • Jede Entity muss einen Primärschlüssel (@Id) haben • ConfigurationbyException / ConventionsoverConfiguration
Entity, Beispiel @Entity public class Employee { @Id protected int id; protected String name; protected long salary; public Employee(int id) { } ... }
Entity Manager, Beispiel • Entity Manager erstellen • Entity persistieren • Entitiy suchen EntityManagerFactoryemf = Persistence.createEntityManagerFactory("jpa.emp.2008");EntityManagerem = emf.createEntityManager(); Employeeemp = newEmployee(158);em.persist(emp); Employeeemp = em.find(Employee.class, 158);
Entity Manager, Beispiel • Entity verändern • Entity löschen • Queries em.getTransaction().begin();emp.setSalary(emp.getSalary() + 1000);em.getTransaction().commit(); em.getTransaction().begin();em.remove(emp); em.getTransaction().commit(); Query q = em.createQuery("SELECT e FROM Employee e");Collectionemps = q.getResultList();
Persitence Unit • Eine Persistence Unit ist eine logische Einheit von Entities. Sie wird beschrieben durch: • Einen Namen • Die zu dieser Unit gehörenden Entity-Klassen • Angaben zum Persistence Provider • Angabe zum Transaktionstyp • Angaben zur Datenquelle • Weitere Properties • Namen von XML O/R-Mapping Files • Technisch wird die Beschreibung einer Persistence Unit in der Datei META-INF/persistence.xml abgelegt. • Persitence Archive = JAR
Persistence Unit, Beispiel • META-INF/persistence.xml <persistence> <persistence-unit name="emp" transaction-type="RESOURCE_LOCAL"> <provider>oracle.toplink.essentials.PersistenceProvider</provider> <class>examples.model.Employee</class> <properties> <propertyname="toplink.jdbc.driver" value="oracle.jdbc.driver.OracleDriver" /> <propertyname="toplink.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:xe" /> <propertyname="toplink.jdbc.user" value="emp3" /> <propertyname="toplink.jdbc.password" value="emp3" /> </properties> </persistence-unit> </persistence>
Entity Mapping Objektrelationales Mapping mit JPA 2.0
Access Typ • Für das Persistenz-Framework existieren zwei Zugriffspunkte auf die Daten einer Klasse // Field Access@Entity public class Employee { @Id private int id;} //Property Access@Entity public class Employee { protected int id; @Id public intgetId() { return id; }}
Access Typ Options (JPA 2.0) • Verschiedene Access Types pro Klasse möglich • Mischen von Acces Types in einer Vererbungshierarchie @Entity @Access(FIELD) public class Vehicle { ... @Transient double fuelEfficiency; @Access(PROPERTY) protected double getDbFuelEfficiency() { return convertToImperial(fuelEfficiency); } ... }
Mapping • Es wird immer vom Defaultverhalten ausgegangen • Das Defaultverhalten kann übersteuert werden @Entity@Table(name = "EMP")public class Employee { @Id @Column(name = "EMP_ID") ...}
Persistente Datentypen • Erlaubt: • Alle primitiven Typen, String • Alle Wrapperklassen und serialisierbaren Typen (z.B. Integer, BigDecimal, Date, Calendar) • byte[], Byte[], char[], Character[] • Enumerations • Beliebige weitere Entity-Klassen • Collections von Entities, welche als Collection<>, List<>, Set<> oder Map<> deklariert sind. • Nicht erlaubt: • Alle Arten von Arrays ausser die obgenannten • Collections von etwas anderem als Entities, also z.B. Wrapperklassen und andere serialiserbare Typen.
Java / SQL Type Mapping • Implizit durch JDBC “Data Type Conversion Table“ definiert • Explizit durch die @Column Annotation, z.B. • Produktspezifisch durch JPA-Implementation oder im JDBC-Driver für die jeweilige Datenbank @Column(name = "sender")protected String sender;
Lazy Fetching und Large Objects • Lazy Field Loading • Large Objects @Basic(fetch = FetchType.LAZY)private String comments; @Basic(fetch = FetchType.LAZY)@Lobprivate byte[] picture;
Enumerations • Enumerations können persistent sein. In der Datenbank wird entweder der Ordinalwert (Position) oder der Stringwert (Name der Konstante) abgelegt. • Vorsicht bei Änderungen an der Enumeration // Variante Ordinal@Enumerated(EnumType.ORDINAL) protected MessageStatus status; // Variante String@Enumerated(EnumType.STRING)protected MessageStatus status;
Temporale Typen • Erlaubte Zeittypen: • java.sql.Date, java.sql.Time, java.sql.Timestamp • java.util.Date, java.util.Calendar • java.sql Typen brauchen keine weitere Definition • Bei java.util Typen muss der JDBC Typ angegeben werden: • Mögliche Typen: TemporalType.DATE, TemporalType.TIME, TemporalType.TIMESTAMP @Temporal(TemporalType.DATE)private Calendar dob;
Transiente Attribute • Attribute können von der Persistierung ausgeschlossen werden • Entweder mittels transient: • oder wenn das Attribut serialisiert werden soll mittels Annotation: transient private String translatedName; @Transientprivate String translatedName;
Entity Identity - Primärschlüssel • Jede Entity-Klasse muss einen mit @Id bezeichneten Primärschlüssel besitzen. • Eine Id kann von folgenden Typen sein: • Primitive Java Typen: byte, int, short, long, char • Wrapper Klassen: Byte, Integer, Short, Long, Character • Array von primitiven Typen oder Wrapper Klassen • java.lang.String • java.math.BigInteger • Zeittypen: java.util.Date, java.sql.Date • Floating Point Typen sind ebenfalls erlaubt, aber sind aufgrund der möglichen Rundungsfehler nicht zu empfehlen