Transcript 24 - JPA

The Java Persistence API
©SoftMoore Consulting
Slide 1
The Java Persistence API
•
The Java Persistence API (JPA) is a Java programming
language framework that allows developers to manage
relational data in Java development environments.
Provides a higher-level framework than JDBC for managing
persistent objects
• Background
– originated within the Enterprise JavaBeans 3.0 (JSR 220) expert
group, but a Java EE application server is not required
– merged expertise from TopLink, Hibernate, JDO, EJB vendors,
and individuals
– first released in May 2006 as part of Java EE 5
©SoftMoore Consulting
Slide 2
JPA Implementations
•
GlassFish (Java EE application server)
– reference implementation
– called “TopLink Essentials” (derived from Oracle TopLink)
– https://glassfish.dev.java.net/javaee5/persistence/
•
•
•
Eclipse Persistence Services Project (EclipseLink)
JBoss Hibernate
Apache OpenJPA
©SoftMoore Consulting
Slide 3
JPA Major Components
•
The API
– defined in the javax.persistence package
•
The Java Persistence Query Language (JPQL)
– used to make queries against entities stored in a relational
database
– resembles SQL but operates against entity objects rather than
database tables
•
Object/Relational Metadata
– can be specified directly in the entity class using annotations or
in a separate XML descriptor file
©SoftMoore Consulting
Slide 4
JPA Overview
•
JPA provides persistence for “Plain Old Java Object”
(POJO) entities.
•
Entities can be defined using annotations or an XML
mapping file.
•
An entity typically represents a table in a relational
database, and each object of the class corresponds to a
row in that table.
•
Primary keys and relationships are also indicated by
appropriate annotations on the entity class or entries in
the XML mapping file.
•
Entities are managed by an entity manager.
©SoftMoore Consulting
Slide 5
Requirements for Entity Classes
• Must be annotated with javax.persistence.Entity
• Must have a public or protected, no-argument
constructor (may have other constructors)
•
Must not be declared final. Also, no methods or
persistent instance variables must be declared final.
•
Must have persistent instance variables declared as
private, protected, or package-private
– entity’s state accessed through accessor (get) methods
• May need to implement the Serializable interface
(if passed by value in a remote call)
©SoftMoore Consulting
Slide 6
Persistent Fields and Properties
•
The persistent state of an entity can be accessed either
through the entity’s instance variables or through
JavaBeans-style properties.
– If the mapping annotations are applied to the entity’s instance
variables, the entity uses persistent fields.
– If the mapping annotations are applied to the entity’s getter
methods for JavaBeans-style properties, the entity uses
persistent properties.
•
You cannot apply mapping annotations to both fields and
properties in a single entity.
©SoftMoore Consulting
Slide 7
Java Types for Persistent Fields/Properties
• Primitive types
• String
• Enumerated types
• Other entities and/or
collections of entities
–
–
–
–
•
java.util.Collection
java.util.Set
java.util.List
java.util.Map
Embeddable classes
©SoftMoore Consulting
•
Other serializable types:
–
–
–
–
–
–
–
–
–
–
–
–
–
Wrappers classes
java.math.BigInteger
java.math.BigDecimal
java.util.Date
java.util.Calendar
java.sql.Date
java.sql.Time
java.sql.TimeStamp
User-defined
serializable types
byte[]
Byte[]
char[]
Character[]
Slide 8
The Minimal Entity
• Must be annotated as an Entity
• Must have a persistent identifier (primary key)
• Example using annotations
@Entity
public class Employee
{
@Id
private int id;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
}
©SoftMoore Consulting
Slide 9
The Minimal Entity
(continued)
•
Example Entity entry in XML mapping file
</xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns=...>
<entity class="com.acme.Employee">
<attributes>
<id name="id"/>
</attributes>
</entity>
</entity-mappings>
©SoftMoore Consulting
Slide 10
Persistent Identity
• Identifier in entity, primary key in database
• Uniquely identifies entity in memory and in database
• Examples
– Simple id – single field/property
@Id int id;
– Compound id – multiple fields/properties
@Id int id;
@Id String name;
– Embedded id – single field of PK class type
@EmbeddedId EmployeePK id;
Uses
PK
class
Identifier Generation
•
Identifiers can be generated in the database by
specifying @GeneratedValue on the identifier
•
Three pre-defined generation strategies:
– IDENTITY
– SEQUENCE
– TABLE
•
Specifying strategy of AUTO indicates that the provider
will choose a strategy
@Id @GeneratedValue
int id;
Persistence Context
•
Abstraction representing a set of “managed” entity
instances
– Entities keyed by their persistent identity
– Only one entity with a given persistent identity may exist in the
persistence context
– Entities are added to the persistence context, but are not
individually removable (“detached”)
•
Controlled and managed by EntityManager
– Contents of persistent context change as a result of operations
on EntityManager API
Persistence Context
Persistence
Context
Application
EntityManager
MyEntity A
MyEntity C
MyEntity a
MyEntity B
MyEntity b
Entities
Entity
state
Entity Manager
•
Client-visible artifact for operating on entities
– API for all the basic persistence operations
•
Can think of it as a proxy to a persistence context
– May access multiple different persistence contexts throughout its
lifetime
•
Multi-dimensionality leads to different aspects of
EntityManager (and persistence context) naming
– Transaction type, life cycle
EntityManager Methods
•
•
•
•
persist() - insert the entity into the database
•
•
•
•
•
•
find() - execute a simple primary key query
remove() - delete the entity from the database
refresh() - reload the entity state from the database
merge() - synchronize state of detached entity with the persistence
context
createQuery() - create query instance using dynamic JPQL
createNamedQuery() - create instance for a predefined query
createNativeQuery() - create instance for an SQL query
contains() - true if entity is managed by persistence context
flush() - force synchronization of persistence context to database
Method persist()
• Insert a new entity instance into the database
• Save the persistent state of the entity and any owned
relationship references
• Entity instance becomes managed
• Example
public Customer createCustomer(int id, String name)
{
Customer cust = new Customer(id, name);
entityManager.persist(cust);
return cust;
}
Method find()
•
Obtains a managed entity instance with a given
persistent identity
– returns null if not found
•
Example
public void removeCustomer(Long custId)
{
Customer cust
= entityManager.find(Customer.class, custId);
entityManager.remove(cust);
}
Queries
• Dynamic or statically defined (named queries)
• Criteria using JPQL
• Native SQL support when required
• Named parameters bound at execution time
• Pagination and ability to restrict size of result
• Single/multiple-entity results
• Bulk update and delete operation on an entity
• Standard hooks for vendor-specific hints
Queries
•
Query instances are obtained from factory methods on
EntityManager
•
Query methods
–
–
–
–
–
getResultList() - execute query returning multiple results
getSingleResult() - execute query returning single result
executeUpdate() - execute bulk update or delete
setFirstResult() - set the first result to retrieve
setMaxResults() - set the maximum number of results to
retrieve
– setHint() - apply a vendor-specific hint to the query
– setFlushMode() - apply a flush mode to the query when it gets
run
Dynamic Queries
•
Use createQuery() factory method at runtime and pass
in the JPQL query string
•
Use correct execution method
– getResultList()
– getSingleResult()
– executeUpdate()
•
Query may be compiled/checked at creation time or
when executed
• Maximal flexibility for query definition and execution
Example: Dynamic Queries
public List findAll(String entityName)
{
return entityManager.createQuery(
"select e from " + entityName + " e")
.setMaxResults(100).getResultList();
}
Named Queries
•
Use createNamedQuery() factory method at runtime
and pass in the query name
•
Query must have already been statically defined either in
an annotation or XML
•
•
Query names are “globally” scoped
•
Can include parameters and hints in static query
definition
Provider has opportunity to precompile the queries and
return errors at deployment time
Example: Named Queries
@NamedQuery(name="Sale.findByCustId",
query="select s from Sale s
where s.customer.id = :custId
order by s.salesDate")
/**
* Returns all sales for a given customer
*/
public List findSalesByCustomer(Customer cust)
{
return
entityManager.createNamedQuery("Sale.findByCustId")
.setParameter("custId", cust.getId())
.getResultList();
}
Object/Relational Mapping
• Map persistent object state to relational database
• Map relationships to other entities
• Metadata may be annotations or XML (or both)
• Annotations
– Logical: object model (e.g. @OneToMany)
– Physical: database tables and columns (e.g. @Table)
• XML can additionally specify scoped settings or defaults
• Standard rules for default database table/column names
Object/Relational Mapping
(continued)
•
State or relationships may be loaded or “fetched” as
EAGER or LAZY
– LAZY - hint to defer loading until the field or property is accessed
– EAGER - requires that the field or relationship be loaded when
the referencing entity is loaded
• Cascading of entity operations to related entities
– Setting may be defined per relationship
– Configurable globally in mapping file for
persistence-by-reachability
Simple Mappings
• Direct mappings of fields/properties to columns
• Maps any of the common simple Java types
– primitives
– enumerated
– etc.
•
•
– wrappers
– serializable
Used in conjunction with @Column
Defaults to the type deemed most appropriate if no
mapping annotation is present
• Can override any of the defaults
Simple Mappings
@Entity
public class Customer
{
@Id
private int id;
private String name;
@Column(name="CREDIT")
private int creditRating;
@Lob
private Image photo;
}
CUSTOMER
ID
NAME
CREDIT
PHOTO
Relationship Mappings
•
Common relationship mappings supported
– @ManyToOne, @OneToOne (single entity)
– @OneToMany, @ManyToMany (collection of entities)
•
•
Unidirectional or bidirectional
•
Owning side specifies the physical mapping
Owning and inverse sides of every bidirectional
relationship
– @JoinColumn to specify foreign key column
– @JoinTable decouples physical relationship mappings from
entity tables
Many-to-One Mapping
@Entity
public class Sale
{
@Id
private int id;
SALE
ID
. . . CUST_ID
...
CUSTOMER
@ManyToOne
private Customer cust;
}
ID
...
OneToMany Mapping
@Entity
public class Customer
{
@Id private int id;
...
@OneToMany(mappedBy="cust")
private Set<Sale> sales;
}
@Entity
public class Sale
{
@Id private int id;
...
@ManyToOne
private Customer cust;
}
CUSTOMER
ID
...
SALE
ID
...
CUST_ID
Persistence in Java SE
•
No deployment phase
– Application must use a “Bootstrap API” to obtain an
EntityManagerFactory
•
Application uses a local EntityTransaction obtained
from the EntityManager
– begin()
– rollback()
•
–
–
commit()
isActive()
New application-managed persistence context for every
EntityManager
– No propagation of persistence contexts
Bootstrap Classes
•
javax.persistence.Persistence
– root class for bootstrapping an EntityManager
– used to obtain an EntityManagerFactory
•
javax.persistence.EntityManagerFactory
– creates EntityManager objects for a named persistence unit or
configuration
Example
public class PersistenceProgram
{
public static void main(String[] args)
{
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("SomePUnit");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// Perform finds, execute queries,
// update entities, etc.
em.getTransaction().commit();
em.close();
emf.close();
}
}
References
•
The Java EE Tutorial, Part VIII: Persistence.
https://docs.oracle.com/javaee/7/tutorial/index.html
•
Pro EJB 3: Java Persistence API by Mike Keith and
Merrick Schincariol, Apress, 2006,
ISBN: 978-1590596456.
©SoftMoore Consulting
Slide 35