You are on page 1of 56

Introduction to Java Persistence API 2.

0
JPA 2.0| 14-June-2012
Topics
Introduction to JPA 2.0 Entity Manager API
JPA Interfaces. Relationship mapping.
JPA configuration. o One to One
Sample configuration Java SE/EE o Many to One
Spring Integration o One to Many
Anatomy of Entity. o Many to Many
Minimal Entity. Inheritance Mapping.
Persistent Identity generation techniques. JPQL
o AUTO id generation Criteria API
o Table id generation JPA Exceptions
o Sequence id generation References.
Entity Lifecycle.
Persistent context.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 2


Introduction| About JPA 2.0
Persistence API for operating on POJO entities
Merger of expertise from TopLink, Hibernate, JDO, EJB vendors and individuals.
Created as part of EJB 3.0 within JSR 317
Released Dec 2010 as part of Java EE 6
Bootstrap API can also be used in Java SE (No need of application server)
Pluggable Container-Provider SPI

Popular implementations of JPA are:


o Hibernate
o EclipseLink
o OpenJPA

The Java Persistence API provides Java developers with an object/relational mapping facility for
managing relational data in Java applications. Java Persistence consists of four areas:
o The Java Persistence API
o The query language
o The Java Persistence Criteria API
o Object/relational mapping metadata

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 3


JPA Interfaces
EntityManagerFactory
o The EntityManagerFactory represents the configuration for a database in your application. We would
typically define one EntityManagerFactory per datastore.
o The EntityManagerFactory is used to create multiple EntityManager instances.

EntityManager
o EntityManager instance is analogous to a database connection.
o In a multithreaded web application, each thread will have its own EntityManager

EntityTransaction
o Each EntityManager has a single EntityTransaction, which is required for persisting changes to the underlying
database.
Query
o EntityManager serves as a factory for generating Query classes.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 4


JPA Configuration
JPA requires you to create a META-INF/persistence.xml file.

In persistence.xml, we can we can optionally configure which classes we want to include for a
given persistence unit. This is mostly useful in multi datastore applications.

Persistence Provider

o The Java Persistence API has a pluggable Service Provider Interface (SPI) that allows any compliant Java EE
server to communicate with any compliant persistence provider implementation.

o The provider class should implement the javax.persistence.spi.PersistenceProvider interface must be listed
in the provider element.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 5


Sample Configuration | Java SE/EE
<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_2_0.xsd"
version="2.0">

<persistence-unit name=jpaDemo" transaction-type="RESOURCE_LOCAL"/>


<class> com.sapient.domain.Person </class>

<provider>org.hibernate.ejb.HibernatePersistence</provider>
<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>

Refer http://docs.oracle.com/cd/B32110_01/web.1013/b28221/cfgdepds005.htm

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 6


Spring Integration
Here are the ways for Spring integration:

LocalEntityManagerFactoryBean uses JPA's Java SE bootstrapping.

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property
name="persistenceUnitName" value=jpaDemo"/> </bean>

LocalContainerEntityManagerFactoryBean
for annotation
o Configure a datasource and JPA vendor-specific adapters. scanning.
o Define datasource bean.
o Create the LocalContainerEntityManagerFactoryBean

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-
ref="dataSource"/>
</context:component-scan>
o Define Transaction manager

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"


p:entityManagerFactory-ref="entityManagerFactory"/> <tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager"/>

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 7


Exercise
Configure JPA using spring integration technique.
Configure JPA without using persistence.xml file.
Take a look at Hibernate configuration properties and the provider class.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 8


Anatomy of an Entity
An entity is a lightweight persistent domain object (POJO).

An entity represents a table in a relational database, and each entity instance corresponds to a
row in that table.

The entity class must be annotated with the Entity annotation.

The entity class must have a no-arg constructor. The no-arg constructor must be public or
protected.

The entity class must be a top-level class. An enum or interface must not be designated as an
entity.

The entity class must not be final. No methods or persistent instance variables of the entity class
may be final.

The persistent state of an entity is represented by instance variables (transient variables will not
be the part of persistent state)

Entities support inheritance, polymorphic associations, and polymorphic queries.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 9


Minimal Entity Primary
key
Must be indicated as an Entity

o @Entity annotation on the class

Must have a persistent identifier (primary key)


o Primary key can be a compound key as well.

@Entity
public class Employee {
@Id
private int id;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
..
..

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 10


Exercise
Implement a test case to persist a minimal entity.
Implement a test case to retrieve object from datastore using primary key.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 11


Persistent Identity | Auto identity generation
Identifier (id) in entity, primary key in database.

Uniquely identifies entity in memory and in db

o Simple id single field/property


@Id int id;
o Compound id multiple fields/properties
@Id int id;
@Id String name;
o Embedded id single field of PK class type
@EmbeddedId EmployeePK id;

Identifiers can be generated in the database by specifying @GeneratedValue on the identifier

4 pre-defined generation strategies:


o AUTO, IDENTITY, SEQUENCE and TABLE @Id
@GeneratedValue(strategy=AUTO)
private int id;
Specifying strategy of AUTO indicates that the provider will choose a strategy.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 12


Persistent Identity | Id generation using table
Most flexible and portable way to generate identifiers is to use a database table
An id generation table should have two columns. The first column is a string type used to identify
the particular generator sequence. It is the primary key for all the generators in the table. The
second column is an integer type that stores the actual id sequence that is being generated.

Easiest way to use table generator


@Id
@GeneratedValue(strategy=GenerationType.TABLE)
private int id;
Fully configured table generator

@TableGenerator(name="Emp_Gen", table="ID_GEN",
pkColumnName="GEN_NAME",
valueColumnName="GEN_VALinitialValue=0,allocationSize=100))
@Id
@GeneratedValue(generator="Emp_Gen")
private int id;

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 13


Persistent Identity | Id generation using database sequence
A database sequence can be used to generate identifiers when the underlying database supports
them.

Minimal configuration
o we are not concerned that it be any particular sequence.
o In this case, no generator is named, so the provider will use a default sequence object of its own choosing.
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
private int id;

Fully configured sequence generator

@SequenceGenerator(name="Emp_Gen", sequenceName="Emp_Seq")
@Id
@GeneratedValue(generator="Emp_Gen")
private int id;

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 14


Exercise
Implement auto Id generation
Implement table id generation.
Implement sequence id generation.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 15


Entity Lifecycle
New entity is instantiated but not associated with persistence context. Not linked to database.
Managed associated with persistence context. Changes get synchronized with database
Detached has an id, but not connected to database
Removed associated with persistence context, but underlying row will be deleted.

The state of persistent entities is synchronized to the database when the transaction commits

new new()
refresh() persist()

managed
remove()
persist()
removed

merge() End of context

detached

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 16


Persistent Context
A persistence context is a set of managed entity instances that exist in a particular data store
o Entities keyed by their persistent identity
o Only one entity with a given persistent identity may exist in the persistence context
o Entities are added to the persistence context, but are not individually removable (detached)

Every persistence context is associated with a persistence unit.

If the persistence context participates in a transaction, the in-memory state of the managed
entities will get synchronized to the database.

Entities are managed by the entity manager.

An entity instance is managed means that it is contained within a persistence context.

An entity manager manages a persistence context and a persistence context is a managed set of
entity instances.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 17


Persistence Context

Persistence
Application Context (L2 cache)

Entity Manager
Entity A

Entity C
Entity a Entity B
Entity b

Entities

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 18


Entity Manager | API
persist()
o Insert a new entity instance into the database
o Save the persistent state of the entity and any owned relationship references
o Entity instance becomes managed
remove()
o Delete a managed entity with the given persistent identity from the database
refresh()-
o Reload the entity state from the db
merge()
o State of detached entity gets merged into a managed copy of the detached entity
find()
o Obtain a managed entity instance with a given persistent identity return null if not found
createQuery()
o Create query instance using dynamic JP QL
createNamedQuery()
o Create instance for a predefined query
createNativeQuery()
o Create instance for an SQL query
contains()
o Determine if entity is managed by pc
flush()
o Force synchronization of pc to database

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 19


Relationship Mapping

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 20


Relationship Mapping
Relationships among entities may be
o one-to-one
o one-to-many
o many-to-one
o many-to-many.

If there is an association between two entities, one of the following relationship modeling
annotations must be applied to the corresponding persistent property or field of the referencing
entity: @OneToOne, @OneToMany, @ManyToOne, @ManyToMany.

For one-to-one relationship, the owning side corresponds to the side that contains the
corresponding foreign key.

Relationships may be bidirectional or unidirectional. A bidirectional relationship has both an


owning side and an inverse (non-owning) side. A unidirectional relationship has only an owning
side. The owning side of a relationship determines the updates to the relationship in the database.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 21


Relationship Mapping 2

JPA supports cascading updates/deletes


CascadeType
o ALL, PERSIST, MERGE, REMOVE, REFRESH

We can declare performance strategy to use with fetching related rows FetchType
o LAZY, EAGER (Lazy means don't load row until the property is retrieved)

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 22


Relationship Mapping | One To One
Assumptions:
Entity A references a single instance of Entity B.
Entity B references a single instance of Entity A.
Entity A is specified as the owner of the relationship. Example:
@Entity
public class Person{
Entity A is mapped to a table named A. private PersonDetail
Entity B is mapped to a table named B. personDetail;
Table A contains a foreign key to table B.
@OneToOne(cascade=CascadeType.AL
L, fetch=FetchType.EAGER)
@Entity //default
public class PersonDetail{ @JoinColumn(name="pdetail_fk")

private Person person; public PersonDetail


@OneToOne(mappedBy="personDetail") getPersonDetail() {
public Person getPerson() { return personDetail;
return person; }...
}... }
}

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 23


Exercise
Implement One to One mapping among person and person details class
Use bi-directional relationship

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 24


Relationship Mapping | Many To One

@Entity
public class Student { Student
@Id
studentId College_id
int studentId;
...
@ManyToOne College
@JoinColumn ID ...
(name=College_id)

College college;
}
}
Many side will own the relationship so join column annotation will be put on many side.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 25


Relationship Mapping | One To Many
For bi-directional relationship use mappedBy attribute.

@Entity
public class College { College
@Id ID ...
int id;
@OneToMany(mappedBy=college)
...
Set<Student> students;
}
@Entity Student
public class Students { ID ... College_id
@Id
int id;
...
@ManyToOne
College college;
}

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 26


Exercise
Implement One to Many mapping among student and college class
Use bi-directional relationship

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 27


Relationship Mapping | Many to Many
@Entity
public class Event {
...
@ManyToMany
@JoinTable(name=JOIN_DELEGATE_EVENT",
joinColumns=@JoinColumn(name="event_id")},
inverseJoinColumns=@JoinColumn(name="delegate_id)})
List<Delegate> delegates;

@Entity
public class Delegate {
...
@ManyToMany
@JoinTable(name="JOIN_DELEGATE_EVENT",
joinColumns={@JoinColumn(name="delegate_id")},
inverseJoinColumns={@JoinColumn(name="event_id")})

List<Event> events;

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 28


Relationship Mapping | Many to Many
EVENT_ID EVENT_NAME DELEGATE_ID DELEGATE_NAME

EVENT DELEGATE

EVENT_ID DELEGATE_ID

JOIN_DELEGATE_EVENT

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 29


Exercise
Implement Many to Many mapping among Event and Delegate class.
An event can be attended by multiple delegates.
A delegate can attend multiple events.
Use bi-directional relationship

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 30


Relationship Mapping | Inheritance mapping
An important capability of the JPA is its support for inheritance and polymorphism

Entities can inherit from other entities and from non-entities

The @Inheritance annotation identifies a mapping strategy:

o SINGLE_TABLE
o JOINED
o TABLE_PER_CLASS

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 31


Inheritance Mapping | Single table
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DISC",
discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue(value=Project")
public class Project { . . . }

@Entity
@DiscriminatorValue(name=Module")
public class Module extends Project { . . . }

SINGLE_TABLE strategy - all classes in the hierarchy are mapped to a single table in
the database
Discriminator column - contains a value that identifies the subclass
Discriminator type - {STRING, CHAR, INTEGER}
Discriminator value - value entered into the discriminator column for each entity in
a class hierarchy

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 32


Inheritance mapping | Table per class

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Project { . . . }
@Entity
public class Module extends Project { . . . }

@Entity
public class Task extends Module { . . . }

One cannot use AUTO for primary key generation strategy with conjunction with table per
concrete class" inheritance, because in such a case the identity column must be present in each
table and its values must be mutually exclusive.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 33


Inheritance mapping | Join Table
Joined inheritance is the most logical inheritance solution because it mirrors the object model in
the data model.

In joined inheritance a table is defined for each class in the inheritance hierarchy to store only the
local attributes of that class. Each table in the hierarchy must also store the object's id (primary
key), which is only defined in the root class.

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Project { . . . }
@Entity
public class Module extends Project { . . . }

@Entity
public class Task extends Module { . . . }

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 34


Inheritance Mapping | Summary
SINGLE_TABLE

Advantage:
o Single table inheritance mapping is the fastest of all inheritance models, since it never requires a join to
retrieve a persistent instance from the database.
Disadvantage:
o The larger the inheritance model gets, the "wider" the mapped table gets, in that for every field in the entire
inheritance hierarchy, a column must exist in the mapped table. This may have undesirable consequence on
the database size, since a wide or deep inheritance hierarchy will result in tables with many mostly-empty
columns.

JOINED

Advantage:
o Using joined subclass tables results in the most normalized database schema, meaning the schema with the
least spurious or redundant data.
Disadvantage:
o The joined strategy is often the slowest of the inheritance models.

TABLE_PER_CLASS

Advantage :
o The table-per-class strategy is very efficient when operating on instances of a known class(no joins).

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 35


Exercise
Implement the below classes hierarchy using all the inheritance techniques we studied.

Project

Module

Task

Use bi-directional relationship

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 36


JPA 2.0 | Queries
Queries and Criteria API

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 37


Queries using JPQL | Introduction
Allows writing of queries that are portable across data stores (databases).

The Java Persistence Query Language (JPQL) is a platform-independent object-oriented query


language defined as part of the Java Persistence API specification.

It is heavily inspired by SQL, and its queries resemble SQL queries in syntax, but operate against
JPA entity objects rather than directly with database tables.

In addition to retrieving objects (SELECT queries), JPQL supports bulk UPDATE and DELETE queries

The main difference between JPQL and SQL lies in that the former deals with JPA entities, while
the latter deals directly with relational data.

JPQL eliminates the need for you to use JDBC API from your Java codethe container does all this
work for you behind the scenes.

JPQL lets you define queries using one of the following three statements: SELECT, UPDATE, or
DELETE.

Standard hooks for vendor-specific hints

Query instances are obtained from factory methods on EntityManager

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 38


Queries | Introduction

Query API:

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
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
o Two modes of flushing query objects
o AUTO (default) and COMMIT

o AUTO - any changes made to entity objects will be reflected the very next time when a SELECT query is made

o COMMIT - the persistence engine may only update all the state of the entities during the database COMMIT

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 39


Dynamic Queries
Use createQuery() factory method at runtime and pass in the JP QL 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

public List findAll(String entityName){


return entityManager.createQuery(
"select e from " + entityName + " e")
.setMaxResults(100)
.getResultList();
}

Return all instances of the given entity type


JP QL string composed from entity type. For example, if Account was passed in then JP QL string
would be: select e from Account e

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 40


Positional Parameters
Positional parameters are prefixed with a question mark (?) & number of the parameter in the
query
To set parameter values use method:
o Query.setParameter(integer position, Object value)

public List findWithName(String name) {


return em.createQuery(
SELECT c FROM Customer c WHERE c.name LIKE ?1)
.setParameter(1, name)
.getResultList();
}

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 41


Named Parameters
Named parameters are parameters in a query that are prefixed with a colon (:)
To bound parameter to an argument use method:
o Query.setParameter(String name, Object value)

public List findWithName(String name) {


return em.createQuery(
"SELECT c FROM Customer c WHERE c.name LIKE :custName")
.setParameter("custName", name)
.getResultList();
}

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 42


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
Provider has opportunity to precompile the queries and return errors at deployment time
Can include parameters and hints in static query definition

@NamedQuery(name="Sale.findByCustId",
@NamedQuery(name="Sale.findByCustId",
query="select
query="select s fromsSale
froms Sale s
wherewhere s.customer.id
s.customer.id = :custId= :custId
order order
by s.salesDate")
by s.salesDate")

publicpublic
List findSalesByCustomer(Customer
List findSalesByCustomer(Customercust) { cust) {
returnreturn
entityManager.createNamedQuery(
entityManager.createNamedQuery(
"Sale.findByCustId")
"Sale.findByCustId")
.setParameter("custId",
.setParameter("custId", cust.getId())
cust.getId())
.getResultList();
.getResultList();
} }
Return all sales for a given customer

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 43


Native Queries
Queries may be expressed in native SQL
Use when you need to use native SQL of the target database
Can call stored procedures using "call procname" syntax

Query q = em.createNativeQuery(
"SELECT o.id, o.quantity, o.item " +
"FROM Order o, Item i " +
"WHERE (o.item = i.id) AND (i.name = 'widget')",
com.acme.Order.class);

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 44


Query Operations Single Result
A query that returns a single entity object

If the match wasnt successful, then EntityNotFoundException is returned

If more than one matches occur during query execution a run-time exception
NonUniqueResultException will be thrown

Query singleSelectQuery = entityManager.createQuery(


SELECT C FROM CUSTOMER WHERE C.ID = ABC-123);
Customer custObj = singleSelectQuery.getSingleResult();

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 45


Criteria API | Introduction
Dynamic, typesafe queries in JPA 2.0.
o A query for persistent Java objects is typesafe if a compiler can verify it for syntactic correctness.
o Java Persistence API (JPA 2.0) introduces the Criteria API, which brings the power of typesafe queries to Java
applications for the first time and provides a mechanism for constructing queries dynamically at run time.

What's wrong with this JPQL query?


o Consider below example

EntityManager em = ...;
String jpql = "select p from Person where p.age > 20";
Query query = em.createQuery(jpql);
List result = query.getResultList();

Above code will compile happily, but will fail at run time because the JPQL query string is
syntactically incorrect. The correct syntax for the second line is :
o String jpql = "select p from Person p where p.age > 20";
o the Java compiler has no way to detect such an error.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 46


Criteria API Path
expression(Meta
Basic steps of writing criteria query. model api (not
covered))
1. EntityManager em = ...
2. CriteriaBuilder qb = em.getCriteriaBuilder();
3. CriteriaQuery<Person> c =
qb.createQuery(Person.class);
4. Root<Person> p = c.from(Person.class);
5. Predicate condition = qb.gt(p.get(Person_.age), 20);
6. c.where(condition);
7. TypedQuery<Person> q = em.createQuery(c);
8. List<Person> result = q.getResultList();

Line 1,2 : Get entity manager, EntityManager creates an instance CriteriaBuilder. CriteriaBuilder is
the factory for CriteriaQuery.
In line 3, the CriteriaBuilder factory constructs a CriteriaQuery instance. The generic type
argument declares the type of result this CriteriaQuery will return upon execution.
In line 4, the CriteriaQuery is set to query from Person.class.
o As a result, root<Person> instance p is returned. Root is a query expression that denotes the extent of a
persistent entity. Root<T> essentially says: "Evaluate this query across all instances of type T." It is similar to
the FROM clause of a JPQL or SQL query.

Line 5 constructs a Predicate. Predicate is another common form of query expression that
evaluates to either true or false. A predicate is constructed by the CriteriaBuilder
Line 6 sets the predicate on the CriteriaQuery as its WHERE clause.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 47


Criteria API
The query expressions are generically typed. A few typical expressions are:
o Root<T>, which is equivalent to a FROM clause.
o Predicate, which evaluates to a Boolean value of true or false. (In fact, it is declared as interface Predicate
extends Expression<Boolean>.)
o Path<T>, which denotes a persistent attribute navigated from a Root<?> expression. Root<T> is a special
Path<T> with no parent.

CriteriaBuilder is the factory for CriteriaQuery and query expressions of all sorts.

CriteriaQuery is a tree of query-expression nodes that are used to specify query clauses such as
FROM, WHERE, and ORDER BY in a traditional string-based query language.

CriteriaQuery is transferred to an executable query with its type information preserved so that the
elements of the selected list can be accessed without any run-time casting.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 48


Criteria API | Methods in the CriteriaBuilder Interface
Expression Methods in the CriteriaBuilder Interface.

Conditional Method Description


equal Tests whether two expressions are equal
notEqual Tests whether two expressions are not equal
gt Tests whether the first numeric expression is greater than the second numeric expression
ge Tests whether the first numeric expression is greater than or equal to the second numeric
expression
lt Tests whether the first numeric expression is less than the second numeric expression
le Tests whether the first numeric expression is less than or equal to the second numeric expression
between Tests whether the first expression is between the second and third expression in value
like Tests whether the expression matches a given pattern

Compound Predicate Methods in the CriteriaBuilder Interface

Method Description

and A logical conjunction of two Boolean expressions

or A logical disjunction of two Boolean expressions

not A logical negation of the given Boolean expression

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 49


Criteria API |Examples
Functional expression in CriteriaQuery
CriteriaQuery<Double> c c= =
CriteriaQuery<Double> cb.createQuery(Double.class);
cb.createQuery(Double.class);
Root<Account> aa==c.from(Account.class);
Root<Account> c.from(Account.class);
c.select(cb.avg(a.get(Account_.balance)));
c.select(cb.avg(a.get(Account_.balance)));

An equivalent JPQL query would be:


o String jpql = "select avg(a.balance) from Account a";
where() predicate in CriteriaQuery.
CriteriaQuery<Account> c = cb.createQuery(Account.class);
Root<Account> account = c.from(Account.class);
Path<Integer> balance = account.get(Account_.balance);
c.where(cb.and (cb.greaterThan(balance, 100), cb.lessThan(balance), 200)));

Equivalent JPQL "select a from Account a where a.balance>100 and a.balance<200";


Complex predicates | Multivalued expression in CriteriaQuery.
CriteriaQuery<Account> c = cb.createQuery(Account.class);
Root<Account> account = c.from(Account.class);
Path<Person> owner = account.get(Account_.owner);
Path<String> name = owner.get(Person_.name);
c.where(cb.in(name).value("X").value("Y").value("Z"));

JPQL : "select a from Account a where a.owner.name in ('X','Y','Z')";

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 50


Criteria API |Join
CriteriaQuery expresses joining two entities by typed join expressions
A typed join expression has two type parameters: the type you are joining from and the bindable
type of the attribute being joined.
For example, if you want to query for the Customers whose one or more PurchaseOrder(s) are not
delivered yet, you need to express this by an expression that joins Customer to PurchaseOrders,
where Customer has a persistent attribute named orders of type java.util.Set<PurchaseOrder>.

CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
Root<Customer> c = q.from(Customer.class);
SetJoin<Customer, PurchaseOrder> o = c.join(Customer_.orders);
Predicate p = cb.equal(o.get(PurchaseOrder_.status), Status.DELIVERED)
.negate();

The join expression created from the root expression c and the persistent Customer.orders
attribute.
The original attribute is of type java.util.Set, the resultant join expression is SetJoin.
SetJoin is a specialized Join for an attribute of declared type java.util.Set.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 51


Criteria API | Using parameters

Though queries are often written with constant literals, it is not a good practice. The good practice
is to parameterize a query, which allows the query to be parsed or prepared only once, cached,
and reused. So a better way to write the query is to use a named parameter:
o String jpql = "select p from Person p where p.age > :age";

A parameterized query binds the value of the parameter before the query execution:
o Query query = em.createQuery(jpql).setParameter("age", 20);
o List result = query.getResultList();

ParameterExpression<Integer> age = qb.parameter(Integer.class);


Predicate condition = qb.gt(p.get(Person_.age), age);
c.where(condition);
TypedQuery<Person> q = em.createQuery(c);
List<Person> result = q.setParameter(age, 20).getResultList();

The parameter expression is created with explicit type information to be an Integer and is directly
used to bind a value of 20 to the executable query.

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 52


Criteria API
Grouping Results
o The CriteriaQuery.groupBy method partitions the query results into groups. These groups are set by passing
an expression to groupBy:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.groupBy(pet.get(Pet_.color));

This query returns all Pet entities and groups the results by the pets color.

The CriteriaQuery.having method is used in conjunction with groupBy to filter over the groups.
The having method takes a conditional expression as a parameter. By calling the having method,
the query result is restricted according to the conditional expression:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.groupBy(pet.get(Pet_.color));
cq.having(cb.in(pet.get(Pet_.color)).value("brown").value("blonde"));

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 53


JPA exceptions
All exceptions
are unchecked

Exceptions in
javax.persistence
package are
self-explanatory

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 54


References
http://www.ibm.com/developerworks/java/library/j-typesafejpa/
http://docs.oracle.com/javaee/6/tutorial/doc/gjitv.html
Pro JPA 2 (Mastering the Java Persistence API 2.0)
http://blog.xebia.com/2009/03/09/jpa-implementation-patterns-data-access-objects/
JSR 317
Open JPA

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 55


Thank You!

COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 56

You might also like