Download - JPA - Java Persistence API
JPA - Java Persistence API
Thomas WöhlkeObjectCode GmbH
12.03.2009
JPA: Agenda
© 2009 ObjectCode GmbH
Domain Object Model
© 2009 ObjectCode GmbH
Object-Relational MappingAnalogie: OO RDB
1. Klasse Tabelle2. Objekt Zeile3. Variable Spalte4. Wert Feld
Domain Object Modell = ERD ?
© 2009 ObjectCode GmbH
O/R Impedance Mismatch
© 2009 ObjectCode GmbH
O/R Impedance Mismatch
© 2009 ObjectCode GmbH
Domain Object Model: GLE
© 2009 ObjectCode GmbH
... und die Physik?
• v(Harddisk) << v(RAM)• CPU 99% idle• Process 99% IO_WAIT• Page Impressions SQL-Requests?
© 2009 ObjectCode GmbH
Anno Domini 2004...
© 2009 ObjectCode GmbH© 2004-2005 TheServerside.com
HibernateMapping von POJO‘s:1. Java Bean API2. Collection API (Generics)3. Mapping:
XML oder Hibernate-Annotations
Hibernate ist ein JPA-Vendor:1. Hibernate-Core2. Hibernate-Annotations3. Hibernate Entity Manager
© 2009 ObjectCode GmbH
Von Hibernate nach JPA
© 2009 ObjectCode GmbH
JPA im JEE-Stack
© 2009 ObjectCode GmbH
persistence.xml (Java EE)<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="JPM_DB"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>java:/JpmDS</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <property name="hibernate.show_sql" value="true"/> <!-- These are the default for JBoss EJB3, but not for HEM: --> <property name="hibernate.cache.provider_class"
value="org.hibernate.cache.HashtableCacheProvider"/> <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/> </properties> </persistence-unit></persistence>
© 2009 ObjectCode GmbH
persistence.xml (Java SE)<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="JPM_DB"> <provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.woehlke.projecteering.kernel.calendar.pao.Day</class> <class>org.woehlke.projecteering.kernel.minutes.pao.Event</class> <class>org.woehlke.projecteering.kernel.minutes.pao.Minutes</class> <class>org.woehlke.projecteering.kernel.minutes.pao.MinutesItem</class> <class>org.woehlke.projecteering.kernel.projects.pao.Project</class> <class>org.woehlke.projecteering.kernel.projects.pao.ProjectCategory</class> <class>org.woehlke.projecteering.kernel.timerecording.pao.TimeRecordingItem</class> <class>org.woehlke.projecteering.kernel.userrights.pao.Company</class> <class>org.woehlke.projecteering.kernel.userrights.pao.Team</class> <class>org.woehlke.projecteering.kernel.userrights.pao.User</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.generate_statistics" value="true"/> <property name="hibernate.show_sql" value="true"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> <property name="hibernate.connection.username" value="jpm"/> <property name="hibernate.connection.password" value="jpmpwd"/> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpm"/> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/></properties> </persistence-unit></persistence>
© 2009 ObjectCode GmbH
Mapping der Klassen 1public class Customer extends Person { @OneToMany(mappedBy=“purchaser”) Set<Order> orders = new HashSet<Order>(); protected Customer() { } // for loading from db public Customer(String fname, String lname) { super(fname, lname); } public void addOrder(Order o) { orders.add(o); } public Set<Order> getOrders() { return orders; }}
© 2009 ObjectCode GmbH
Mapping der Klassen 2@Entity@Table(name=“PRODUCTS”)public class Product { @Id @GeneratedValue @Column(name=“PRODUCT_PK”) long id; @Version int oplock; // column defaults to “OPLOCK” String name; // column defaults to “NAME”
@ManyToOne @JoinColumn(name=“SUPP_FK”, referencedColumnName=“SUPP_PK”) Supplier supplier; ...}
© 2009 ObjectCode GmbH
Mapping der AssoziationenKardinalität:1. 1:1 OneToOne 2. 1:n OneToMany3. n:m ManyToMany
Richtung:1. 1:n -> OneToMany2. N:1 <- ManyToOne
Sichtbarkeit:1. Unidirektional ->2. Bidirektional <->
© 2009 ObjectCode GmbH
Mapping der Vererbung
1. Eine Tabelle pro Klassen-Hierarchie2. Eine Tabelle pro konkrete Klasse3. Eine Tabelle pro Subklasse4. Non-Entity Vererbung5. Keine Vererbung: Embbeding
© 2009 ObjectCode GmbH
Mapping der Vererbung?
© 2009 ObjectCode GmbH
Einsatz von JPA im JBoss/EJB3@Statelesspublic class MinutesItemDao extends BaseDao<MinutesItem> implements
IMinutesItemDao {
@PersistenceContext(unitName = "JPM_DB") private EntityManager entityManager;
public MinutesItem findById(Long id) { return entityManager.find(MinutesItem.class,id); }
public EntityManager getEntityManager() { return entityManager; }
public void setEntityManager(EntityManager entityManager) { this.entityManager = entityManager; }}
© 2009 ObjectCode GmbH
Einsatz von JPA in Spring/Tomcat@Transactionalpublic class MinutesDao extends BaseDao<Minutes> implements
IMinutesDao {
public Minutes findById(Long id) { return jpaTemplate.find(Minutes.class,id); }
}
© 2009 ObjectCode GmbH
EJB-QLQuery q = em.createQuery(“select c from Customer c where c.firstName
= :fname order by c.lastName”);q.setParameter(“fname”, “Joe”);q.setFirstResult(20);q.setMaxResults(10);List<Customer> customers = (List<Customer>) q.getResultList();
// all orders, as a named query@Entity @NamedQuery(name=“Order:findAllOrders”, query=“select o from Order o”);public class Order { ... }
Query q = em.createNamedQuery(“Order:findAllOrders”);
© 2009 ObjectCode GmbH
Lebenszyklus Persistente Objekte
1. Neu, transient (@Id id == null)2. Persistent (@Id id != null)3. Detached:
– Wie persistent (@Id id!= null)– Jedoch ausserhalb des EntityManager Kontext– Lazy Loading nicht möglich!– Änderungen in DB sichern mit merge
© 2009 ObjectCode GmbH
EJB-QL // all people, via a custom SQL statementQuery q = em.createNativeQuery(“SELECT ID, VERSION, SUBCLASS,
FIRSTNAME, LASTNAME FROM PERSON”, Person.class);List<Person> people = (List<Person>) q.getResultList();
// single-result aggregate: average order total price Query q = em.createQuery(“select avg(i.price) from Item i”);Number avgPrice = (Number) q.getSingleResult();
// traverse to-many relationsQuery q = em.createQuery(“select o from Order o left join o.items li where
li.price > :price”);q.setParameter(“price”, 1000);List<Order> orders = (List<Order>) q.getResultList();
© 2009 ObjectCode GmbH
Lazy Loading• Supplier s = order.getItem().getProduct().getSupplier();• Bei Aufruf eines Getters wird Objekt aus DB-Zeile nachgeladen.• Ohne Lazy Loading muss komplettes Objekt-Netz geladen werden.• Struktur des Objekt-Netzes variiert je nach Web-View
© 2009 ObjectCode GmbH
DAO und „Unit of Work“
© 2009 ObjectCode GmbH
Ausblick: Seam• Kern-Entwickler von Hibernate sind nun im Seam-
Projekt• O/R-Mapping von EJB3/JPA auch für die
Webapplikation• OO im Datenbankbackend durch ORM• OO im Webfrontend durch JSF• Im Conversation-Scope ist Lazy-Loading möglich.• Detached Objects können für die Webview
verwendet werden: Kein DTO-Antipattern
© 2009 ObjectCode GmbH
RTFM: http://www.hibernate.org/O‘Reilly: Enterprise JavaBeans 3.0Manning: EJB3 in ActionManning: Hibernate in Action
Literatur
© 2009 ObjectCode GmbH
FRAGEN? Fragen!
... Vielen Dank für die Aufmerksamkeit
© 2009 ObjectCode GmbH