JPL – THE NEXT GENERATION Stefan Bacher, Klaus Huthmacher | JBFOne 2009
Ziel dieses Vortrags Vorstellung des neuen JBF-Persistenz-Frameworks JPL Welche Vorteile bietet das neue Framework Erster Eindruck zur Verwendung des Frameworks in Anwendungen Dos and Don‘ts im Umgang mit OR-Mappern
Agenda JBF-Persistenz – Gestern und Heute JPL – Die Architektur JPL – Die Unterschiede kompakt JPL – Die Verwendung Stolpersteine beim O/R-Mapping
Agenda JBF-Persistenz – Gestern und Heute JPL – Die Architektur JPL – Die Unterschiede kompakt JPL – Die Verwendung Stolpersteine beim O/R-Mapping
DAM - Data Access Management JPL - JBF Persistence Layer Person.addKonto() Select … Update … Kunde.getName() … Insert … Adresse.setOrt(…)
Ziele der Neuentwicklung Vereinfachung der Verwendung des Persistenzframeworks Bessere Abfragemöglichkeiten Massenverarbeitung Nur eine Persistenz-Schnittstelle (auch für natives SQL) Nutzung des TXManagers aus JBF obligatorisch Migration auf JPL ohne Datenmigration Temporale und bitemporale Datenhaltung
Agenda JBF-Persistenz – Gestern und Heute JPL – Die Architektur JPL – Die Unterschiede kompakt JPL – Die Verwendung Stolpersteine beim O/R-Mapping
Architektur – Komponentensicht (Bi)Temporale Zugriffe Klassisch Temporal BiTemporal BPS (Bi)Temporale Erweiterung Java Persistence API
JPA – Java Persistence API JPA ist der Nachfolger von JDO (Java Data Objects) zweiter Versuch der Definition einer Persistenzschnittstelle für Java Definition als Bestandteil von EJB 3.x Erfahrungen von JDO, Hibernate und TopLink flossen in die Entwicklung ein „Der“ Persistenz-Mechanismus für EJB- und Standard-Java-Anwendungen JPA definiert wie JDO nur eine Schnittstelle Implementierungen vieler Hersteller Hibernate Entity Manager TopLink Essentials (Oracle/Sun) EclipseLink JPA OpenJPA (Apache)
JPA – Java Persistence API Mächtige (SQL-nahe) Abfragesprache JPAQL objektorientiert Joins, Unterabfragen, Projektionen, Aggregationsfunktionen, Gruppierungen RDBMS-unabhängig natives SQL über die gleiche Schnittstelle ist möglich Mengenoperationen bemerkenswerteste Neuerung in JPA direkte Formulierung von Update- und Delete-Anweisungen über JPA Kein Einsatz von nativem JDBC mehr notwendig keine Objektinstanziierung bei Ausführung der Operationen
Fazit JPA ist ein gelungener Standard für Persistenz Leichtgewichtiges Programmiermodell durch die Verwendung von Annotationen Persistenz fügt sich nahtlos in die Java-Entwicklung ein JPAQL ermöglicht komplexe RDBMS-unabhängige Abfragen mit derselben Technologie, die für Unternehmensanwendungen verwendet wird Mengenoperationen zur Massenverarbeitung von Daten sind möglich ABER: Standard reicht nicht immer aus (Funktionalität, Performanz) Zusätzliche Funktionalitäten müssen in der Wrapperschicht (JPL) bereit gestellt werden Funktionalitäten des zugrundeliegenden Providers müssen verwendet werden
Architektur – Komponentensicht (Bi)Temporale Zugriffe Klassisch Temporal BiTemporal BPS (Bi)Temporale Erweiterung Java Persistence API
Architektur – Komponentensicht JPL = JBF Persistence Layer neues objektorientiertes Persistenz-Framework für JBF JPL ist eine Kapsel der zugrunde liegenden Basis JPA mit Hibernate als Implementierung JPL bietet für jedes DAM-Feature ein Äquivalent neue, zusätzliche Features Vereinfachung in der Nutzung umfangreichere Abfragemöglichkeiten durch JPAQL Performancevorteile Erweiterungen für die Bearbeitung von Massendaten Erweiterungen für die (bi)temporale Datenspeicherung (Bi)temporales Zugriffsmodul (BPS = Bitemporal Persistence Services) Implementiert vordefinierte, fachlich orientierte Zugriffe auf (bi)temporale Daten zur Vereinfachung der Anwendungsprogrammierung xxx : nicht Bestandteil dieses Vortrags
PersistenceManager & Co create createOrUpdate delete createQuery PersistenceManager has IPersistenceManager IDatastore Anwendung executeUpdate getResult HibernateDS uses IQuery HibernateQuery uses Java Persistence API returns hasNext / next HibernateCursor ICursor uses API des Frameworks Implementierung des Frameworks
PersistenceManager & Co IPersistenceManager als Schnittstelle der Anwendung für das Lesen, Erzeugen, Ändern und Löschen von Objekten und Objektmodellen IQuery und ICursor als Schnittstelle für die Abfrage von Daten
Mapping der Modelle MAPPING MAPPING SO-Modell DO-Modell Mapper-Klassen Java Persistence API Mapping-Metadaten projektspezifisch generiert
Mapping der Modelle Mapper zwischen Objektmodell der Anwendung (DO-Modell) und Persistenzmodell (SO- Modell) sind generiert Mapper sind projektspezifisch Mapping zwischen DO-Modell und SO-Modell erfolgt im JPL-Framework Mapping ist transparent für die Anwendung Anwendung übergibt ihr DO-Modell an das Persistenzframework Anwendung erhält vom Persistenzframework ein DO-Modell als Ergebnis der Abfrage
Mapping der Modelle MAPPING MAPPING SO-Modell DO-Modell Mapper-Klassen Java Persistence API Mapping-Metadaten projektspezifisch generiert
Mapping der Modelle Mapping zwischen dem SO-Modell des Frameworks und der Datenbank erfolgt über Mapping-Metadaten in XML beschrieben Definition des Mappings der Java-Objekte auf die Artefakte der relationalen Datenbank Abbildung Klasse auf Tabelle Abbildung Attribut auf Spalte Abbildung der Vererbungshierarchie Abbildung von Beziehungen zwischen Entitäten Mapping-Metadaten werden durch den RSA aus dem Modell generiert
Locking und Transaktionshandling Für den konkurrierenden Zugriff auf Daten verwendet JPL optimistisches Locking über die Versionsnummer pro Objekt Transaktionen werden über den Transaktionsmanager von JBF gesteuert JPL verwendet eine vorhandene Transaktion falls keine Transaktion aktiv ist, stellt jeder Persistenzzugriff eine eigenständige Transaktion dar
Agenda JBF-Persistenz – Gestern und Heute JPL – Die Architektur JPL – Die Unterschiede kompakt JPL – Die Verwendung Stolpersteine beim O/R-Mapping
Die Unterschiede kompakt Anwendungsschnittstelle ist aSA-konform JPAQL (mächtige Abfragesprache) Nur DO-Klassen in der Anwendung bekannt Mapping transparent im JPL-Framework Generierung direkt aus RSA Natives SQL direkt über JPL-Schnittstelle möglich Unterstützung Massenverarbeitung (Bi)Temporale Datenhaltung Activity als Anwendungsschnittstelle JDOQL SO-Klassen sind in der Anwendung bekannt Mapping explizit in der Anwendung Generierung über externe DAM- Generatoren Einsatz von nativem SQL nur sehr beschränkt möglich
Agenda JBF-Persistenz – Gestern und Heute JPL – Die Architektur JPL – Die Unterschiede kompakt JPL – Die Verwendung Stolpersteine beim O/R-Mapping
JPL – Die Verwendung DEMO RSA-Modellierung Generierung aus RSA 100 Prozent generierter Code vs. Usercode PersistenceManager AbstractPersistenceFacade Pathklassen Fetchgroups vordefinierte C(R)UD Zugriffe Implementierung der Abfragen PersistenceFassadeImpl CustomTypeMapper DEMO
Agenda JBF-Persistenz – Gestern und Heute JPL – Die Architektur JPL – Die Unterschiede kompakt JPL – Die Verwendung Stolpersteine beim O/R-Mapping
Stolpersteine beim O/R-Mapping O/R-Mapper als Blackbox Funktionen des O/R-Mappers Abbildung der Abfrageresultate auf Objektmodelle Steuerung der JDBC-Schicht Transaktionssteuerung Caching Ohne Verständnis für die Funktionsweise des O/R-Mappers ist es schwierig, das Verhalten und die erzeugten SQL-Abfragen vorherzusagen Das Verständnis der Details ist aber erforderlich, um Datenbankzugriffe optimal und performant zu implementieren
Stolpersteine beim O/R-Mapping Falsche Verwendung O/R-Mapper unterstützen CRUD Operationen auf Objektebene das bedeutet aber auch, dass immer ganze Objekte oder Objektbäume verarbeitet werden Bei Geschäftsobjekten meist erwünscht Bei Übersichten unnötig Netzwerktraffic Speicherverbrauch Datenbank-Zugriffe Projektionen Vererbungshierachien
Stolpersteine beim O/R-Mapping Bulk-Operationen über O/R-Layer Verwenden eines O/R-Mappers für Massenoperationen auf Daten tritt oft schleichend auf keine Planung/Modellierung der Datenzugriffe Generische Abfragen generische Abfragebehandlung Objekte werden immer einzeln aus der DB geladen großes Problem bei Master-Detail-Beziehungen als 1+n Statements-Problematik benannt Datenmanipulationskommandos direkt verwenden Nicht zu verwechseln mit Lazy Loading Die Ladestrategie definiert lediglich wann Objekte geladen werden und nicht wie! Diese Stategie ist der Default Wenn aber schon bekannt ist, welche Objekte wir benötigen, sollten wird das in der Abfrage berücksichtigen bzw. explizit angegeben werden. Dadurch wird es dem O/R Mapper möglich die Anzahl der DB Zugriffe zu minimieren. Oft lassen sich eine Große Anzahl von DB Abfragen auf einen einzige reduzieren! Dadurch werden auch unnötige Netzwerkroudtrips vermieden Hier lassen sich massive Performanceoptimierungen erreichen.
Stolpersteine beim O/R-Mapping Gleichbehandlung unterschiedlicher Daten Daten für einen Anwendungsfall für viele Anwendungsfälle lesend schreibend ... Cachingpotenzial bleibt meist ungenutzt Datenmanipulationskommandos direkt verwenden Nicht zu verwechseln mit Lazy Loading Die Ladestrategie definiert lediglich wann Objekte geladen werden und nicht wie! Diese Stategie ist der Default Wenn aber schon bekannt ist, welche Objekte wir benötigen, sollten wird das in der Abfrage berücksichtigen bzw. explizit angegeben werden. Dadurch wird es dem O/R Mapper möglich die Anzahl der DB Zugriffe zu minimieren. Oft lassen sich eine Große Anzahl von DB Abfragen auf einen einzige reduzieren! Dadurch werden auch unnötige Netzwerkroudtrips vermieden Hier lassen sich massive Performanceoptimierungen erreichen.
Stolpersteine beim O/R-Mapping Schlechte Modellierung des Datenzugriffs Datenzugriffe sind nicht ausreichend von der Anwendung getrennt Ladezeitpunkt von Daten sind nicht ausreichend definiert Definition, welche Daten für einzelne Operationen notwendig sind, fehlt DB-Verbindung wird unnötig lange aufrecht erhalten resource hiding Datenmanipulationskommandos direkt verwenden Nicht zu verwechseln mit Lazy Loading Die Ladestrategie definiert lediglich wann Objekte geladen werden und nicht wie! Diese Stategie ist der Default Wenn aber schon bekannt ist, welche Objekte wir benötigen, sollten wird das in der Abfrage berücksichtigen bzw. explizit angegeben werden. Dadurch wird es dem O/R Mapper möglich die Anzahl der DB Zugriffe zu minimieren. Oft lassen sich eine Große Anzahl von DB Abfragen auf einen einzige reduzieren! Dadurch werden auch unnötige Netzwerkroudtrips vermieden Hier lassen sich massive Performanceoptimierungen erreichen.
Stolpersteine beim O/R-Mapping schlechtes Testen zu wenige Testclients gleichartige DB-Zugriffe keine Regressionstests Locksituationen werden nicht aufgedeckt Performanceverschlechterungen fallen nicht auf Locksituationen werden nicht aufgedeckt
Stolpersteine beim O/R-Mapping Fazit: Nutzung eines O/R-Mappers ist nicht so einfach, wie es die APIs versprechen Um Performanceprobleme zu vermeiden, muss man die Arbeitsweise des O/R Mappers verstehen die Datenzugriffe bereits in der Architektur/im Design berücksichtigen auf die zuvor genannten Punkte achten Auslöser der meisten Probleme ist die Programmlogik Fehler, die hier gemacht werden, können in den nachfolgenden Schichten nicht mehr kompensiert werden, sondern potenzieren sich dort eher noch der beste Datenbankzugriff ist derjenige, der vermieden wird Locksituationen werden nicht aufgedeckt
Zusammenfassung Vorstellung des neuen JBF-Persistenz-Frameworks JPL Welche Vorteile bietet das neue Framework Erster Eindruck zur Verwendung des Frameworks in Anwendungen Stolpersteine im Umgang mit OR-Mappern
Stefan Bacher Klaus Huthmacher Fragen? – Diskussion? Technische Architektur stefan.bacher@fiducia.de 089 – 9943 3398 Klaus Huthmacher Technische Architektur klaus.huthmacher@fiducia.de 089 – 9943 3134
Ihr IT-Partner Vielen Dank
JPA – Eigenschaften Transparente Persistenz Entitäten sind POJOs (Plain Old Java Objects) keine speziellen Interfaces kein Enhancement des Bytecodes keine erforderlichen Callbackmethoden Programmier-Interface für das Lesen, das Speichern und die Abfrage von Entitäten Abfrage der Daten erfolgt unter Verwendung einer SQL-ähnlichen Abfragesprache JPA ist in unterschiedlichen Umgebungen lauffähig standalone in der JAVA SE-Umgebung innerhalb eines J2EE-Containers
JPA – Eigenschaften Mapping in die Datenbank über Annotationen im Code oder über externe xml- Beschreibung Assoziationen zwischen Entitäten 1 – 1 - Beziehung 1 – n - Beziehung m – n - Beziehung Denormalisierung durch eingebettete Objekte möglich Vererbung bei Entitäten per-concrete-class per-class single-table Transaktionen durch interne TX-Verwaltung („non managed“-Umgebung) durch JTA-konformen Manager („managed“ im Applicationserver)
Query Mit Pathklassen Ohne Pathklassen public DOKunde sucheKundeAnhandName(String nachName) { DOKundePath kunde = DOKundePath.get(„k"); String qryString = "select k from " + kunde.entity() + " where " + kunde.name() + " = " + nachName; IQuery<DOKunde> qry = getPersistenceManager().createQuery(qryString, DOKunde.class); return qry.getUniqueResult(); } Ohne Pathklassen public DOKunde sucheKundeAnhandName(String nachName) { DOKundePath kunde = DOKundePath.get(„k"); String qryString = "select k from SOKunde k where k.name = " + nachName; IQuery<DOKunde> qry = getPersistenceManager().createQuery(qryString, DOKunde.class); return qry.getUniqueResult(); }
Query public DOKunde sucheKundeAnhandName (String nachname) { DOKunde kunde = null; String constraint = SOKunde.NAME + "==" + nachname; IQuery query = qyFactory.createQuery(ws, SOKunde.class, constraint); try { ICursor it = query.execute(); if (it.hasNext()) { IStorableObject nextObject = it.next(ws); IStorableReadMapper theMapper = (IStorableReadMapper)AuwMapperFactory.getDeepMapper4Read (new Object[]{IDataMgmtQueryFactory.class.getName(), qyFactory}, nextObject.getClass()); Pair p = it.next(ws, theMapper, nextObject); kunde = (DOKunde) ((SOKundeMapper) p.getFirst()).getDOKunde(); } catch (Exception e) { doExceptionHandling(); finally { if (query.isExecutedOrCompiled()) { query.closeAll(); return kunde;