Java Persistence API (JPA)
and Object Relational Mapping
Sadegh Aliakbary
JPA www.asta.ir 2
Java Database Connectivity (JDBC)
Object Relation Mapping
Java Persistence API (JPA)
Entity Classes
DAO and Generic DAO patterns
Object Relations (Many-to-One, One-to-Many, Many-to-Many)
JPQL
Querying with the Criteria API
Test JPA and DAO classes using spring
JPA and Spring
Transaction Management (by Spring Transaction)
Table of Contents
Getting Ready
3www.asta.irJPA
Review the Layers (Service, Manager, DAO)
Changes needed in Tomcat
Context.xml
Deploying the Project
Running Tomcat
It will generate some DB tables, that we will use in this session…
Start the Exercise Project
JPA www.asta.ir 4
Java Database Connectivity (JDBC)
5www.asta.irJPA
6
JDBC API provides a standard database-independent interface to
interact with RDBMSs.
JDBC API is used to
connect a java application to a database
query the data, and/or update data.
Using JDBC API relieves you of the effort to learn specific protocols for
different databases
But the SQL syntax of different DBs may still differ
JDBC
JPA www.asta.ir
7
The collection of implementation classes
that is supplied by a vendor
to interact with a specific database
The ‘JDBC driver’ is used to connect to the RDBMS.
Is usually delivered as a JAR file
E.g., Oracle JDBC driver, MySQL JDBC driver
JDBC Driver
JPA www.asta.ir
8
The Architecture of JDBC
JPA www.asta.ir
//Class.forName("com.mys ql.jdbc.Driver");
String SQL = "SELECT * FROM classes";
try (
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost/cse3330a",
"root", "123");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(SQL)
) {
while (rs.next()) {
System.out.println(rs.getString ("prof"));
}
}
9
JDBC Example
Now: Optional
JPA www.asta.ir
10
To connect to a database:
1. Obtain the JDBC driver class files (JAR)
add them to the CLASSPATH.
2. Construct a connection URL.
3. Use the static getConnection()’ method of ‘DriverManager’ to
establish a connection.
4. Create statements on the connection
and execute SQL queries
JDBC
JPA www.asta.ir
11
execute()’ method
is used to execute a SQL statement which does not return a value,
such as ‘CREATE TABLE’.
executeUpdate()method
is used for SQL that updates a database,
as in ‘INSERT, ‘UPDATE’ and ‘DELETE’ SQL statements.
It returns the number of rows affected.
executeQuery()
is used for SQL that produces a resultset,
as in ‘SELECT’ SQL statements.
‘Statement’ interface
JPA www.asta.ir
12
The ‘auto-commit’ property for the ‘Connectionobject
is set to ‘true’ by default.
If a ‘Connection’ is not in auto-commit mode:
you must call the ‘commit()’ or ‘rollback()’ method of the
Connection’ object to commit or rollback the transaction
Commit & Rollback
JPA www.asta.ir
13
AutoCommit
JPA www.asta.ir
try {
Connection conn = get the connection…
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql1);
stmt.executeUpdate(sql2);
conn.commit();
conn.close();
}
catch (SQLException e){
conn.rollback();
e.printStackTrack();
conn.close();
}
14
ResultSet Example
JPA www.asta.ir
Connection conn = …//get a Connection object
Statement stmt = conn.getStatement();
String sql = “select person_id, first_name,”+
last_name,dob,income from person”;
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
int personID=rs.getInt(1);
String firstName=rs.getString(2);
String lastName = rs.getString(3);
java.sql.Date dob = rs.getDate(4);
double income = rs.getDouble(5);
//do something with the retrieved values from the cols.
}
JPA www.asta.ir 15
JDBC Driver
Connection
Statement
ResultSet
Commit & rollback
Overview of JDBC Concepts
Pros
Clean and simple SQL processing
Very good for small applications
Simple syntax easy to learn
Cons
Complex if it is used in large projects
Large programming overhead
No encapsulation
Query is DBMS specific
JDBC Pros and Cons
JPA www.asta.ir 16
JPA www.asta.ir 17
Implement save and load methods in ContactDAO
Using JDBC
Add “age” field to ContactEntity
Revise the ContactDAO class
How much effort is needed?!
JDBC Exercise
JPA www.asta.ir 18
PreparedStatement
And CallableStatement
RowSet
SQL Injection
Other Concepts in JDBC
Object Relational Mapping
JPA www.asta.ir 19
JPA www.asta.ir 20
In relational databases:
business entities are represented as tables + relationships
In object-oriented languages:
business entities are represented as classes
Object relational mapping frameworks (ORMs) are used for:
mapping business entities to database tables
What is ORM?
ORM
Framework
OO
Programming
Language
Relational
Database
JPA www.asta.ir 21
ORM Example
JPA www.asta.ir 22
Person person = new Person(“Ali Alavi, 22, “0078934563”);
orm.save(person);
Simple Scenarios (Pseudocode)
Person[] people = orm.loadAll(Person.class);
query = “SELECT from Student where instructor.dep.name=‘ce ”;
Entity[] found = orm.find(query);
JPA www.asta.ir 23
E.g., how does it find the corresponding table for Student class?
It needs some meta-information
Class-table correspondence
Field-column correspondence
What is the format of such meta-data?
XML or Annotations
How does an ORM framework work?
JPA www.asta.ir 24
Now the ORM framework knows that:
ir.hr.Person class corresponds to PERSON table
and Person.name field corresponds to FULL_NAME column
How does it operate?
Suppose you want to write the ORM.save(Object o) method
How to implement save method?
Java Feature: Reflection
Reflection dynamically finds and manipulates classes and fields
How does an ORM framework work? (cont’d)
JPA www.asta.ir 25
ORM (Object-Relational Mapping) technologies
Map database tables to objects and enables CRUD operations, queries,
concurrency, transactions, etc.
Simplifies the development of DB applications
ORM in the Java world:
Java Persistence API (JPA) the standard for ORM in Java
Hibernate the most popular ORM library for Java (open source)
EclipseLink ORM for Java by Eclipse foundation (open source)
ORM Technologies
JPA www.asta.ir 26
Hibernate ORM http://hibernate.org/orm/
The first popular ORM framework in the Java world (2001)
Alternative to J2EE persistence technology called "EJB
Belongs to JBoss (RedHat)
EclipseLink https://eclipse.org/eclipselink/
ORM for Java by Eclipse foundation
Maps classes to database, XML and Web services
ORM in Java: Products and History
JPA www.asta.ir 27
Java Persistence API (JPA)
The official standard for ORM in Java and Java EE (JSR 338)
Implemented by most Java ORMs like Hibernate ORM, EclipseLink,
OpenJPA, Apache JDO, Oracle TopLink, DataNucleus, …
Hibernate also supports JPA
EclipseLink is the reference implementation
ORM in Java: Products and History (2)
Java v1.1 (1997) included JDBC
J2EE v1.2 (1999) introduced EJB Entity beans
Entity beans introduced, so others did it better
Hibernate (2001)
JPA v1.0 (JSR 220) was released in 2006
JPA v2.0 (JSR 317) was released in 2009
History
JPA www.asta.ir 28
Introduction to JPA
JPA www.asta.ir 29
JPA www.asta.ir 30
What is Java Persistence API (JPA)?
Database persistence technology for Java (official standard)
Object-relational mapping (ORM) technology
Operates with POJO entities with annotations or XML mappings
Implemented by many ORM engines: Hibernate, EclipseLink,
JPA maps Java classes to database tables
Maps relationships between tables as associations between classes
Provides CRUD functionality and queries
Create, read, update, delete + queries
About JPA
JPA www.asta.ir 31
A JPA entity is just a POJO class
The java classes corresponding to persistent data
E.g., User, Author, Book, etc.
Name more?!
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)
Entities in JPA
JPA www.asta.ir 32
Must be indicated as an Entity
@Entity annotation on the class:
The Minimal JPA Entity: Class Definition
@Entity
public class Employee {
}
JPA www.asta.ir 33
Must have a persistent identifier (primary key):
The Minimal JPA Entity: Primary Key
@Entity
public class Employee {
@Id int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
JPA www.asta.ir 34
Simple id single field/property
Compound id multiple fields
Primary Key (Id) Definitions
@Id int id;
@Id String firstName;
@Id String lastName;
JPA www.asta.ir 35
Identifiers can be generated in the database
@GeneratedValue on the ID field
Several pre-defined generation strategies:
IDENTITY. uses a database identity column
SEQUENCE. uses a database sequence
AUTO. Either identity or sequence or …
(depending on the underlying DB)
Primary Key Identifier Generation
@Id @GeneratedValue int id;
JPA www.asta.ir 36
Mapping a class field to a database column:
A column name can be explicitly given:
Simple Column Mappings
@Entity
public class Message {
private String message;
public void setMessage(String msg) { message = msg; }
public String getMessage() { return message; }
}
@Column(name="SAL")
private double salary;
JPA www.asta.ir 37
Example
@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable {
@Id
@Column(name = "ID")
private Integer id;
@Column(name = "CITY")
private String city;
@Column(name = "STATE")
private String state;
@Column(name = "STREET")
private String street;
@Column(name = "ZIP")
private String zip;
...
}
Persistence Contexts and
EntityManager
Manipulating Database Entities
JPA www.asta.ir 38
JPA www.asta.ir 39
The persistence context (PC)
Holds a set of “managedentity instances
Keyed by persistent identity (primary key)
Only one entity with a given persistent ID may exist in the PC
Managed by EntityManager
The PC change as a result of operations on EntityManager API
Persistence Context (PC)
JPA www.asta.ir 40
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
The EntityManager
JPA www.asta.ir 41
Persistence Context (PC) and Entities
Application
Persistence
Context
Entities
MyEntity A
MyEntity B
MyEntity C
MyEntity a
EntityManager
MyEntity b
Entity
state
JPA www.asta.ir 42
Entities are managed by an EntityManager instance using persistence
context
Each EntityManager instance is associated with a persistence context
Within the persistence context, the entity instances and their lifecycle
are managed
A persistence context is like a cache which contains a set of persistent
entities
So once the transaction is finished, all persistent objects are detached
from the EntityManager's persistence context and are no longer
managed
Overview of PC
JPA www.asta.ir 43
EntityManager API
persist() persists given entity object into the DB
(SQL INSERT)
merge() updates given entity in the DB
(SQL UPDATE)
remove() deletes given entity into the DB
(SQL DELETE by PK)
Operations on Entities
JPA www.asta.ir 44
flush()
Forces changes in the PC to be sent to the database
It is automatically called on transaction commit (but not vice
versa)
It does not call transaction commit. The transaction may be rolled-
back
Note:
Entitymanager.flush() vs EntityManager.getTransaction().commit
EntityManager.flush() method
JPA www.asta.ir 45
find() execute a simple query by PK
(SQL SELECT by PK)
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
Other EntityManager Operations
JPA www.asta.ir 46
Insert a new entity instance into the database
Save the persistent state of the entity and any owned relationship
references
Entity instance becomes managed
EntityManager.persist()
public Customer createCustomer(int id, String name) {
Customer cust = new Customer(id, name);
entityManager.persist(cust);
return cust;
}
JPA www.asta.ir 47
1- By just changing a managed
*
entity
And committing the transaction
2- By invoking merge() over a detached
*
entity
And committing the transaction
* Detached/Managed entities: described later
Updating an Entity
JPA www.asta.ir 48
find()
Obtain a managed entity instance (SQL SELECT by PK)
Return null if not found
remove()
Delete a managed entity by PK
find() and remove()
public void removeCustomer(Long custId) {
Customer cust = entityManager.find(Customer.class, custId);
entityManager.remove(cust);
}
Using the Persistence API
Creating Standalone JPA Applications
JPA www.asta.ir 49
JPA www.asta.ir 50
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
EntityManagerFactory Class
JPA www.asta.ir 51
Sample Config: META-INF/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>model.Message</class>
<properties>
<property name="ConnectionURL"
value="jdbc:derby:messages-db;create=true"/>
<property name="ConnectionDriverName"
value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="ConnectionUserName" value=""/>
<property name="ConnectionPassword" value=""/>
</properties>
</persistence-unit>
</persistence>
JPA www.asta.ir 52
JPA may be configured to automatically create the database
tables
During application deployment
Typically used during the development phase of a release,
not against a production database
javax.persistence.schema-generation.database.action property
Configures the behavior of JPA for table generation
Automatic Table Generation
JPA www.asta.ir 53
Since JPA 2.1 (2013)
Possible values:
none, create, drop-and-create,
javax.persistence.schema-generation.database.action
<persistence ...>
<persistence-unit name="WISE">
...
<properties>
...
<property name="javax.persistence.schema-generation.database.action"
value="drop-and-create"/>
</properties>
</persistence-unit>
</persistence>
JPA www.asta.ir 54
JPA Bootstrap Example
public class PersistenceExample {
public static void main(String[] args) {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("hellojpa");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// Perform finds, execute queries, update entities, etc.
em.getTransaction().commit();
em.close();
emf.close();
}
}
JPA Configuration in Spring
Many things should be configured for JPA: For Example?!
Which JPA implementation is used?
Hibernate? EclipseLink?
Database Configuration
Which DBMS? Oracle? MySQL?
DB URL? User/pass?
Which packages should be scanned for entities?
How to manager Transactions?
How to inject an EntityManager into DAO classes?
Spring makes configurations easy
JPA Configuration with Spring
JPA www.asta.ir 56
JPA www.asta.ir 57
Spring Configuration Example
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="ir.asta.training.contacts.entities" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/spring_jpa" />
<property name="username" value=“root" />
<property name="password" value=“123" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven />
JPA www.asta.ir 58
Now, With Spring We Can:
@Named("contactDao")
public class ContactDao {
@PersistenceContext
private EntityManager entityManager;
public void save(ContactEntity entity) {
entityManager.persist(entity);
}
public void delete(ContactEntity entity) {
entityManager.remove(entity);
}
}
JPA www.asta.ir 59
Review the Layers
Review the Spring configurations
Exercise on JPA and Spring
DAO and Generic DAO Patterns
JPA www.asta.ir 60
JPA www.asta.ir 61
Enterprise applications usually are
divided into logical layers
Three-layer
UI, Business Logic, Data
Four-Layer
UI, Service, Business Logic, Data
Data Layer: Collection of classes related to
data access (DAO layer)
Layering
Presentation Layer
Service Layer
Manager Layer
DAO Layer
DB
JPA www.asta.ir 62
Data Access Object Pattern (DAO)
(Entity)
JPA www.asta.ir 63
Abstracts the details of the underlying persistence mechanism
Hides the implementation details of the data source from its
clients
Loose coupling between core business logic and persistence
mechanism
DAO
JPA www.asta.ir 64
1. Write Entity Classes
@Entity @Table(name="WISE_CONTACT")
public class ContactEntity {
Long id;
String name;
@Id
@Column(name = "CONTACT_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) { this.id = id; }
@Basic(fetch=FetchType.EAGER)
@Column(name="NAME_")
public String getName() {
return name;
}
public void setName(String name) { this.name = name; }
}
JPA www.asta.ir 65
2. DAO implementations
@Named("contactDao")
public class ContactDao {
@PersistenceContext
private EntityManager entityManager;
public void save(ContactEntity entity) {
entityManager.persist(entity);
}
public void delete(ContactEntity entity) {
entityManager.remove(entity);
}
}
JPA www.asta.ir 66
The problem with many DAO implementations
Similar methods for
Load
Save, update, delete
Search
The solution?
A Generic DAO class
DAO implementation classes inherit from it
and implement the DAO interface
Generic DAO
JPA www.asta.ir 67
Generic DAO Example
class AbstractJpaDAO<T extends BaseEntity<U>, U extends Serializable>{
@PersistenceContext
private EntityManager entityManager;
public void save(T entity) {
etityManager.persist(entity);
}
public T load(U id) {
return (T) etityManager.find(getEntityClass(), id);
}
public abstract Class<T> getEntityClass() ;
//and find, search, update, many other methods.
}
public class ContactDao extends AbstractJpaDAO<ContactEntit, Long>{
public Class<ContactEntity> getEntityClass() {
return ContactEntity.class;
}
}
JPA www.asta.ir 68
Implement find method in ContactDAO
Using JPA
Exercise on JPA Basics
Transaction Management
(by Spring Transaction)
Programmatic Transactions
public void save(ContactEntity entity) {
EntityTransaction entityTransaction =
entityManager.getTransaction();
entityTransaction.begin();
entityManager.persist(entity);
entityTransaction.commit();
}
JPA www.asta.ir 70
With Spring @Transactional, the transaction management is made simple
This declarative transactions are much more convenient and readable
To use declarative transactions, we should configure it:
Using Spring @Transactional
@Transactional
public void businessLogic() {
... use entity manager inside a transaction ...
}
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven />
JPA www.asta.ir 71
JPA www.asta.ir 72
Methods of which layer become transactional?
Manager
Why?
Layering and Transactions
Presentation Layer
Service Layer
Manager Layer
DAO Layer
DB
JPA www.asta.ir 73
Implement save method in ContactDAO
Using JPA
Note to Transactions
Add emailfield to ContactEntity
Revise the ContactDAO class
How much effort is needed?!
Compare it with the JDBC approach
Simulate anaccount-transfer” method in Manager
Which invokes two dao methods in a transactional method
Test the transactionality! Does it roll-back?
Exercise on JPA
JPA Queries
Using JPQL
JPA www.asta.ir 74
JPA www.asta.ir 75
JPA supports powerful querying API
Dynamic or statically defined (named queries)
Criteria using JPQL (Java Persistence API Query Language)
SQL-like language
Native SQL support (when required)
Named parameters bound at execution time (no SQL injection)
Pagination and ability to restrict size of result
Single/multiple-entity results, data projections
Bulk update and delete operations on an entity
JPA Queries
JPA www.asta.ir 76
Query instances are obtained from factory methods on
EntityManager, e.g.
JPA query API:
getResultList() execute query returning multiple results
getSingleResult() execute query returning single result
executeUpdate() execute bulk update or delete
JPA Query API
Query query = entityManager.createQuery(
"SELECT e from Employee e");
JPA www.asta.ir 77
setMaxResults() set the maximum number of results to
retrieve
setFirstResult() set the first result row
number (starting row in paginations)
setParameter() bind a value to a named or positional
parameter
setFlushMode() apply a flush mode to the query when it
gets run
JPA Query API (2)
JPA www.asta.ir 78
Example: Pagination with JPQL
Query query = entityManager.createQuery("From Foo");
int pageNumber = 1;
int pageSize = 10;
query.setFirstResult((pageNumber-1) * pageSize);
query.setMaxResults(pageSize);
List fooList = query.getResultList();
JPA www.asta.ir 79
Use createQuery() factory method at runtime
Pass in the JPQL query string
Get results by getResultList() / getSingleResult()
Dynamic Queries Example
public List findAll(String entityName){
return entityManager.createQuery(
"select e from " + entityName + " e")
.setMaxResults(100)
.getResultList();
}
JPA www.asta.ir 80
JPQL Examples
Query query = em.createQuery("Select e FROM Employee e WHERE e.id = :id");
query.setParameter("id", id);
Employee result2 = (Employee)query.getSingleResult();
TypedQuery<Object[]> query = em.createQuery(
"SELECT c.name, c.capital.name FROM Country AS c", Object[].class);
List<Object[]> results = query.getResultList();
for (Object[] result : results) {
System.out.println("Country: " + result[0] + ", Capital: " + result[1]);
}
JPA www.asta.ir 81
Named queries are once defined and invoked later many times
Named Queries
@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();
}
JPA www.asta.ir 82
Named Query Examples
@Entity
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c")
public class Country {
...
}
@Entity
@NamedQueries({
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c"),
@NamedQuery(name="Country.findByName",
query="SELECT c FROM Country c WHERE c.name = :name"),
})
public class Country {
...
}
JPA www.asta.ir 83
Implement findAll method in ContactDAO
Using JPQL
Implement findByNamePrefix method in ContactDAO
Using JPQL
Like expression
SELECT e FROM Employee e WHERE p.name LIKE 'Mich%‘
Parameterized: ... WHERE p.name LIKE :name||'%'
Exercise on JPA
ORM Mappings
Mapping Tables to Classes by
Annotations
JPA www.asta.ir 84
JPA www.asta.ir 85
Map persistent object state to relational database
Map relationships between entities
Metadata may be described as annotations or XML (or both)
Annotations
Describe the logical (object) model, e.g. @OneToMany
Describe the physical model (DB tables and columns), e.g. @Table
Object / Relational Mapping
JPA www.asta.ir 86
Direct mappings of fields to columns
@Basic optional, indicates simple mapped attribute
Can specify fetch=EAGER / fetch=LAZY
LAZY: container defers loading until the field or property is accessed
(load on demand)
EAGER: the field or relationship loaded when the referencing entity is loaded
(pre-load)
Maps any of the common simple Java types
Primitives (int, long, String), wrappers, serializable, etc.
Used in conjunction with @Column
Can override any of the defaults
Simple Mappings
JPA www.asta.ir 87
Simple Mappings (Annotations)
public class Customer {
int id;
String name;
int creditRating;
Image photo;
}
CUSTOMER
ID NAME CREDIT
PHOTO
@Entity
@Id
@Lob
@Basic @Column(name="CREDIT")
@Basic @Column(name="name")
JPA www.asta.ir 88
It is also possible to describe mappings by XML files
But we focus on annotation-based mappings
Simple Mappings (XML)
<entity class="model.Customer">
<attributes>
<id name="id" />
<basic name="name" />
<basic name="creditRating">
<column name="CREDIT" />
</basic>
<basic name="photo"><lob /></basic>
</attributes>
</entity>
JPA www.asta.ir 89
Cardinality:
@ManyToOne, @OneToOne single entity
@OneToMany, @ManyToMany collection
Direction (navigability):
Unidirectional: we can go from entity A to entity B only.
Bi-directional: we can go from entity A to entity B & vice-versa.
Owning and inverse sides
Owning side specifies the physical mapping
@JoinColumn to specify foreign key DB column
@JoinTable decouples physical relationship mappings from entity tables
Relationship Mappings
JPA www.asta.ir 90
Many-To-One Mapping (Annotations)
public class Sale {
int id;
...
Customer cust;
}
SALE
CUST_ID
ID
CUSTOMER
ID
@Entity
@ManyToOne
@Id
@JoinColumn(name="CUST_ID")
JPA www.asta.ir 91
One-To-Many Mapping (Attributes)
public class Sale {
int id;
Customer cust;
}
public class Customer {
int id;
Set<Sale> sales;
}
CUSTOMER
ID
SALE
CUST_IDID
@Entity
@ManyToOne
@Id
@Entity
@Id
@OneToMany(mappedBy="cust")
JPA www.asta.ir 92
Many-To-Many Example
@Entity
public class Employee {
@Id
@Column(name="ID")
private long id;
...
@ManyToMany
@JoinTable(
name="EMP_PROJ",
joinColumns=@JoinColumn(name="EMP_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="PROJ_ID", referencedColumnName="ID"))
private List<Project> projects;
.....
}
@Entity
public class Project {
@Id
@Column(name="ID")
private long id;
...
@ManyToMany(mappedBy="projects")
private List<Employee> employees;
...
}
JPA www.asta.ir 93
The relationship may be unidirectional
If one end does not need to use the relationship
Example: Unidirectional ManyToMany relationship:
Bi-directional and Unidirectional Relationships
@Entity
public class Employee{
@Id
private Integer id;
@JoinTable(name = "PROJECT_EMPLOYEE",
joinColumns={@JoinColumn(name="EMPLOYEES_ID",
referencedColumnName="ID")},inverseJoinColumns
={@JoinColumn(name="PROJECTS_ID",
referencedColumnName = "ID")})
@ManyToMany
private List<Project> projectList;
...
}
@Entity
public class Project {
@Id
private Integer id;
...
}
Employee Project
0* 0*
JPA www.asta.ir 94
A collection is fetched when the application invokes an
operation upon that collection
This is the default for collections
Fetch Types:
EAGER: Defines that data must be eagerly fetched
LAZY: Defines that data can be lazily fetched (Upon request)
Remind:
Properties (basic fields) can also be lazy loaded (But default is eager)
Lazy Collection Fetching
JPA www.asta.ir 95
Lazy Fetching Example
@Entity
public class ProductEntity {
...
@ManyToMany(fetch=FetchType.EAGER)
private List<CategoryEntity> categories;
}
@ManyToMany(fetch=FetchType.LAZY)
Cascade Strategies
JPA www.asta.ir 97
Cascading of entity operations to related entities
may be defined per relationship
Configurable globally in the mapping files
By default no operations are cascaded.
Developers must do operations for relations of an entity
Cascading Actions
Persisting Relationships
@Entity
@Table(name = "PHONE")
public class Phone implements Serializable {
...
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "EMPLOYEE_ID", referencedColumnName = "ID")
private Employee employee;
}
Employee emp = new Employee(); // setters skipped
Phone phone = new Phone(); // setters skipped
phone.setEmployee(emp);
em.persist(phone);
// Consequently, em will also persist the Employee
JPA www.asta.ir 98
JPA www.asta.ir 99
ALL
Cascade all operations
PERSIST
Cascade persist operation
MERGE
Cascade merge operation
REMOVE
REFRESH
DETACH
Cascade Types:
JPA www.asta.ir 100
Assume the relationships
Order [1-n] Item
Item [n-1] Product
Product [n-n] Category
Define Entities
Add annotations
Set appropriate lazy/eager
Defines Services:
Add product (with a POST request to …/product/save)
With no category
Add Order
Add Item (…/add-item/23/12/3 Create an item: count=3, product_id=12, order-id=23)
Exercise
JPA www.asta.ir 101
Defines Services:
Add-product-item
…/category/categoryname/productname
(Adds a product in a new category)
Does it work with no cascade?
No, results in an exception
Set appropriate Cascade type
Exercise (cont’d)
Bean Validation
Validating input received from the user
to maintain data integrity is an important part of application logic.
The Java API for JavaBean Validation ("Bean Validation")
provides a facility for validating objects
The Bean Validation model is supported by constraints in the form of annotations
Constraints can be built in or user defined.
User-defined constraints are called custom constraints
Integrated with JSF, JPA, CDI, JAX-RS, etc.
Introduction to Bean Validation
JPA www.asta.ir 103
Constraint
Description
Example
@
AssertFalse
The
value of the field or property must be false.
@
AssertFalse
boolean
isUnsupported;
@
AssertTrue
The
value of the field or property must be true.
@
AssertTrue
boolean
isActive;
@
DecimalMax
The
value of the field or property must be a
decimal
value
lower than or equal to the number in the
value
element
.
@
DecimalMax("30.00")
BigDecimal
discount;
@
DecimalMin
The
value of the field or property must be a
decimal
value
greater than or equal to the number in the
value
element
.
@
DecimalMin("5.00")
BigDecimal
discount;
Built-In Bean Validation Constraints
JPA www.asta.ir 104
Constraint
Description
@Digits
The
value of the field or property must be a number within a
specified
range
. The integer element specifies the maximum integral digits for
the
number,
and the fraction element specifies the maximum fractional
digits
for
the number.
6
2)
price;
@Future
The
value of the field or property must be a date in the future.
eventDate;
@Max
The
value of the field or property must be an integer value lower than
or
equal
to the number in the value element.
10)
quantity;
@Min
The
value of the field or property must be an integer value greater than
or
equal
to the number in the value element.
5)
quantity;
Built-In Bean Validation Constraints
JPA www.asta.ir 105
Constraint
Description
Example
@
NotNull
The
value of the field or property must not be null.
@
NotNull
String
username;
@Null
The
value of the field or property must be null.
@Null
String
unusedString;
@Past
The
value of the field or property must be a date in the past.
@Past
Date
birthday;
@Pattern
The
value of the field or property must match the
regular
expression
defined in the regexp element.
@Pattern(
regexp="\\(\\d{3}\\)\\d
{
3}-\\d{4}")
String
phoneNumber;
Built-In Bean Validation Constraints
JPA www.asta.ir 106
Constraint
Description
Example
@Size
The
size of the field or property is evaluated and must match
the
specified
boundaries. If the field or property is a String, the size
of
the
string is evaluated. If the field or property is a Collection,
the
size
of the Collection is evaluated. If the field or property is a
Map,
the
size of the Map is evaluated. If the field or property is an
array,
the
size of the array is evaluated. Use one of the optional max
or
min
elements to specify the boundaries.
@Size(min=
2, max=240)
String
briefMessage;
Built-In Bean Validation Constraints
JPA www.asta.ir 107
Field Level Validation
public class Name {
@NotNull
@Size(min=1, max=16)
private String firstname;
@NotNull
@Size(min=1, max=16)
private String lastname;
}
JPA www.asta.ir 108
public class Employee {
...
public Employee(@NotNull String name) { ... }
public void setSalary(
@NotNull
@Digits(integer = 6, fraction = 2) BigDecimal salary,
@NotNull
String currencyType) {
}
...
}
Validating Constructors and Methods
JPA www.asta.ir 109
Declarative constraint management across application layers
Constraint
Restriction on a bean, field, property, method parameter, return value
Not null, between 10 and 45, valid email, etc
@Max, @Min, @Size, @NotNull, @Pattern, @Future, @Past
Custom constraints
Evaluated automatically
Integrated with JSF, JPA, CDI, JAX-RS
Summary
JPA www.asta.ir 110
JPA www.asta.ir 111
Set the following validation rules for contact entity
Age is a Required field
Age should be in the range [0,200]
Name contains no digits
Exercise
Managed vs Detached
JPA www.asta.ir 112
Life cycle of Entity
JPA www.asta.ir 113
JPA www.asta.ir 114
A managed object is the one read in the current persistence context
The PC will track changes to every managed object
If the same object is read again in the same persistence context,
or traversed through another managed object's relationship,
the same identical (==) object will be returned.
Calling persist() on a new object will also make it become managed
Calling merge() on a detached object will return a managed copy
A removed object will no longer be managed
after a flush() or commit().
Managed Objects
JPA www.asta.ir 115
A detached object is one that is not managed in the current PC
This could be
an object read through a different persistence context
or an object that was cloned or serialized
A new object is also considered detached until persist() is called on it
An object that was removed and flushed or committed, will become detached
A managed object should only ever reference other managed objects
and a detached object should only reference other detached objects
Incorrectly relating managed and detached objects :
one of the most common problems users run into in JPA
Detached Objects
JPA www.asta.ir 117
Entities Lifecycle
merge() synchronize the state of
detached entity with the PC
JPA www.asta.ir 118
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
merge()
public Customer storeUpdatedCustomer(Customer cust) {
return entityManager.merge(cust);
}
JPA www.asta.ir 119
New: The bean exists in the memory but is not mapped to
DB yet. It is not yet mapped to persistence context (via
entity manager)
Managed: The bean is mapped to the DB. The changes
effect the data in DB.
Detached: The bean is not mapped to the persistence
context anymore.
Removed: The bean is still mapped to the persistence
context and the DB, but it is programmed to be deleted.
Life cycle of Entity
JPA www.asta.ir 120
remove(): To delete the data
set(), get(): If the bean is in managed state, these methods
(of the entity bean) are used to access or modify the data.
persist(): To create the data. The bean goes to managed
state.
merge(): To take a bean from detached state to a managed
state.
Life cycle of Entity
JPA www.asta.ir 121
When the transaction (in transaction-scoped persistence
context) commits, entities managed by the persistence context
become detached.
If an application-managed persistence context is closed, all
managed entities become detached.
Using clear method
using detach method
rollback
When will the JPA Entities become Detached?
Criteria APIs
JPA www.asta.ir 123
The Java Persistence Criteria API
Defines dynamic queries
through the construction of object-based query definition objects
rather than use of the string-based approach of JPQL
Criteria API allows dynamic queries to be built programmatically
offering better integration with the Java language
than a string-based approach
The Criteria API was added in JPA 2.0
The Criteria API delete and update support was added in JPA 2.1
Criteria API
JPA Criteria API provides an alternative way for defining JPA queries
type-safe way to express a query
Mainly useful for building dynamic queries
whose exact structure is only known at runtime
Allows developers to find, modify, and delete persistent entities
Similar to JPQL
The Criteria API and JPQL are closely related
designed to allow similar operations in their queries.
Criteria API
JPA www.asta.ir 124
Consider this simple Criteria query:
returns all instances of the User entity in the data source
The equivalent JPQL query is: SELECT u FROM User u
The First Example
JPA www.asta.ir 125
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> user = cq.from(User.class);
cq.select(user);
TypedQuery<User> q = em.createQuery(cq);
List<User> allUsers = q.getResultList();
JPA www.asta.ir 126
With JPQL:
With criteria API:
JPQL may look simpler, but criteria API has its own advantages
JPQL vs Criteria API, an Example:
List<User> users =
entityManager.createQuery("select e from User e").getResultList();
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> user = cq.from(User.class);
cq.select(user);
TypedQuery<User> q = em.createQuery(cq);
List<User> allUsers = q.getResultList();
JPA www.asta.ir 127
A CriteriaBuilder is obtained from an EntityManager
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaBuilder is used to construct CriteriaQuery objects and their expressions
CriteriaBuilder API:
createQuery() - Creates a CriteriaQuery
createQuery(Class): using generics to avoid casting the result class
createTupleQuery() - Creates a CriteriaQuery that returns map like Tuple objects
instead of object arrays for multiselect queries
createCriteriaDelete(Class) and createCriteriaUpdate(Class)
Creates a CriteriaDelete or CriteriaUpdate to delete/update a batch of objects (JPA 2.1)
CriteriaBuilder
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
JPA www.asta.ir 128
(CriteriaQuery defines a database select query)
from(Class) : Defines an element in the query's from clause
At least one from element is required for the query to be valid
Returns a Root<EntityClass> instance
select(Selection): Defines the query's select clause
If not set, the first root will be selected by default
where(Expression), where(Predicate...) : Defines the where clause
By default all instances of the class are selected.
CriteriaQuery API
JPA www.asta.ir 129
CriteriaQuery Example
CriteriaBuilder cb = ...;
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> user = cq.from(User.class);
cq.select(user);
criteriaQuery.where(cb.greaterThan(user.get("age"), 18));
CriteriaQuery<CategoryEntity> cq = cb.createQuery(CategoryEntity.class);
Root<CategoryEntity> cat = cq.from(CategoryEntity.class);
cq.select(cat);
Predicate pred = cb.like(cat.get("name"), "Laptop%");
cq.where(pred);
Predicate like = cb.like(cat.get("name"), "Lap%");
Predicate idgt = cb.greaterThan(cat.get("id"), 5);
Predicate and = cb.and(like, idgt);
cq.where(and);
JPA www.asta.ir 130
distinct(boolean): filter duplicate results (defaults to false)
orderBy(Order...), orderBy(List<Order>): the order clause
By default the results are not ordered
groupBy(Expression...), groupBy(List<Expression>)
Defines the query's group by clause
By default the results are not grouped.
having(Expression), having(Predicate...): the having clause
Having allows grouped results to be filtered.
Other CriteriaQuery API
JPA www.asta.ir 131
Calls to the from() method are additive
Each call adds another root to the query
resulting in a Cartesian product
if no further constraints are applied in the WHERE clause
Multiple Selects in One CriteriaQuery
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")));
SELECT DISTINCT d FROM Department d, Employee e WHERE d = e.department
The path expression is the key to the power and flexibility of the JPQL language
And it is likewise a central piece of the Criteria API
Roots are actually just a special type of path expression
The get() method is equivalent to the dot operator used in JPQL path expressions
Path Expressions
CriteriaQuery<Employee> c = cb.createQuery(Employee.class);
Root<Employee> emp = c.from(Employee.class);
c.select(emp)
.where(cb.equal(emp.get("address").get("city"), "Yazd"));
SELECT e FROM Employee e WHERE e.address.city = 'Yazd'
JPA www.asta.ir 132
JPQL Clause
Criteria API Method
SELECT
select()
FROM
from()
WHERE
where()
ORDER BY
orderBy
()
GROUP BY
groupBy
()
HAVING
having()
Basic Structure
JPA www.asta.ir 133
JPQL Operator
CriteriaBuilder
Method
AND
and()
OR
or()
NOT
not()
=
equal()
<>
notEqual
()
>
gt
()
>=
ge
()
<
lt
()
<=
le()
Building Expressions
JPA www.asta.ir 134
Building Expressions
JPA www.asta.ir 135
JPQL Operator
CriteriaBuilder
Method
EXISTS
exist()
NOT EXISTS
not(exist())
IS
EMPTY
isEmpty
()
IS
NOT EMPTY
isNotEmpty
()
LIKE
lik
()
NOT LIKE
notLike
()
BETWEEN
between()
IN
in()
NOT IN
not(in())
IS NULL
isNull
()
IS NOT NULL
isNotNull
()
Building Expressions
JPA www.asta.ir 136
JPQL Operator
CriteriaBuilder
Method
AVG
avg
()
MIN
min()
MAX
max()
COUNT
count()
COUNT DISTINCT
countDistinct
()
LOWER
lower()
UPPER
upper()
CONCAT
concat
()
CURRENT_TIME
currentTime
()
In Expressions Example
CriteriaQuery<Employee> c = cb.createQuery(Employee.class);
Root<Employee> emp = c.from(Employee.class);
c.select(emp)
.where(emp.get("address")
.get("state").in("Yazd","Qom"));
JPA www.asta.ir 137
SELECT e FROM Employee e
WHERE e.address.state IN ('Yazd', 'Qom')
JPA www.asta.ir 138
Join
teacher.join("phones") creates a join
on the collection field named phones
Variable phones is similar to the p variable
that represents join in JPQL
SELECT
p FROM Teacher t JOIN t.phones p
CriteriaBuilder
cb = em.getCriteriaBuilder();
CriteriaQuery
<Phone> query = cb.createQuery(Phone.class);
Root<Teacher> teacher =
query.from(Teacher.class);
Join<Teacher, Phone> phones
= teacher.join("phones");
query.select
(phones).where(cb.equal(teacher.get("firstName"), "Sadegh"));
JPA www.asta.ir 139
Multiselect
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.multiselect(employee.get("firstName"), employee.get("lastName"));
Query query = entityManager.createQuery(criteriaQuery);
List<Object[]> result = query.getResultList();
JPA www.asta.ir 140
Parameters in Criteria API
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery();
Root<Employee> employee = cq.from(Employee.class);
criteriaQuery.where(
cb.equal(employee.get("firstName"),
cb.parameter(String.class, "first")),
cb.equal(employee.get("lastName"),
cb.parameter(String.class, "last"))
);
Query query = entityManager.createQuery(cq);
query.setParameter("first", "Bob");
query.setParameter("last", "Smith");
List<Employee> = query.getResultList();
The orderBy() method
Accepts one or more Order objects
created by the asc() and desc() methods of CriteriaBuilder
The ORDER BY Clause
CriteriaQuery<Employee> c = cb.createQuery(Employee.class);
Root<Employee> emp = c.from(Employee.class);
c.orderBy(cb.desc(emp.get("name")), cb.asc(emp.get("age")));
SELECT e ROM Employee e
ORDER BY d.name DESC, d.age ASC
JPA www.asta.ir 141
The GROUP BY and HAVING Clauses
CriteriaQuery<Object[]> c = cb.createQuery(Object[].class);
Root<Employee> emp = c.from(Employee.class);
Join<Employee,Project> project = emp.join("projects");
c.multiselect(emp, cb.count(project))
.groupBy(emp)
.having(cb.ge(cb.count(project),2));
SELECT e, COUNT(p)
FROM Employee e JOIN e.projects p
GROUP BY e HAVING COUNT(p) >= 2
JPA www.asta.ir 142
Bulk Update and Delete
UPDATE Employee e SET e.salary = e.salary + 5000 WHERE e.salary<1000000
CriteriaUpdate<Employee> q = cb.createCriteriaUpdate(Employee.class);
Root<Employee> emp = q.from(Employee.class);
q.set(emp.get("salary"), cb.sum(emp.get("salary"), 5000))
.where(cb.lt(emp.get("salary"), 1000000));
JPA www.asta.ir 143
CriteriaDelete<Employee> q = cb.createCriteriaDelete(Employee.class);
Root<Employee> emp = q.from(Employee.class);
q.where(cb.isNull(emp.get("dept")));
DELETE FROM Employee e WHERE e.department IS NULL
JPA www.asta.ir 144
JPQL queries are defined as strings, similarly to SQL
JPA criteria queries are defined by instantiation of Java objects
The criteria API: errors can be detected earlier
during compilation rather than at runtime
For many developers string based JPQL queries are easier to use and understand
JPQL queries are similar to SQL queries
For simple static queries: string based JPQL queries may be preferred
For dynamic queries that are built at runtime: the criteria API may be preferred
E.g., building a dynamic query based on fields that a user fills at runtime
in a form that contains many optional fields
cleaner when using the JPA criteria API because it eliminates many string concatenations
JPQL and JPA criteria based queries are equivalent in power
JPQL vs Criteria API
JPA www.asta.ir 145
First, fill some items and products into the DB
Defines Services:
Select product-name of items of an order with quantity>param
…/min-items/order-id/min-quantity
Exercise
Appropriate inheritance
strategies
It maps each concrete class to its own table
A mapped superclass is not an entity, and there is no table for it
1- Mapped Superclass Strategy
@MappedSuperclass
public abstract class Publication {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
protected Long id;
...
}
@Entity(name = “Book”)
public class Book extends Publication {
@Column
private int pages;
}
JPA www.asta.ir 147
JPA www.asta.ir 148
Similar to the mapped superclass strategy
But the superclass is now also an entity
Each of the concrete classes gets still mapped to its own table
This mapping allows you to use polymorphic queries
and to define relationships to the superclass
2- Table per Class Strategy
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Publication {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = “id”)
protected Long id;
...
}
JPA www.asta.ir 149
It maps all entities of the inheritance structure to the same table
3- Single Table Strategy
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = “Publication_Type”)
public abstract class Publication {...}
JPA www.asta.ir 150
It maps each class of the inheritance hierarchy to its own table
Even the parent class
The tables of the subclasses are much smaller
They hold only the columns specific for the mapped entity class
and a primary key with the same value as the record in the table
of the superclass.
4- Joined Strategy
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Publication {
JPA www.asta.ir 151
1- Mapped Superclass Strategy
2- Table per Class Strategy
3- Single Table Strategy
4- Joined Strategy
Choosing a Strategy
The End
JPA www.asta.ir 152