National Academy for Software Development

Download Report

Transcript National Academy for Software Development

Java Persistence API
Mario Peshev
National Academy for
Software Development
academy.devbg.org
Svetlin Nakov
National Academy for
Software Development
academy.devbg.org
Contents
1. About JPA
2. Entities
3. Queries
4. Mappings
5. Persistence
About JPA
Introduction
About JPA
• What is Java Persistence API (JPA)?
• Database persistence technology for Java
• Object-relational mapping (ORM) engine
• Operates with POJO entities
• Similar to Hibernate and JDO
• JPA maps Java classes to database tables
• Maps relationships between tables as
associations between classes
• Provides CRUD functionality
• Create, read, update, delete
History of JPA
• History of JPA
• Created as part of EJB 3.0 within JSR 220
• Released May 2006 as part of Java EE 5
• Can be used as standalone library
• Standard API with many implementations
• OpenJPA – http://openjpa.apache.org/
• Hibernate – http://www.hibernate.org
• TopLink JPA –
http://www.oracle.com/technology/jpa
• JPOX – http://www.jpox.org/
JPA Reference
Implementation
• Part of “Glassfish” project on java.net
• Glassfish is RI for the entire Java EE platform
• Sun and Oracle partnership
• Sun Application Server + Oracle persistence
• JPA open-source implementation
called “TopLink Essentials”
• Donated by Oracle, derived from Oracle
TopLink
• All open source (under CDDL license)
• Anyone can download/use source code or
binary code in development or production
Entities
Defining Simple Entity Classes
Anatomy of an Entity
• Just a POJO class
• Abstract or concrete top level Java class
• Non-final fields/properties, no-arguments
constructor
• No required interfaces
• No requirement for business or callback
interfaces
• Direct field or property-based access
• Getter/setter can contain logic (e.g.
validation)
The Minimal Entity
• Must be indicated as an Entity
• @Entity annotation on the class:
@Entity
public class Employee { … }
• Entity entry in XML mapping file
<entity class="com.acme.Employee"/>
The Minimal Entity
• Must have a persistent identifier
(primary key):
@Entity
public class Employee {
@Id int id;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
}
Persistent Identity (Id)
• Identifier (id) in entity, primary key in
database
• Uniquely identifies entity in memory
and in db
• Different ID definitions
• Simple id
• Compound id
• Embedded id
Id Definitions
• Simple id – single field/property
@Id int id;
• Compound id – multiple fields
@Id int id;
@Id String name;
• Embedded id – single field of PK class
type
@EmbeddedId EmployeePK id;
Identifier Generation
• Identifiers can be generated in the database
• @GeneratedValue on the ID
@Id @GeneratedValue
int id;
• 3 pre-defined generation strategies:
• IDENTITY, SEQUENCE, TABLE
• May pre-exist or be generated
• AUTO strategy indicates that the provider will
choose a strategy
Using Identity or Sequence
• Using identity (auto increment column in
the database) for Id generation:
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
• Using database sequence for Id generation:
@Id
@GeneratedValue(generator="UsersSeq")
@SequenceGenerator(name="UsersSeq",
sequenceName="USERS_SEQ")
private long id;
Simple Column Mappings
• Mapping a property to a database
column:
@Entity
public class Message {
private String message;
public void setMessage(String msg) { message = msg; }
public String getMessage() { return message; }
}
• A column name can be explicitly given:
@Column(name="SAL")
private double salary;
Persistent Contexts
and EntityManager
Manipulating Database Entities
Persistence Context (PC)
• A set of “managed” entity instances
• Keyed by persistent identity
• Only one entity with a given persistent ID
may exist in the PC
• Added to the PC, but not individually
removable (“detached”)
• Managed by EntityManager
• Contents of PC change as a result of
operations on EntityManager API
Persistence Context (PC)
Persistence
Context
Application
EntityManager
MyEntity A
MyEntity C
MyEntity a
MyEntity B
MyEntity b
Entities
Entity
state
Entities Lifecycle
Entity Manager
• Client-visible object for operating on
entities
• API for all the basic persistence
operations (CRUD)
• Manages connection and transaction
• Can think of it as a proxy to a
persistence context
Operations on Entities
• EntityManager API
• persist() – persists given entity object into
the database (SQL INSERT)
• remove() – deletes given entity object into
the database (SQL DELETE by PK)
• refresh() – reloads given entity object from
the database (SQL SELECT by PK)
• merge() – synchronize the state of detached
entity with the PC
• find() – execute a simple query by PK
Operations on Entities (2)
• createQuery() – creates a query instance
using dynamic JPQL
• createNamedQuery() – creates an instance
for a predefined JPQL query
• createNativeQuery() – creates an instance
for an SQL query
• contains() – determine if given entity is
managed by the PC
• flush() – forces changes in the PC to be
saved in the database (automatically called
on transaction commit)
persist()
• Insert a new entity instance into the
database (SQL INSERT / UPDATE)
• Save the persistent state of the entity
and any owned relationship references
• Entity instance becomes managed
public Customer createCustomer(int id, String
name) {
Customer cust = new Customer(id, name);
entityManager.persist(cust);
return cust;
}
find() and remove()
• find()
• Obtain a managed entity instance (SQL
SELECT by PK)
• Return null if not found
• remove()
• Delete a managed entity by PK
public void removeCustomer(Long custId) {
Customer cust = entityManager.
find(Customer.class, custId);
entityManager.remove(cust);
}
merge()
• Merges the state of detached entity into
a managed copy of the detached entity
• Returned entity has a different Java
identity than the detached entity
public Customer storeUpdatedCustomer(Customer
cust) {
return entityManager.merge(cust);
}
• May invoke SQL SELECT
Queries
Using JPQL
Queries
• Dynamic or statically defined (named
queries)
• Criteria using JPQL (Java Persistence
API Query Language, a kind of SQL)
• Native SQL support (when required)
• Named parameters bound at execution
time (no SQL injection)
Queries (2)
• Pagination and ability to restrict size of
result
• Single/multiple-entity results, data
projections
• Bulk update and delete operation on an
entity
• Standard hooks for vendor-specific
hints
Query API
• Query instances are obtained from factory
methods on EntityManager, e.g.
Query query = entityManager.createQuery(
"SELECT e from Employee e");
• Query API:
• getResultList() – execute query returning
multiple results
• getSingleResult() – execute query returning
single result
• executeUpdate() – execute bulk update or
delete
Query API (2)
• setFirstResult() – set the first result to
retrieve
• setMaxResults() – set the maximum number
of results to retrieve
• setParameter() – bind a value to a named or
positional parameter
• 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
Dynamic Queries – Example
• Return all instances of the given entity type
public List findAll(String entityName){
return entityManager.createQuery(
"select e from " + entityName + " e")
.setMaxResults(100)
.getResultList();
}
• JPQL string composed from entity type
• For example, if “Account” was passed in
then JPQL string would be: “select a from
Account a”
Named Queries
• Use createNamedQuery() factory
method at runtime and pass in the
query name
• Query must be statically defined
• Query names are “globally” scoped
• Provider can to precompile the queries
and return errors at deployment time
• Can include parameters and hints in
static query definition
Named Queries – Example
@NamedQuery(name="Sale.findByCustId",
query="select s from Sale s
where s.customer.id = :custId
order by s.salesDate")
public List findSalesByCustomer(Customer cust) {
return (List<Customer>)entityManager.
createNamedQuery("Sale.findByCustId")
.setParameter("custId", cust.getId())
.getResultList();
}
ORM Mappings
Annotations or XML
Object/Relational Mapping
• Map persistent object state to relational
database
• Map relationships to other entities
• Metadata may be annotations or XML (or
both)
Annotations / XML
Annotations
• Logical—object model (e.g.
@OneToMany)
• Physical—DB tables and columns (e.g.
@Table)
• XML
• Can specify scoped settings or defaults
• Standard rules for default db
table/column names
Fetching and Cascading
• State may be “fetched” as EAGER or LAZY
• LAZY – container defers 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 to columns
• @Basic – optional, indicates simple
mapped attribute
• Can specify fetch=EAGER / LAZY
• Maps any of the common simple Java
types
• Primitives, wrappers, serializable, etc.
• Used in conjunction with @Column
• Can override any of the defaults
Simple Mappings
@Entity
public class Customer {
@Id
int id;
String name;
@Column(name=“CREDIT”)
int c_rating;
@Lob
Image photo;
}
CUSTOMER
ID
NAME
CREDIT
PHOTO
Simple Mappings
<entity class="example.Customer">
<attributes>
<id name="id"/>
<basic name="c_rating">
<column name="CREDIT"/>
</basic>
<basic name="photo"><lob/></basic>
</attributes>
</entity>
Relationship Mappings
• Common relationship mappings supported
• @ManyToOne, @OneToOne – single entity
• @OneToMany, @ManyToMany – collection
• Unidirectional or bidirectional
• Owning and inverse sides
• Owning side specifies the physical mapping
• @JoinColumn to specify foreign key column
• @JoinTable decouples physical relationship
mappings from entity tables
ManyToOne Mapping
@Entity
public class Sale {
@Id
int id;
...
@ManyToOne
Customer cust;
}
}
SALE
ID
. . . CUST_ID
CUSTOMER
ID
...
ManyToOne Mapping
<entity class="example.Sale">
<attributes>
<id name="id" />
...
<many-to-one name="cust" />
</attributes>
</entity>
OneToMany Mapping
@Entity
public class Customer {
@Id
int id;
...
@OneToMany(mappedBy=“cust”)
Set<Sale> sales;
}
@Entity
public class Sale {
@Id
int id;
...
@ManyToOne
Customer cust;
}
CUSTOMER
ID
...
SALE
ID
...
CUST_ID
OneToMany Mapping
<entity class="example.Customer">
<attributes>
<id name="id" />
...
<one-to-many name="sales" mappedby="cust"/>
</attributes>
</entity>
Using Persistence API
Creating JPA Applications
Persistence in Java SE
• No deployment phase
• Application must use a “Bootstrap API”
to obtain an EntityManagerFactory
• Resource-local EntityManagers
• Application uses a local
EntityTransaction obtained from the
EntityManager
Entity Transactions
• Only used by resource-local
EntityManagers
• Transaction demarcation under explicit
application control using
EntityTransaction API
• begin(), commit(), rollback(), isActive()
• Underlying (JDBC) resources allocated by
EntityManager as required
Persistence Class
• javax.persistence.Persistence
• Root class for bootstrapping an
EntityManager
• Locates provider service for a named
persistence unit
• Invokes on the provider to obtain an
EntityManagerFactory
EntityManagerFactory Class
• javax.persistence.EntityManagerFactory
• Obtained by the Persistance
• Creates EntityManager for a named
persistence unit or configuration
• In Java SE environment the persistence
unit configuration is defined in the
META-INF/persistence.xml file
Sample Configuration (METAINF/persistence.xml)
<?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"
version="1.0">
<persistence-unit name="hellojpa">
<class>hellojpa.Message</class>
<properties>
<property name="openjpa.ConnectionURL"
value="jdbc:derby:openjpa-database;create=true"/>
<property name="openjpa.ConnectionDriverName"
value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="openjpa.ConnectionUserName" value=""/>
<property name="openjpa.ConnectionPassword" value=""/>
</properties>
</persistence-unit>
</persistence>
OpenJPA Enhancer
• OpenJPA uses class files enhancer
• Enhancements are critical for the normal
work of the OpenJPA!
• Provide optimal runtime performance,
flexible lazy loading, and efficient,
immediate dirty tracking
• Enhancement can be done at build time,
during the deployment or at runtime
• To switch on runtime class enhancement
use the following VM parameters:
-javaagent:lib/openjpa-1.0.2.jar
JPA Bootstrap – Example
public class PersistenceExample {
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();
}
}
Java Persistence API
Live Demo
IDE Support
• Eclipse “Dali” project
(http://www.eclipse.org/dali)
• JPA support
• NetBeans
(http://community.java.net/netbeans)
• EJB 3.0 support including JPA (Beta 2)
• JDeveloper (http://otn.oracle.com/jdev)
• EJB 3.0 support including JPA (10.1.3.1)
Summary
• JPA emerged from best practices of existing
best of breed ORM products
• Lightweight persistent POJOs, no extra
baggage
• Simple, compact and powerful API
• Standardized object-relational mapping
metadata specified using annotations or XML
• Feature-rich query language
• Java EE integration, additional API for Java SE
Java Persistence API
Questions?
Exercises
1. Define an entity class Student which has Id,
FirstName and LastName.
2. Define an entity class Course which has Id,
name and list of students.
3. Create a database matching the entity
classes. Use Apache Derby and its built-in
identity columns support.
4. Create a program that lists all classes and the
students in each class.
5. Create a program that adds a new class and
few students inside it.
Exercises