Softwareentwicklung mit Enterprise JAVA Beans JPA - JAVA Persistence API
Problem In JAVA-programmen arbeitet man mit Hauptspeicherobjekten. Nach Beendigung des Programmes sind diese nicht mehr vorhanden. Wie soll Verteilung in Clusterumgebungen erfolgen? Abhilfe zum Persistenzproblem Serialisierung Abbildung in Datenbanken Serialisierung ineffizient, eingeschränkt Abbildung in Datenbanken ständiger Paradigmenwechsel navigierender Zugriff vs. relationalen Operatoren JPA-2
Lösungsansätze Entity Enterprise JavaBeans (EJB) sehr aufwändig Viele proprietäre Systeme zur Abbildung von Java Objekten auf persistente Strukturen entstanden... Hibernate (Oracle) TopLink Erster Ansatz einer standardisierten Lösung JDO JAVA Data Objects Mit Java EE 5: Verschmelzung der Konzepte von EJB und JDO JPA Enterprise Java Beans 3.0 JPA-3
Entity Beans 1 Objektorientierte Repräsentation eines persistenten Business Objektes. Beispiele: Ein Entity, das in einer relationalen DB gespeichert ist Ein Entity, das von einem Legacy-System verwaltet wird. Zur Verwaltung der persistenten Daten: persistent attributes primary key methods providing access to attributes. Ermöglicht parallelen, transaktionssicheren Zugriff auf persistente Daten. Sie sollten nur sehr wenig Geschäftsprozesslogik enthalten. JPA-4
Entity Beans 2 Entity Beans können: einen automatischen Persistenzmechanismus des EJB Containers verwenden: container-managed persistence oder ihren eigenen Persistenzmechanismus implementieren: bean-managed persistence Entity Beans müssen das Transaktionshandling immer dem EJB Container überlassen: container-managed transaction demarcation JPA-5
Entwicklung einer Enterprise Bean 1 Sie sind (RMI-basierte) Objekte unter der Kontrolle des EJB Containers Der Bean Provider erzeugt: Java Schnittstellen: home interface remote interface Java Klassen: bean class (implementing bean s methods) primary key class (for entity beans, optional) Deployment Descriptor: ein XML File: ejb-jar.xml es enthält Metadaten über die Bean Alle Bestandteile kommen in ein EJB JAR Archiv JPA-6
Entwicklung einer Enterprise Bean 2 Zum Deploy-Zeitpunkt generiert der EJB Container: EJBHome Klasse Die Implementierung des Home Interfaces EJBObject Klasse Die Implementierung des Remote Interfaces Der Deployment Descriptor Liefert dem EJB Container die notwendigen Infos zur Erzeugung der EJBHome- und der EJBObject Klasse JPA-7
Entwicklung einer Enterprise Bean 3 Eine Enterprise Bean zur Laufzeit: an EJBHome class instance: EJBHome object an EJBObject class instance: EJBObject object a bean class instance: bean instance (entity beans only): primary key class instance Der Client kann nur auf die Client Stub-Implementierung zugreifen Auf die Instanzen der Bean-Klasse hat nur der EJB-Container Zugriff JPA-8
Bestandteile einer Enterprise Bean «Interface» EnterpriseBean «Interface» Session/EntityBean «Interface» EJBObject «Interface» EJBHome Bean Class «Interface» Remote Interface «Interface» Home Interface «XML file» Deployment Descriptor EJB Spec (package javax.ejb) erstellt Entwickler EJBObject Object EJBHome Object Wird beim Deployment vom EJB Container erzeugt JPA-9
Der JPA Ansatz Reduktion der notwendigen Klassen, Schnittstellen und Konfigurationsdateien Nutzung von Annotationen Einfachere Abbildung auf Relationen Verwendbarkeit auch außerhalb des EJB-Containers Neue Anfragesprache "Java Persistence Query Language" Eine Erweiterung der früheren EJB QL u.a. mit Outer Join und Subqueries Die Entity-Objekte sind POJOs (Plain Old Java Objects) JPA kann von existierenden Mappern (leicht) implementiert werden. JPA-10
persistence.xml Konfigurationsdatei für ein oder mehrere Entity Beans Anbindung der Datenquelle <persistence-unit name="jee_unit" transaction-type="jta"> <jta-data-source> jdbc/javaeeds </jta-data-source>... </persistence-unit> Alternative: transaction-type="resource_local" Falls keine Teilnahme an verteilten Transaktionen gewünscht Viele weitere Optionen möglich z.b.: <provider> oracle.toplink.essentials.persistenceprovider </provider> JPA-11
JPA Entity Beans Annotationen kennzeichnen die Attributzuordnung @Entity @NamedQuery(name = "Category.findAll", query = "select o from Category o") public class Category implements Serializable { @Id @Column(nullable = false) private String categoryid; @Column private String description; @Column(nullable = false) private String name; @OneToMany(mappedBy = "category") private List<Product> productlist;... JPA-12
Mapping Beziehungen Vielfältige Möglichkeiten auf das Verhalten Einfluss zu nehmen @OneToMany(mappedBy = "category", fetch=fetchtype.eager, cascade={cascadetype.all} ) private List<Product> productlist;... CascadeType Möglichkeiten CascadeType.PERSIST CascadeType.REMOVE CascadeType.REFRESH CascadeType.MERGE JPA-13
Verbindungsaufbau Basiert auf persistence.xml Je nachdem, ob die Anwendung im EJB-Container läuft, im Web- Container oder komplett extern können unterschiedliche Verbindungsinformationen im Code injiziert werden Beispiel: Manuelle Deklaration ohne Injizierung: EntityManager em; EntityManagerFactory emf; emf = Persistence.createEntityManagerFactory("JEE_UNIT"); em = emf.createentitymanager(); JPA-14
Verbindungsaufbau 2 Nutzung von JPA im EJB-Container (z.b. in SessionBeans) Injizierung des PersistenceContextes @PersistenceContext private EntityManager em; public Product lieswas (String param) { Query query = em.createquery(...); } Nutzung von JPA im Web-Container (z.b. in Servlets) Injizierung der PersistenceUnit @PersistenceUnit(unitName="JEE_UNIT") private EntityManagerFactory emf; public Product lieswas (String param) { EntityManager em = emf.createentitymanager(); Query query = em.createquery(...); } JPA-15
Transaktionen Unterscheidung Container-Managed Entity Managers Kontrolle durch TA-Server ermöglicht verteilte Transaktionen @PersistenceContext EntityManager em; Application-Managed Entity Managers Kontrolle durch Applikation EntityManager em;... em.gettransaction().begin();... em.persist(o); em.gettransaction().commit(); JPA-16
Daten Lesen Lesen über Key Category c = em.find(category.class, id); Dynamic Queries String q = "SELECT c FROM Category c WHERE c.name LIKE :cn" List cl = em.createquery(q).setparameter("cn", name)).getresultlist() ; Named (Static) Queries List cl = em.createnamedquery("findcatsbyname").setparameter("cn", name)).getresultlist(); // in Category.java @NamedQuery(name="findCatsByName", query= "SELECT c FROM Category c WHERE c.name LIKE :cn") JPA-17
Vergleich zu SQL Ähnlicher Aufbau QL_statement ::= select_clause from_clause [where_clause][groupby_clause][having_clause][orderby_clause] Beispiel JOIN SELECT p FROM Product p JOIN p.categoryid Category c WHERE c.name = 'Fish' Auch UPDATE/DELETE-Statements sind möglich Zusätzlich auch navigierende Zugriffe SELECT p FROM Product p WHERE p.category.name = 'Fish' Vollständige Syntax SELECT p.category FROM Product p WHERE p.name = 'Karlchen' http://java.sun.com/javaee/6/docs/tutorial/doc/bnbuf.html JPA-18
Daten verändern Anlegen Category c = new Category (name, description); em.persist(c); Ändern Category c = em.find(category.class, id); c.setname (newval); // Falls Instanz nicht mehr mit em verbunden: // em.merge (c); Löschen Category c = em.find(category.class, id); em.remove(c); JPA-19
Schlüsselgenerierung Über Sequence @Id @GeneratedValue( strategy=generationtype.sequence, generator="catseq" ) @SequenceGenerator( name="catseq", sequencename="cat_seq", allocationsize=5 ) Über Id-Tabelle @Id @GeneratedValue( strategy=generationtype.table, generator="gentab" ) @TableGenerator( name="gentab", table="gen_table", pkcolumnname="gen_key", valuecolumnname="gen_value", pkcolumnvalue="category_max_id", allocationsize=5 ) JPA-20
Resumee JPA ist wesentlicher einfacher zu verwenden als Entity EJBs funktioniert auch in Java SE! allerdings dann nur Application-Managed Entity Managers ist eine herstellerübergreifende Schnittstellenspezifikation, gegen die programmiert werden kann erfordert konkrete Implementierung Weitere Infos z.b. durch Hibernate, Toplink, etc. http://java.sun.com/javaee/6/docs/tutorial/doc/ (Part V) http://www.oracle.com/technology/products/ias/toplink/jpa/ JPA-21