You are on page 1of 71

Java Persistence API:

Simplifying Persistence

Doris Chen Ph.D.


Technology Evangelist
Sun Microsystems, Inc.

1
Agenda
• Java Persistence Requirements
• JPA Programming Model
• Persistence Context & Entity Manager
• Transaction
• O/R Mapping
• Entity Relationships
• Entity Inheritance Strategy
Java Persistence
Requirements
Java Persistence Requirements
• Simplification of the persistence model
> Elimination of deployment descriptor
> Most configuration is defaulted – configure by exception only
(configure only to override default)
• POJO based programming/persistence model
> Simple Java classes – not EJB components, only 1 file instead of 3
> Entities usable outside the container
> No need for Data Transfer Objects
> Facilitates testability outside of the containers
• Standardized object/relational mapping
> Standardized annotations @ and XML configuration files
> xml for mapping is optional
• Domain modelling through inheritance and polymorphism
• Extensive querying capabilities
Common Java Persistence Between
J2SE and J2EE Environments

• Persistence API expanded to include use outside of EJB


container
• Evolved into “common” Java persistence API
> You can use new Java persistence API in Java SE, Web, and
EJB applications
• Support for pluggable, third-party
persistence providers
> Through persistence.xml
What is an Entity?
What is an Entity?
• Plain Old Java Objects (not an EJB)
> Created by means of new keyword
• No required interfaces
• Has a persistence identity
• May have both persistent and non-persistent state
> Simple types (e.g., primitives, wrappers, enums)
> Composite dependent object types (e.g., Address)
> Non-persistent state (transient or @Transient)
• Can extend other entity and non-entity classes
• Serializable; usable as detached objects in other tiers
> No need for data transfer objects
Entity Example
Annotated as “Entity” @Id denotes primary key
@Entity
public class Customer implements Serializable {
@Id protected Long id;
protected String name;
@Embedded protected Address address;
protected PreferredStatus status;
@Transient protected int orderCount;

public Customer() {}

public Long getId() {return id;}


protected void setId(Long id) {this.id = id;}

public String getName() {return name;}


public void setName(String name) {this.name = name;}


}
Entity Identity
• Every entity has a persistence identity
> Maps to primary key in database
• Identity can be application or database generated
• Can correspond to simple type
> @Id—single field/property in entity class
> @GeneratedValue—value can be generated automatically
using various strategies (SEQUENCE, TABLE, IDENTITY,
AUTO)
• Can correspond to user-defined class
> @EmbeddedId—single field/property in entity class
> @IdClass—corresponds to multiple Id fields in entity class
• Must be defined on root of entity hierarchy
or mapped superclass
Types of Identity
• Simple
> @Id – single field/property in entity class
> @GeneratedValue
@Id @GeneratedValue(strategy=SEQUENCE)
private int id;
• User defined:
> @EmbeddedId – single field/property in entity class
@EmbeddedId Class must be
@Embeddable
private EmployeePK pk;
> @IdClass – corresponds to multiple id field in entity class
@Entity
@IdClass(EmployeePK.class)
public class Employee {
@Id private String empName;
@Id private int dept;
JPA
Programming Model
Java Persistence Programming Model
• Entity is a POJO (no need to implement EntityBean)
• Use of Annotation to denote a POJO as an entity (instead
of deployment descriptor)
// @Entity is an annotation
// It annotates Employee POJO class to be Entity
@Entity
public class Employee {
// Persistent/transient fields
// Property accessor methods
// Persistence logic methods
}
Persistence Entity Example
@Entity Annotated as “Entity”
public class Customer {
private Long id;
private String name;
private Address address;
private Collection<Order> orders = new HashSet();

public Customer() {}
@Id denotes primary key
@Id public Long getID() {
return id;
}

protected void setID (Long id) { Getters/setters to access


this.id = id; state
}

...
Persistence Entity Example (Contd.)
...

// Relationship between Customer and Orders


@OneToMany
public Collection<Order> getOrders() {
return orders;
}

public void setOrders(Collection<Order> orders) {


this.orders = orders;
}

// Other business methods


...
}
Client View: From Stateless Session Bean
@Stateless
public class OrderEntry {

// Dependency injection of Entity Manager for


// the given persistence unit
@PersistenceContext
EntityManager em;

public void enterOrder(int custID, Order newOrder){

// Use find method to locate customer entity


Customer c = em.find(Customer.class, custID);
// Add a new order to the Orders
c.getOrders().add(newOrder);
newOrder.setCustomer(c);
}

// other business methods


Client Code: From Java SE Client

public static void main(String[] args) {


EntityManagerFactory emf =
Persistence.createEntityManagerFactory("EmployeeService");
EntityManager em = emf.createEntityManager();

Collection emps = em.createQuery("SELECT e FROM Employee e")


.getResultList();

// More code
Demo
Creating Entities from Existing
Database tables
Persistence Context &
Entity Manager
Persistence – Key Concepts

Persistence

creates

PersistenceUnit EntityManager
Configured by Factory

creates

PersistenceContext EntityManager
Manages
Persistence Context
• Set of managed entities, belonging to a single
persistence unit
• “Entity instance is in managed state”means it is
contained in a persistent context
• Inclusion or exclusion of an entity into/from the
persistence context will determine the outcome of any
persistence operation on it
• Not directly accessible to application, it is accessed
indirectly through entity manager – type of entity
manager determines how a persistence context is
created and removed
EntityManager
• API to manage the entity instance lifecycle
• Allows your program to interact with underlying
persistence engine
• Similar in functionality to Hibernate Session,
JDO PersistenceManager, etc.
• Provides the following functionalities
> Lifecycle operations – persist(), remove(), refresh(), merge()
> Finder – find(), getReference()
> Factory for query objects – createNamedQuery(),
createQuery(), createNativeQuery()
> Managing persistence context – flush(), clear(), close(),
getTransaction(), ...
Entity Lifecycle State Diagram
> New entity instance is created
no longer associated with
> Entity is not yet managed or persistent persistence context

new()
New PC ends Detached
Updates
persist()
> Entity becomes managed Managed merge()
> Entity becomes persistent > State of detached entity is
in database on transaction merged back into
commit managed entity
remove()

> Entity is removed


Removed > Entity is deleted from
database on transaction
commit
Persist Operation

public Order createNewOrder(Customer customer) {


Order order = new Order(customer);

// Transitions new instances to managed. On the


// next flush or commit, the newly persisted
// instances will be inserted into the datastore.
entityManager.persist(order);

return order;
}
Find and Remove Operations

public void removeOrder(Long orderId) {


Order order =
entityManager.find(Order.class, orderId);

// The instances will be deleted from the datastore


// on the next flush or commit. Accessing a
// removed entity has undefined results.
entityManager.remove(order);
}
Merge Operation

public OrderLine updateOrderLine(OrderLine


orderLine) {

// The merge method returns a managed copy of


// the given detached entity. Changes made to the
// persistent state of the detached entity are
// applied to this managed instance.
return entityManager.merge(orderLine);
}
Transactions
Transaction Types
• Two different transaction types
> Resource-local transactions
> JTA (Java Transaction API)
> Multiple participating resources
> Distributed XA transactions
• Transaction type is defined in persistence unit
(persistence.xml file)
> Default to JTA in a JavaEE environment and to
RESOURCE_LOCAL in a JavaSE environment
• Container managed entity manager use JTA transactions
> Propagation of persistence context with a JTA transaction is
supported by the container – sharing same persistence context
among multiple entity managers
@TransactionAttribute Annotation
• TransactionAttributeType.REQUIRED
• TransactionAttributeType.REQUIRES_NEW
• TransactionAttributeType.MANDATORY
• TransactionAttributeType.NOT_SUPPORTED
• TransactionAttributeType.NEVER
• TransactionAttributeType.SUPPORTS
Transactions & Persistence Context
• Transactions define when new, modified, or removed
entities are synchronized with the database
• How persistence context is created and used is
determined by Transaction type (Resource-local or JTA)
and Transaction attribute (REQUIRED or ..)
Transaction & Persistence Context
Example
@Stateless
public class AuditServiceBean implements AuditService {
@PersistenceContext(unitName="EmployeeService")
private EntityManager em;

@TransactionAttribute(TransactionAttributeType.REQUIRED) //Default
public void logTransaction(int empId, String action) {
// verify employee number is valid
if (em.find(Employee.class, empId) == null) {
throw new IllegalArgumentException("Unknown employee id");
}
LogRecord lr = new LogRecord(empId, action);
em.persist(lr);
}

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void logTransaction2(int empId, String action) {
logTransaction(empId, action);
}
Transactions & Persistence Context
Example
@Stateless
public class EmployeeServiceBean implements EmployeeService {
@PersistenceContext(unitName="EmployeeService")
private EntityManager em;
@EJB
AuditService audit;

public void createEmployee(Employee emp) {


em.persist(emp);
audit.logTransaction(emp.getId(), "created employee");
}

public void createEmployee2(Employee emp) {


em.persist(emp);
audit.logTransaction2(emp.getId(), "created employee");
Detached Entities
Detached Entities
• Must implement Serializable interface if detached object
has to be sent across the wire
• No need for DTO (Data Transfer Object) anti-design
pattern
• Merge of detached objects can be cascaded
Transition to Detached Entities
• When a transaction is committed or rollback'ed
• When an entity is serialized
O/R Mapping
Object/Relational Mapping
• Comprehensive set of annotations defined for mapping
> Relationships
> Joins
> Database tables and columns
> Database sequence generators
> Much more
• Specified using
> Annotations within the code
> Separate mapping file
Object/Relational Mapping
● Logical and physical mapping views
● Logical—object model (e.g., @OneToMany)

● Physical—DB tables and columns (e.g., @Table)


Support for basic, serialized objects and LOBs
● Unary, n-ary relationship mappings

Rules for defaulting of DB table and
column names
● Access to object state using fields or properties
● Multiple tables, composite relationship keys

37
Simple Mappings

● Direct mappings of fields to columns


● @Basic—known field type maps to standard
DB column type
● @Lob—field typically maps to BLOB or CLOB
DB column type
● Used in conjunction with @Column
(physical mapping annotation)
● Defaults to the type deemed most appropriate
if no mapping annotation is present
● Can override any of the defaults

38
Simple Mappings
CUSTOMER
ID NAME C_RATING PHOTO

@Entity(access=FIELD)
public class Customer {
@Id
int id;

String name;

int c_rating;
@Lob
Image photo;
}

39
Simple Mappings CUSTOMER
ID NAME CREDIT PHOTO

@Entity(access=FIELD)
public class Customer {
@Id
int id;

String name;
@Column(name=“CREDIT”)
int c_rating;
@Lob
Image photo;
}

Mapping defaults to matching column name. Only configure if


entity field and table column names are different
40
Entity
Relationships
Entity Relationships
• Model instance association between entities
• Supports unidirectional as well as bidirectional
relationships
> Unidirectional relationship: Entity A references B, but B doesn't
reference A
• Mapping defaults are specified for all bi-directional as well
as uni-directional cardinalities
• Cardinalities
> One to one
> One to many
> Many to one
> Many to many
Relationship
owner
Mappings – ManyToMany
of Relationship
@Entity(access=FIELD) @Entity(access=FIELD) Inverse
public class Customer { public class Phone { of Relationship
@Id @Id
int id; int id;
... ...
@ManyToMany @ManyToMany(mappedBy=“phones”)
Collection<Phone> phones;
} Collection<Customer> custs;
}

CUSTOMER PHONE
ID ... ID ...
CUSTOMER_PHONE
ID CUSTS_ID PHONES_ID

Join table name is made up of the 2 entities. Field name


is the name of the entity plus the name of the PK field
Entity Relationships: Example
Many to many – Owning side
@Entity
public class Project {
private Collection<Employee> employees;
@ManyToMany
public Collection<Employee> getEmployees() {
return employees;
}

public void setEmployees(Collection<Employee>


employees) {
this.employees = employees;
}
...
}
Entity Relationships: Example
Many to many – Inverse side
@Entity
public class Employee {
private Collection<Project> projects;
@ManyToMany(mappedBy="employees")
public Collection<Project> getProjects() {
return projects;
}

public void setProjects(Collection<Project> projects) {


this.projects = projects;
}
...
}
Entity Relationships and Cascading Behavior
• Cascading is used to propagate the effect of an operation to
associated entities
• Cascading operations will work only when entities are
associated to the persistence context
> If a cascaded operation takes place on detached entity,
IllegalArgumentException is thrown
• Cascade=PERSIST
• Cascade=REMOVE
> Not advisable to use it on relationships other than one-to-one
and one-to-many relationships
• Cascade=MERGE Cascade=REFRESH
• Cascade=ALL
Entity Inheritance
Entity Inheritance
• Entities can now have inheritance relationship
> They are POJO's
• Three inheritance mapping strategies (mapping
entity inheritance to database tables)
> Single table – all classes stored in the same table
> Joined subclass – each class is stored in a separate
table
> Table per class – each concrete class is stored in a
separate table
• Use Java application @Inheritance(..) to specify
mapping
Object Model

Animal
id: int
name: String

LandAnimal AirAnimal

legCount: int wingSpan: int


Data Models
Single table:
all classes stored in the ANIMAL
same table ID DISC NAME LEG_CNT WING_SPAN

ANIMAL
ID NAME
Joined:
LAND_ANML AIR_ANML
each class is stored in
ID LEG_COUNT ID WING_SPAN
a separate table

LAND_ANML AIR_ANML
Table per Class:
ID NAME LEG_COUNT ID NAME WING_SPAN

each concrete class is


stored in a separate table
Entity Inheritance -Mapping Classes to Tables
• Use Java application metadata to specify mapping
Support for various inheritance mapping strategies
> SINGLE_TABLE [default]
> All the classes in a hierarchy are mapped to a single table
> Root table has a discriminator column whose value identifies the specific
subclass to which the instance represented by row belongs
> TABLE_PER_CLASS
> Each class in a hierarchy mapped to a separate table and hence, all properties
of the class (incl. inherited properties) are mapped to columns of this table
> JOINED
> The root of the hierarchy is represented by a single table
> Each subclass is represented by a separate table that contains fields specific to
the subclass as well as the columns that represent its primary key(s)
Single Table Strategy

• All the classes in a hierarchy are mapped to a single table


• Annotation to the parent Entity
> @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
• Root table has a discriminator column whose value identifies
the specific subclass to which the instance represented by row
belongs
> @DiscriminatorColumn(columnDefinition="MYDTYPE")
Single Table Strategy Example
// Parent Entity
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
//default is SINGE_TABLE

public class Person implements Serializable {...}


private String name;

// Child Entity
@Entity
public class Student extends Person {...}
private String school;
private double grade;

// Child Entity
@Entity
public class Teacher extends Person {...}
Single Table Strategy Example
Single Table Strategy Example
Joined Strategy

• The root of the hierarchy is represented by a single table


• Each subclass is represented by a separate table that contains
fields specific to the subclass as well as the columns that
represent its primary key(s)
• Annotation to the parent Entity
> @Inheritance(strategy=InheritanceType.JOINED)
Joined Table Strategy Example
// Parent Entity
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(columnDefinition="MYDTYPE")
public class Person implements Serializable {...}
private String name;

// Child Entity
@Entity
public class Student extends Person {...}
private String school;
private double grade;

// Child Entity
@Entity
public class Teacher extends Person {...}
Demo
Use different strategies for
inheritance and how database
tables are created

- SINGLE_TABLE
- JOINED
Entity Inheritance Strategy
• SINGLE_TABLE [default]
> All the classes in a hierarchy are mapped to a single table
> This strategy provides good support polymorphic relationships between
entities and queries that cover the entire class hierarchy
> May contain null fields for some subclass data
• TABLE_PER_CLASS
> Each class in a hierarchy mapped to a separate table and hence,
provides poor support for polymorphic relationships
> requires SQ union or separate SQL queries for each subclass
• JOINED
> no null fields => compact data
> This provides good support for polymorphic relationships, but requires
one or more join operations – may result in poor performance
Embedded Objects
Embedded Objects

• @Embeddable used to mark an embeddable object


• Embeddable object is stored as intrinsic part of an owning
entity
> Doesn't have its own identity
• Each persistent field/property of embeddable object is
mapped to the same database table that represents the
Embedded Objects

@Entity
public class Customer
{
@Id CUSTOMER
int id; ID NAME CREDIT PHOTO
@Embedded
CustomerInfo info;
}

@Embeddable
public class CustomerInfo {
String name;
int credit;
@Lob
Image photo;
}
Entity Listeners
Entity Listeners
• Listeners or callback methods are designated to receive
invocations from persistence provider at various stages of
entity lifecycle
• Callback methods
> Annotate callback handling methods right in the entity class or
put them in a separate listener class
> Annotations
> PrePersist / PostPersist
> PreRemove/ PostRemove
> PreUpdate / PostUpdate
> PostLoad
Entity Listeners: Example – 1
@Entity
@EntityListener(com.acme.AlertMonitor.class)
public class AccountBean implements Account {
Long accountId;
Integer balance;
boolean preferred;
public Long getAccountId() { ... }
public Integer getBalance() { ... }

@Transient context
public boolean isPreferred() { ... }

public void deposit(Integer amount) { ... }


public Integer withdraw(Integer amount) throws NSFException {... }
Entity Listeners: Example – 2

@PrePersist
public void validateCreate() {
if (getBalance() < MIN_REQUIRED_BALANCE)
throw new AccountException("Insufficient balance to
open an account");
}

@PostLoad
public void adjustPreferredStatus() {
preferred =(getBalance() >=
AccountManager.getPreferredStatusLevel());
}
}
Entity Listeners: Example – 3

public class AlertMonitor {

@PostPersist
public void newAccountAlert(Account acct) {
Alerts.sendMarketingInfo(acct.getAccountId(),
acct.getBalance());
}
}
Summary,
Resources,
Sun Developer Network
Java Persistence Summary
• Simplifies persistence model
• Supports Light-weight persistence model
• Support both Java SE and Java EE environments
• O/R mapping through annotation
• Extensive querying capabilities
Resources
http://developers.sun.com/events/techdays/presentations/

• Glassfish persistence homepage


> https://glassfish.dev.java.net/javaee5/persistence
• Persistence support page
> https://glassfish.dev.java.net/javaee5/persistence/entity-
persistence-support.html
• Blog on using persistence in Web applications
> http://weblogs.java.net/blog/ss141213/archive/2005/12/using_ja
va_pers.html
• Blog on schema generation
> http://blogs.sun.com/roller/page/java2dbInGlassFish#automatic
_table_generation_feature_in
Java Persistence API:
Simplifying Persistence

Doris Chen Ph.D.


Technology Evangelist
Sun Microsystems, Inc.

71

You might also like