Sei sulla pagina 1di 66

JPA - Java Persistence Api

Talk Outline
• Object Relational Mapping
• Why JPA?
• JPA versions
• JPA interfaces
• Simple JPA example
• JPA Object life cycle
• JPA standalone - Spring
• ORM JPA 1.0 – JPA 2.0
• Java Persistence Query Language JPA 1.0 – JPA 2.0
• Criteria API JPA 2.0
• Concurrency
• Caching
Object relational mapping issues

• Mapping objects to relational data is hard!


• The two systems satisfy different needs.
– Structured data storage/retrieval/sorting vs. entity that represents the
state and functions of a real world thing.
• There are a number of obstacles to overcome based in the
differences (see Hibernate presentation)
– Identity
– Granularity
– Associations
– Navigation
– Inheritance
– Data type mismatches
Why JPA?
• Hibernate was one of the first object-relational mapping frameworks.
(°2001),In English: an ORM provides tools to get in an out of the
database
– java objects
– their relationships to other objects
• It does so without a lot of intrusion.
– You don’t have to know a lot of API.
– You don’t have to know or use a lot of SQL.
– But … each ORM has its own custom API for persisting mapped objects (iBatis, JDO, Toplink,
Castor…)
• JPA is a specification for a generic ORM
– Not an implementation
– Vendor-neutral
– Based java 1.5 annotations ( javax.persistence)  use Hibernate or alternatives for Java 1.4
Java Persistence API
The standard API for object/relational persistence
for Java SE and Java EE applications
• Mapping is explicit, not “magic”
– Uses annotations and/or XML
– Many useful defaults
– Lots of hooks and options for customization
• SQL-like query language (JPQL)
– Applied to domain model
– Supports both static and dynamic queries
JPA implementations
All these ORMs use the same API
• Open-source:
–Hibernate >=3.2 (still supports legacy config)
–GlassFish - EclipseLink RI (Reference Impl)
–Apache OpenJPA
• Commercial:
–SAP NetWeaver
–Oracle TopLink
–Oracle Kodo
JPA versions
JPA 1.0 Part of the EJB 3 Specification (JSR 220 may
2006)
• Introduced as part of Java EE 5
– required to be supported under Enterprise JavaBeans 3.0.
– also targeted stand-alone with Java SE
• Part of the EJB 3.0 simplification effort
– no need for Data Access Objects, Data Transfer Objects ,
deployment descriptors, Home interface
– contributions from the Hibernate, TopLink, and JDO , EJB
communities
– Covered all the essentials
JPA versions
JPA 2.0 (JSR 317 dec 2009)
• Improvements of JPA 1.0
– More sophisticated mapping and modeling options
– Expanded query interfaces and query language.
• adds
– API for criteria queries
– a metamodel API
– support for validation.
• EclipseLink is reference implementation
• Integrated in GlassFish
JPA interfaces
• EntityManagerFactory
– Used to create entity managers
– One entity manager factory per persistence unit (db conn)
• EntityManager
– Used to manage persistence context
• Entities read/written from database
– Operations: persist, remove, find, refresh, createQuery,…
• Query, TypedQuery
– Used for query configuration
– parameter binding
– query execution
EntityManager
set of entities
managed by
API for managing entities Entity Manager
EntityManager
persist()
remove()
refresh()
merge()
find()
createQuery()
createNamedQuery
Persistence
() Context
contains()
flush()
JPA – Hibernate
JPA has many components that can be
somewhat mapped to Hibernate:
• EntityManagerFactory –> SessionFactory,
• EntityManager –> Session,
• Query –> Query
• EntityTransaction –>Transaction.
Simple JPA example

• So what does JPA code package com.intertech.JPA.Customer;


import java.util.Date;

look like? import javax.persistence.*;


@Entity (name="Emp")

• Let’s start with a public class Customer {


@Id private long id;
customer class like that private String name;
private char gender; // m = male; f = female; private
to the right. Date dateOfBirth;
public Date getDateOfBirth() {return dateOfBirth; }
• Configuration by public void setDateOfBirth(Date dateOfBirth)
{ this.dateOfBirth = dateOfBirth;}
exception public char getGender() { return gender; } public
void setGender(char gender) { this.gender =
@Entity (name="Emp") gender; }
public long getId() { return id; }

Default table name = class private void setId(long id) { this.id = id; } public
String getName() { return name; } public void
name setName(String name) { this.name = name; }
Creating and saving

• Code to create a couple of //package and imports removed for brevity


public class MakeCustomers {
customers and save them to public static void main(String[] args) {
Customer tom = new Customer(); tom.setName(\"Tom
the DB. Salonek\"); tom.setGender('M');
tom.setDateOfBirth(new Date());
• CustomerService Customer dan = new Customer(); dan.setName(\"Dan
McCabe\"); dan.setGender('M');
connection is defined in dan.setDateOfBirth(new Date());
persistence.xml EntityManagerFactory emf = Persistence.
createEntityManagerFactory(“CustomerService“);
• In fact, the EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
EntityManagerFactory line em.persist(tom);
is usually done elsewhere. em.persist(dan);
em.getTransaction().commit();
em.close();
emf.close(); }
}
Creating and saving (remember Hibernate)

• Code to create a couple of //package and imports removed for brevity


public class MakeCustomers {
customers and save them to public static void main(String[] args) {
Customer tom = new Customer();
the DB. tom.setName(\"Tom Salonek\");
tom.setGender('M'); tom.setDateOfBirth(new
Date());
Customer dan = new Customer();
dan.setName(\"Dan McCabe\"); dan.setGender('M');
dan.setDateOfBirth(new Date()); SessionFactory sf =
new Configuration().
configure().buildSessionFactory();
Session session = sf.openSession(); Transaction trx =
session.beginTransaction(); session.save(tom);
session.save(dan);
trx.commit();
session.close();
sf.close(); }
}
Retrieving

//package and imports removed for brevity


• Code to fetch and iterate import org.JPA.*;
through all the import org.JPA.cfg.Configuration;
import java.util.*;
customers. public class ReadCustomers {
public static void main (String[] args){
EntityManagerFactory emf = Persistence.
createEntityManagerFactory(“CustomerService“);
EntityManager em = emf.createEntityManager();
Query q = em.createQuery(\"from Customer\");
List customers = q.getResultList();
for (Iterator i=customers.iterator(); i.hasNext(); )
{ Customer cust = (Customer)i.next();
System.out.println(cust.getName()
+ \" says hello.\");
}
em.close();
}
}
Updating

//package and imports removed for brevity public class


• Code to get and update a MakeUpdate {
single employee. public static void main(String[] args) {
EntityManagerFactory emf = Persistence.
createEntityManagerFactory(“EmployeeService“);
EntityManager em = emf.createEntityManager();
Employee emp = em.find(Employee.class, 158);
emp.setSalary(emp.getSalary() + 1000);
em.getTransaction().commit();
em.close();
emf.close();
}
}
Object Lifecycle
• Lifecycle Persistent object (like the tom customer object) are
synchronized with the database.
– That is, the object’s state and the affected database rows are kept the same
whenever either changes.
• Domain objects are in one of five states.
– Does not exist
– New
– Managed
– Detached
– Removed
• An object’s state determine if it is kept synchronized with the database.
• The presence of a EntityManager and certain method calls move an
object between states.
Object state
• http://download.oracle.com/docs/cd/B32110_01/web.1013/b28221/undejbs003.htm#BABIAAGE
Configuring JPA
• A persistence.xml file defines all the database connection information.
• packaged in a persistence archive that contains the persistence.xml file in the
META-INF directory and the entity class files.
<persistence>
<persistence-unit name="EmployeeService"
transaction-type="RESOURCE_LOCAL">
<class>examples.model.Employee</class>
<properties>
<property name="javax.persistence.jdbc.driver"
value="org.apache.derby.jdbc.ClientDriver"/>
<property name="javax.persistence.jdbc.url"
value="jdbc:derby://localhost:1527/EmpServDB;create=true"/>
<property name="javax.persistence.jdbc.user" value="APP"/>
<property name="javax.persistence.jdbc.password" value="APP"/>
</properties>
</persistence-unit>
</persistence>
Catalog Spring JPA Application

Registration Application
Managed Bean Entity Class

Item
DB

ItemController
Catalog
Spring
JSF Components Bean
Spring
Framework
Spring with JPA
Component Stereotype
@Repository Spring transactions use aop
@Transactional
public class CatalogDAO implements CatalogService {

@PersistenceContext(unitName="PetCatalogPu")
private EntityManager em;

@Transactional(readOnly=true)
public List<Item> getItems(int firstItem,int batchSize) {
Query q =
em.createQuery("select object(o) from Item as o");
q.setMaxResults(batchSize);
q.setFirstResult(firstItem);
List<Item> items= q.getResultList();
return items;
}
ORM Essentials JPA 1.0
• Entities
• Basic types
– Strings, integers, floats, decimals, …
• Embeddable classes
– E.g. Address
• Relationships
– One-to-one, one-to-many/many-to-one, many-to-many
– Collections modeled with java.util Collection, Set, List, or Map
– Customized via metadata: @JoinColumn, @JoinTable, etc.
• Inheritance
– Single table, joined subclass, table per class (optional)
Annotations versus XML
@Entity
public class Employee {
@Id private int id;
@Column(name="EMP_NAME")
private String name;
@Column(name="SAL")
private long salary;
// ...
}

orm.xml snippet:
<entity-mappings>
...
<entity class="examples.model.Employee"
metadata-complete="true">
<attributes>
<id name="id"/>
</attributes>
</entity>
...
</entity-mappings>
Associations
• JPA provides a rich set of alternatives for mapping object
associations in the database.
• Providing for all the various multiplicities of relationships.
– Many to one
– One to many
– Many to many
– One to one
• Providing for Java’s understanding of directionality.
– Unidirectional
– Bidirectional
NB Bidirection Many to one  also One to Many
• Providing for fine grained control of “transitive persistence”
Transitive Persistence
• Controls when/how associated objects react to
changes in the other.
– For example, should associated address rows be deleted when a customer object is
removed (cascade delete).
– When an new order is saved should associated new line item objects also be saved
(cascade save).
Association Employee->Department
package examples.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

@Entity
public class Employee {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private long salary;

@ManyToOne
private Department department;

public int getId() {…


public Department getDepartment() {
return department;
}

public void setDepartment(Department department) {


this.department = department;
}
Association Department->Employee
import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Department {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
@OneToMany(mappedBy="department")
private Collection<Employee> employees;

public Department() {
employees = new ArrayList<Employee>();
}
public void addEmployee(Employee employee) {
if (!getEmployees().contains(employee)) {
getEmployees().add(employee);
if (employee.getDepartment() != null) {
employee.getDepartment().getEmployees().remove(employee);
}
employee.setDepartment(this);
}
}

public Collection<Employee> getEmployees() {


return employees;
}
Fetching Strategies
• Along with fetching objects there is a problem when
objects are related to other objects.
– When you fetch a customer, should you also fetch
associated address, order, order item, etc. objects?
– If not, what happens when you do something like the
following?
Customer dave =
(Customer)EntityManager.find(Customer.class, new
Long(3)); dave.getAddress();
– Object graphs can be quite large and complex. How much
and when should objects be retrieved?
Proxy Objects
• JPA provides for specifying both lazy and eager fetching.
– When lazy fetching is specified, it provides proxy objects as
stand- ins for associated objects
– Proxy objects get replaced by the framework when a request
hits a proxy
@Entity
public class Customer{
@Id private int id;
@OneToOne(fetch=FetchType.LAZY)
private Adress adress;
// ...
Inheritance
• JPA also handles inheritance associations.
• In fact, it supports three strategies with regard to inheritance
mapping.
– Table per concrete class
– Table per subclass
– Table per class hierarchy
• Let’s look at an example inheritance tree and examine the
options.
Table per Concrete class
Table per Subclass
Table per Class Hierarchy
Inheritance example
Example of Hierarchy mapping
<class name=“BankAccount”>
<id name=“accountNum” column=“ACCOUNTNUM”> <generator class=“native”/>
</id>
<discriminator column=“TYPE”/>
<property name=“first”/>
<property name=“last”/> ...
<subclass name=“SavingsAccount” discriminator-value=“1”> <property
name=“interestRate” column=“INTEREST”/> ...
</subclass>
<subclass name=“CheckingAccount” discriminator-value=“2”>
<property name=“checkFee” column=“FEE”/> ...
</subclass>
</class>
Object/Relational Mapping
New in JPA 2.0
• Element collections
– Collections of strings, integers, floats, decimals, …
– Collections of embeddable classes
• Embeddable classes
– Nested embeddables; embeddables with relationships
• Persistently ordered lists
• Improved Map support
• More relationship mapping options
– Unidirectional one-many foreign key mappings
– Join table mappings for one-one, one-many/many-one
Collections of Basic Types
@Entity
public class Person {
@Id protected String ssn;
protected String name;
protected Date birthDate;
...
@ElementCollection
protected Set<String> nickNames;
}
Collections of Basic Types
@Entity
public class Person {
@Id protected String ssn;
protected String name;
protected Date birthDate;
...
@ElementCollection
@CollectionTable(name=”ALIAS”)
protected Set<String> nickNames;
}
Multiple Levels of Embedding
@Embeddable public class ContactInfo {
@Embedded Address address;
...
}
@Entity public class Employee {
@Id int empId;
String name;
ContactInfo contactInfo;
...
}
Embeddables with Relationships
@Embeddable public class ContactInfo {
@Embedded Address address;
@OneToMany Set<Phone> phones;
...
}
@Entity public class Employee {
@Id int empId;
String name;
ContactInfo contactInfo;
...
}
Ordered Lists
@Entity public class CreditCard {
@Id long cardNumber;
@OneToOne Person cardHolder;
...
@OneToMany
@OrderColumn
List<CardTransaction> transactions;
}
Maps
@Entity public class VideoStore {
@Id Integer storeId;
Address location;
...
@ElementCollection
Map<Movie, Integer> inventory;
}
@Entity public class Movie {
@Id String title;
@String director;
...
}
Automatic Orphan Deletion
For entities logically “owned” by “parent”
@Entity public class Order {
@Id int orderId;
...
@OneToMany(cascade=PERSIST,
orphanRemoval=true)
Set<Item> lineItems;
...
}
Java Persistence Query Language
• String-based SQL-like query language
– SELECT, FROM, WHERE, GROUP BY, ORDER BY,…
• Queries written over Java domain model
– Entities, state, relationships
– Supports navigation using dot-notation
– Mapped into SQL by the provider
• Supports static and dynamic use

SELECT AVG (p.price)


FROM Order o JOIN o.products p
WHERE o.customer.address.zip = ‘94301’
Java Persistence Query Language
New in JPA 2.0
• Support for all new modeling and mapping
features
• Operators and functions in select list
• Case, coalesce, nullif expressions
• Restricted polymorphism
• Collection-valued parameters for IN-
expressions
JPQL New Operators
INDEX
For ordered Lists
KEY, VALUE, ENTRY
For maps
CASE, COALESCE, NULLIF
For case expressions, etc.
TYPE
For restricted polymorphism
Ordered Lists
SELECT t
FROM CreditCard c JOIN c.transactions t
WHERE c.cardHolder.name = 'John Doe'
AND INDEX(t) < 10
Maps
// Inventory is Map<Movie, Integer>
SELECT v.location.street, KEY(i).title, VALUE(i),
FROM VideoStore v JOIN v.inventory i
WHERE KEY(i).director LIKE '%Hitchcock%'
AND VALUE(i) > 0
Case Expressions
UPDATE Employee e
SET e.salary =
CASE e.rating
WHEN 1 THEN e.salary * 1.05
WHEN 2 THEN e.salary * 1.02
ELSE e.salary * 0.95
END
Restricted Polymorphism
SELECT e
FROM Employee e
WHERE TYPE(e) IN :empTypes
Criteria API
New in JPA 2.0
• Object-based API for building queries
• Designed to mirror JPQL semantics
• Strongly typed
– Based on type-safe metamodel of persistent classes
and relationships
– Heavy use of Java generics
– Supports object-based or string-based navigation
• Query construction at development time or
runtime
Criteria API: Core Interfaces
• CriteriaBuilder
– Used to construct criteria queries, selections, predicates, orderings
• CriteriaQuery
– Used to add / replace/ browse query elements
– from, select, where, orderBy, groupBy, having,… methods
• Root
– Query roots
• Join, ListJoin, MapJoin, …
– Joins from a root or existing join
• Path
– Navigation from a root, join, or path
• Subquery
How to Build a Criteria Query
EntityManager em = …;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<ResultType> cquery = cb.createQuery(ResultType.class);
Root<MyEntity> e = cquery.from(MyEntity.class);
Join<MyEntity, RelatedEntity> j = e.join(…);

cquery.select(…)
.where(…)
.orderBy(…)
.groupBy(…);

TypedQuery<ResultType> tq = em.createQuery(cquery);
List<ResultType> result = tq.getResultList();
Criteria Query Example
SELECT distinct d
FROM Department d, Employee e
WHERE d = e.department

CriteriaQuery<Department> c = cb.createQuery(Department.class);
Root<Department> dept = c.from(Department.class);
Root<Employee> emp = c.from(Employee.class);
c.select(dept)
.distinct(true)
.where(cb.equal(dept, emp.get("department")));
TypedQuery<Department> q = em.createQuery(c);
List l = q.getResultList();
MetaModel – strong typed criteria queries

• Abstract “schema-level” view of managed classes


– Entities, mapped superclasses, embeddables
• Accessed dynamically
– EntityManagerFactory.getMetamodel()
– EntityManager.getMetamodel()
• And/or materialized as static metamodel classes
– Used to create strongly-typed criteria queries
– Spec defines canonical format
Generating Static Metamodel
javac -processor
org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor
-sourcepath src -d src -classpath
/ace2_apps/eclipselink/jlib/eclipselink.jar:.:/ace2_apps
/eclipselink/jlib/JPA/javax.persistence_2.0.0.v200911271158.jar -proc:only
-Aeclipselink.persistencexml=src/METAINF/
persistence.xml src/demo/*.java
Note: Creating the metadata factory …
Note: Building metadata class for round element:
demo.Item
...
http://weblogs.java.net/blog/lancea/archive/2009/12/15/generating-jpa-20-
static-metamodel-classes-using-eclipselink-20-and-n
Entity class
package com.example;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Embedded;
import javax.persistence.OneToMany;
import java.util.Set;

@Entity
public class Customer {
@Id int custId;
@Embedded Address address;
@OneToMany Set<Order> orders;

}
Metamodel Class
package com.example;

import javax.annotation.Generated;
import javax.persistence.metamodel.SetAttribute;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;

@Generated(“EclipseLink JPA 2.0 Canonical Model Generation”)


@StaticMetamodel(Customer.class)
public class Customer_ {
public static volatile SingularAttribute<Customer,Integer> custId;
public static volatile SingularAttribute<Customer,Address>
address;
public static volatile SetAttribute<Customer,Order> orders;

}
Validation
New in JPA 2.0
• Leverages work of Bean Validation (JSR 303)
• Automatic validation upon lifecycle events
– PrePersist
– PreUpdate
– PreRemove
• Validation-mode element in “persistence.xml”
– AUTO, CALLBACK, NONE
• Standardization of many configuration options
Concurrency
• Java Persistence assumes optimistic concurrency
– Short-term read locks
– Long-term write locks
– Provider can defer writing to database to transaction
commit
– Application can flush to database on demand
• Optimistic “locking” done via version attributes
– Integral or timestamp attributes, managed by provider
– Provider validates version when writing to database
– Explicit lock() calls available to validate read data
Pessimistic Locking
New in JPA 2.0
• Java Persistence assumes optimistic concurrency
– Normal pessimistic locking
– Persistent state of entity
• Relationships, Element collections
• Grab database locks upfront
– JPA spec defines semantics, not mechanism
– Provider can lock more (not less)
• Lock modes
– PESSIMISTIC_READ – grab shared lock
– PESSIMISTIC_WRITE – grab exclusive lock
– PESSIMISTIC_FORCE_INCREMENT – update version
Locking APIs
• EntityManager methods: lock, find, refresh
• Query / TypedQuery methods: setLockMode, setHint
• NamedQuery annotation: lockMode element

• javax.persistence.lock.scope property
• javax.persistence.lock.timeout hint

• PessimisticLockException (if transaction rolls back)


• LockTimeoutException (if only statement rolls back)
Locking
Optimistic
// foo is an instance loaded by a previous
Sessionsession = factory.openSession();
int oldVersion = foo.getVersion();session.load( foo, foo.getKey() );
if ( oldVersion!=foo.getVersion ) throw new StaleObjectStateException();
foo.setProperty("bar");
session.flush();
session.connection().commit();
session.close();
Locking
Pessimistic
public Timesheet getTimesheetWithLock(int timesheetId){
Session session = JPAUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Timesheet timesheet = (Timesheet)session.get(Timesheet.class, new Integer(timesheetId),
LockMode.UPGRADE); // NONE, READ, UPGRADE, UPGRADE_NOWAIT, and WRITE
session.getTransaction().commit();
session.close(); 
return timesheet;
}
Caching Configuration
New in JPA 2.0
• EntityManager persistence context corresponds to
“first level” cache
– Entities managed by persistence provider
• Entities read from database
• Entities to be written to database
• Most implementations also use second-level caches
– Not always transparent to application
• JPA 2.0 standardizes basic second-level cache
options
Summary of JPA 2.0 New Features
• More flexible modeling capabilities
• Expanded O/R mapping functionality
• Additions to Java Persistence query language
• Criteria API
• Metamodel API
• Pessimistic locking
• Support for validation
• Standardization of many configuration options
Resources

• JPA 1.0 Part of the EJB 3 Specification JSR-220


http://jcp.org/en/jsr/detail?id=220
• JPA 2.0 – JSR317
http://jcp.org/en/jsr/detail?id=317
• http://wiki.eclipse.org/EclipseLink
• http://www.oracle.com/technetwork/articles/cioroianu-
eclipse-jpa-084626.html
• Books
– Pro JPA 2(Keith/Schincariol – Apress)
Sources http://www.apress.com/book/downloadfile/4522

Potrebbero piacerti anche