An introduction to the Java Persistence API 2.x (JPA). Namely, this set of slides first introduces the problem of impedance mismatch between the object model and the relation model. Then, the EntityManager's public interface is discussed, together with the parallelism between a persistence context and a L1 cache. The issue of encapsulating the different application's use cases (which are exposed by the service objects) is solved by means of the @Transactional annotation, which provides a declarative way of demarcating the application's transactional boundaries. It follows an in-depth explanation on how to integrate a local, container-managed EntityManager within an existing Spring MVC application, so as to correctly support the propagation of the persistence context throughout the different beans involved in the same transaction. We then turn our attention to the problem of mapping relationships, thus introducing the @OneToMany, @ManyToMany and @OneToOne annotations. The additional topics of how to cascade operations and how to support lazy loading are covered as well. The presentation concludes with a discussion on how to use both the Criteria and Query API (and JPQL) to query the underlying database.
2. Outline
• Object vs. rela/onal model
• En//es and EntityManager
• Integra/ng JPA into Spring
• Mapping rela/onships
• Querying the data source
• References
5. Object vs. rela.onal model
In many cases, the DBMS has been around for much longer than
the Web applica;on
6. Object vs. rela.onal model
It is up to the object model of the Web app to find ways to work
with the database schema
7. Object vs. rela.onal model
The technique of bridging the gap between the object model and
the rela7onal model is known as object-rela+onal mapping (ORM)
8. Object vs. rela.onal model
Object-rela+onal mapping techniques try to map the concepts
from one model onto another
9. Impedance mismatch
┌───────────────────────────────┬──────────────────────────────┐
│////////// OOP Model //////////│////// Relational model /////│
├───────────────────────────────┼──────────────────────────────┤
│ Classes, objects │ Tables, rows │
├───────────────────────────────┼──────────────────────────────┤
│ Attributes, properties │ Columns │
├───────────────────────────────┼──────────────────────────────┤
│ Identity │ Primary key │
├───────────────────────────────┼──────────────────────────────┤
│ References to other entities │ Foreign key │
├───────────────────────────────┼──────────────────────────────┤
│ Inheritance, polymorphism │ Not supported │
├───────────────────────────────┼──────────────────────────────┤
│ Methods │ Stored procedures, triggers │
├───────────────────────────────┼──────────────────────────────┤
│ Code is portable │ Code is vendor-depending │
└───────────────────────────────┴──────────────────────────────┘
10. The challenge of mapping one model to the other lies in the concepts in
each for which there is no logical equivalent in the other
11. Impedance mismatch
As a result, moving data back and forth between a DBMS and the
object model is a lot harder than it needs to be
20. Java Persistence API
Despite its ini)al associa)on with EJBs, JPA is a JSE API, as
reflected by its belonging to the java.persistence package
21. Java Persistence API
JPA provides an ease-of-use abstrac5on on top of JDBC
┌──────────────────┐ ┌──────────────────┐
│ Java │ │ Vendor- │
│ Persistence API │ │ specific API │
└──────────────────┘ └──────────────────┘
┌───────────────────────────────────────┐
│ │ The persistence provider
│ Persistence provider │ is in charge of the ORM
│ │
└───────────────────────────────────────┘
┌───────────────────────────────────────┐
│ │ JDBC provides methods
│ JDBC │ for querying and updating
│ │ data in the database
└───────────────────────────────────────┘
┌───────────────────────────────────────┐
│ │
│ DBMS │
│ │
└───────────────────────────────────────┘
22. Java Persistence API
The code can therefore be isolated from vendor-specific
peculiari1es and rela1on model peculiari1es
┌──────────────────┐ ┌──────────────────┐
│ Java │ │ Vendor- │
│ Persistence API │ │ specific API │
└──────────────────┘ └──────────────────┘
┌───────────────────────────────────────┐
│ │ The persistence provider
│ Persistence provider │ is in charge of the ORM
│ │
└───────────────────────────────────────┘
┌───────────────────────────────────────┐
│ │ JDBC provides methods
│ JDBC │ for querying and updating
│ │ data in the database
└───────────────────────────────────────┘
┌───────────────────────────────────────┐
│ │
│ DBMS │
│ │
└───────────────────────────────────────┘
24. POJO persistence
JPA provides a Plain Old Java Object (POJO) persistence model
public class Employee {
private int id;
private String name;
private long salary;
public Employee() {...}
// other methods (e.g., getters and setters)
}
25. POJO persistence
There is nothing special about the objects being persisted
public class Employee {
private int id;
private String name;
private long salary;
public Employee() {...}
// other methods (e.g., getters and setters)
}
26. POJO persistence
Any exis)ng non-final class with a default constructor can be
made persistable
public class Employee {
private int id;
private String name;
private long salary;
public Employee() {...}
// other methods (e.g., getters and setters)
}
27. Non-intrusiveness
The persistence API exists as a separate layer from the domain
model
┌──────┐┌────────────────────────────────┐
│ D ││ │
│ o ││ Presentation layer │
│ m ││ │
│ a │└────────────────────────────────┘
│ i │┌────────────────────────────────┐
│ n ││ │
│ ││ Service layer │
│ m ││ │
│ o │└────────────────────────────────┘
│ d │┌────────────────────────────────┐
│ e ││ │
│ l ││ Persistence layer │
│ ││ │
└──────┘└────────────────────────────────┘
28. Non-intrusiveness
That is, the persisted objects are not aware of the persistence layer
┌──────┐┌────────────────────────────────┐
│ D ││ │
│ o ││ Presentation layer │
│ m ││ │
│ a │└────────────────────────────────┘
│ i │┌────────────────────────────────┐
│ n ││ │
│ ││ Service layer │
│ m ││ │
│ o │└────────────────────────────────┘
│ d │┌────────────────────────────────┐
│ e ││ │
│ l ││ Persistence layer │
│ ││ │
└──────┘└────────────────────────────────┘
29. Object queries
JPA comes with an object-oriented query language that operates
on classes and objects, rather than tables and rows
SELECT c
FROM Category c
WHERE c.items is NOT EMPTY
31. En##es in the rela#onal paradigm
In the rela*onal paradigm, an en#ty is something that can be
recognized to have a7ributes and rela*onships
id departOn
● ○
│ │
┌───┴───────────┴─────┐
│ │ arriveOn
│ Flight │─────○
│ │
└─────────────────────┘
32. En##es in the rela#onal paradigm
An en%ty has an independent existence and can be uniquely
iden/fied
id departOn
● ○
│ │
┌───┴───────────┴─────┐
│ │ arriveOn
│ Flight │─────○
│ │
└─────────────────────┘
33. En##es in the rela#onal paradigm
An en%ty may par$cipate in rela$onships with any number of
other en%%es in a number of standard ways
+---------+ +---------+ +----------+
| | | | | |
| +-----> +------> |
| | | | | |
+---------+ +---------+ +----------+
Flight FlightLeg Airport
34. En##es in the OO paradigm
In the object-oriented paradigm, we would add behavior to an
en7ty and call it a class
public class Flight {
private List<FlightLeg> legs;
private BigDecimal totalCost;
public Flight(...) {...}
public boolean isNonStop() {...}
public long getTotalTravelTime() {...}
// other methods
}
35. The intui)on behind ORM
Hence, the intui%on behind object-rela2onal mapping is that
• Classes correspond to tables
• Objects correspond to tuples
36. En#ty classes
The @Entity annota)on is used to qualify a class as an en'ty
@Entity
public class Employee {
@Id private int id;
private String name;
private long salary;
public Employee() { ... }
// other methods (e.g., getters and setters)
}
37. En#ty classes
En#ty objects are just plain-old Java objects
Employee emp1 = new Employee(12, "Jon Snow");
Employee emp2 = new Employee(20, "Portgas D. Ace");
38. En#ty requirements
En##es must respect some requirements
• The en'ty class must have a public or protected default
constructor
• The en'ty class must not be final
39. En#ty requirements
En##es must respect some requirements
• No method or variables of the en3ty class may be final
• If an en3ty object is to be passed as a detached object, the
Serializable interface must be implemented
40. Persistence unit
We refer to the set of en(ty classes as the persistence unit
@Entity public class Employee { ... }
@Entity public class Department { ... }
@Entity public class ParkingSpace { ... }
44. Crea%ng a new en%ty
En#ty objects do not become persistent just by invoking the new
operator1
Employee e = new Employee(12, "Jon Snow”)
1
How would they auto-magically become persistent? A:er all, we said that en<<es objects are just POJOs
45. Crea%ng a new en%ty
Newly-created objects are in the transient state, since the
EntityManager does not know they exist yet
Employee e = new Employee(12, "Jon Snow")
46. Persis&ng an en&ty
En#ty objects remain transient un#l we no#fy the
EntityManager of their existence
Employee e = new Employee(12, "Jon Snow")
47. Persis&ng an en&ty
The persist() method no#fies the En+tyManager of the
existence of a given transient en+ty object2
Employee emp = new Employee(12, "Jon Snow");
entityManager.persist(emp);
2
Remembr that the persist() method does not actually cause the en3ty object to be immediately persisted, we
are just sending a no3fica3on to the EntityManager
48. Persis&ng an en&ty
The en&ty object enters the managed state
Employee emp = new Employee(12, "Jon Snow");
entityManager.persist(emp);
49. Persis&ng an en&ty
EntityManager makes sure that each managed object is
synchronized with the related database tuple
Employee emp = new Employee(12, "Jon Snow");
entityManager.persist(emp);
50. Persistence context
The set of managed objects is called the persistence context
┌─────────────────────────────┐
│ │
│ ● o1 │ ● o5
│ │
│ ● o4 │ ● o6
│ │
│ ● o2 │
│ ● o3 │ ● o7
│ │
└─────────────────────────────┘
Persistence context
52. Persistence context
Each EntityManager has its own persistence context, and there
may exist several EntityManagers at once
EntityManager A EntityManager B
◊ ◊
│ │
┌──────────────────┼──────────┐ ┌──────────────────┼──────────┐
│ │ │ │ │ │
│ │ │ │ │ │
│ ● o1 │ │ ● o5 │ ● o9
│ │ │ │
│ ● o4 │ │ ● o7 │ ● o8
│ │ │ │
│ ● o2 │ │ ● o6 │
│ ● o3 │ │ │ ● o10
│ │ │ │
└─────────────────────────────┘ └─────────────────────────────┘
Persistence context A Persistence context B
53. Finding an en)ty
The find() method finds en*ty objects by primary key
Employee emp = entityManager.find(Employee.class, 12);
54. Finding an en)ty
When the call completes, the returned en2ty object is in the
managed state
Employee emp = entityManager.find(Employee.class, 12);
55. Finding an en)ty
The find() method returns null if the en/ty cannot be found
Employee emp = entityManager.find(Employee.class, 12);
56. Removing an en+ty
The remove() method removes the data associated with an en/ty
object from the database
entityManager.remove(emp);
57. Removing an en+ty
The remove() method will also detach the en/ty object
entityManager.remove(emp);
58. Removing an en+ty
Once detached, an en+ty is no longer managed by the related
EntityManager, i.e., it is no longer part of its persistence context
entityManager.remove(emp);
59. Removing an en+ty
Since the related tuple is deleted, the en1ty objects enters the
removed state
entityManager.remove(emp);
64. Iden%fier genera%on
This persistence provider’s feature is called iden%fier genera%on
and is specified by the @GeneratedValue annota7on
@Entity
public class Employee {
@Id @GeneratedValue
private int id;
...
}
65. Iden%fier genera%on
Applica'ons can choose one out of four genera*on strategies
┌──────────────────────────────┬─────────────────────────────────────────┐
│/// Id generation strategy ///│////////////// Description /////////////│
├──────────────────────────────┼─────────────────────────────────────────┤
│ │The provider generates identifiers by │
│ AUTO │using whatever strategy it wants │
│ │ │
├──────────────────────────────┼─────────────────────────────────────────┤
│ │Identifiers are generated according to a │
│ TABLE │generator table │
│ │ │
├──────────────────────────────┼─────────────────────────────────────────┤
│ │If the underlying DB supports sequences, │
│ SEQUENCE │the provider will use this feature for │
│ │generating ids │
├──────────────────────────────┼─────────────────────────────────────────┤
│ │If the underlying DB supports primary key│
│ IDENTITY │identity columns, the provider will use │
│ │this feature for generating ids │
└──────────────────────────────┴─────────────────────────────────────────┘
66. AUTO strategy
Remember that the AUTO mode is a genera0on strategy mainly
meant for developing prototypes
@Entity
public class Employee {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private int id;
...
}
67. AUTO strategy
In any other situa.on, it would be be4er to use other genera.on
strategies
@Entity
public class Employee {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private int id;
...
}
69. Required steps
To use JPA in our Spring Web applica5on we need to
1. Define a data source
2. Understand how to produce EntityManager instances
3. Introduce transac8onal seman8cs into the service layer
4. Write JPA-based repository beans
75. Pooled data source
We will use the pooled data source coming from the Apache
Database Connec/on Pooling (DBCP) project
76. Declaring the data source
By altering dataSource-context.xml, we can declare the new
data source as a bean in the back-end container
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://server:3306/db_schema"/>
<property name="username" value=”dbuser"/>
<property name="password" value=”dbpassword"/>
</bean>
77. Declaring the data source
BasicDataSource is the class implemen-ng the pooled data
source
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://server:3306/db_schema"/>
<property name="username" value=”dbuser"/>
<property name="password" value=”dbpassword"/>
</bean>
78. Declaring the data source
com.mysql.jdbc.Driver is the class implemen-ng the JDBC
driver
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://server:3306/db_schema"/>
<property name="username" value=”dbuser"/>
<property name="password" value=”dbpassword"/>
</bean>
79. Maven dependencies
As usual, we can use Maven to automa1cally resolve dependencies
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
80. Maven dependencies
As usual, we can use Maven to automa1cally resolve dependencies
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
85. Applica'on-managed
The applica*on is responsible for every aspect of the
EntityManager’s lifecycle
EntityManager em = emf.createEntityManager();
...
entityManager.close();
86. Applica'on-managed
The applica*on also needs to manually manage transac'ons
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
90. EntityManager beans
• LocalEntityManagerFactoryBean for applica+on-managed
EntityManagers
• LocalContainerEntityManagerFactoryBean for
container-managed EntityManagers3
3
Actually, LocalEntityManagerFactoryBean (resp. LocalContainerEntityManagerFactoryBean)
produces applica5on-managed (resp. container-managed) EntityManagerFactorys, which will in turn produce
applica5on-managed (resp. container-managed) EntityManagers
91. EntityManager beans
The following declares a factory bean for container-managed
EntityManagers in dataSource-context.xml
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="it.polimi.awt.springmvc.domain"/>
<property name="persistenceUnitName" value=”MyPersistenceUnit"/>
...
</bean>
92. EntityManager beans
dataSource is the data source bean we previously declared
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="it.polimi.awt.springmvc.domain"/>
<property name="persistenceUnitName" value=”MyPersistenceUnit"/>
...
</bean>
93. EntityManager beans
it.polimi.awt.springmvc.domain is the package containing
the classes to be persisted
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="it.polimi.awt.springmvc.domain"/>
<property name="persistenceUnitName" value=”MyPersistenceUnit"/>
...
</bean>
94. EntityManager beans
MyPersistenceUnit is the name of the persistence unit
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="it.polimi.awt.springmvc.domain"/>
<property name="persistenceUnitName" value=”MyPersistenceUnit"/>
</bean>
96. Persistence provider
One way to tell Spring which implementa3on to use is to declare a
JpaVendorAdapter bean in dataSource-context.xml
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
</bean>
97. Persistence provider
Specifically, we use HibernateJpaVendorAdapter to denote
that Hibernate is our persistence provider
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
</bean>
98. Persistence provider
We set the database property to MYSQL to denote that MySQL is
the underlying RDBMS
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
</bean>
99. Persistence provider
We can now set-inject our JpaVendorAdapter bean into the
LocalContainerEntityManagerFactoryBean:
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="it.polimi.awt.springmvc.domain"/>
<property name="persistenceUnitName" value=”MyPersistenceUnit"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
</bean>
106. Transac'ons
Transac'ons allow grouping several opera'ons into a single unit of
work that either fully happens or fully does not happen
Everything goes well
+------------------->
+-----------------------+ |
| | |
| 1. Verify seats | |
Purchase ticket | 2. Reserve seat | |
+-----------------------> 3. Receive payment +----+
| 4. Issue ticket | |
| | |
+-----------------------+ |
+-------------------->
Something goes wrong
107. Transac'onal boundary
The service layer is the transac'onal boundary of the applica1on
┌──────┐┌────────────────────────────────┐
│ D ││ │
│ o ││ Presentation layer │
│ m ││ │
│ a │└────────────────────────────────┘
│ i │╔════════════════════════════════╗
│ n │║ ║
│ │║ Service layer ║
│ m │║ ║
│ o │╚════════════════════════════════╝
│ d │┌────────────────────────────────┐
│ e ││ │
│ l ││ Persistence layer │
│ ││ │
└──────┘└────────────────────────────────┘
108. Transac'onal boundary
If a service method makes mul3ple calls against one or more
persistence beans, we want those calls to operate as part of a
single transac,on
109. Transac'onal boundary
To handle this, the service layer needs a way to embed its
persistence calls within the context of a transac,on
112. Transac'on managers
Instead, it provides a selec1on of transac'on managers
• JpaTransactionManager
• JtaTransactionManager
• JdoTransactionManager
113. Transac'on managers
Each such transac+on manager acts as a façade to a pla2orm-
specific implementa+on
• JpaTransactionManager
• JtaTransactionManager
• JdoTransactionManager
114. Declaring a transac-on manager
The transac+on manager of interest needs to be declared in
dataSource-context.xml
<bean id=”transactionManager”
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
115. Declaring a transac-on manager
JpaTransactionManager needs to be wired to a
EntityManagerFactory
<bean id=”transactionManager”
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
116. Declaring a transac-on manager
JpaTransactionManager collaborates with the
EntityManager that is produced by the factory to conduct
transac4ons
<bean id=”transactionManager”
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
117. Two types of transac/ons
Spring provides two ways of specifying transac3ons
• Programma(c transac(ons
• Declara(ve transac(ons
118. Declara've transac'ons
Most Spring users choose declara've transac'on management, as
this op2on has the least impact on applica2on code
120. @Transactional
The @Transactional annota)on specifies that an interface,
class, or method must have transac'onal seman'cs
@Service
@Transactional
public class AccountServiceImpl implements AccountService { ... }
121. @Transactional
From this point on, opera/ons will be transac'onal
@Service
@Transactional
public class AccountServiceImpl implements AccountService { ... }
122. @Transactional
When needed, addi$onal transac-onal seman$cs can be specified
(e.g., marking the transac-ons as read-only)
@Service
@Transactional(readOnly = true)
public class AccountServiceImpl implements AccountService { ... }
123. Ac#vate declara#ve transac#ons
A simple addi+on to dataSource-context.xml allows
ac+va+ng declara+ve transac+ons
<tx:annotation-driven/>
124. Maven dependencies
As usual, we can use Maven to automa1cally resolve dependencies
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
134. One persistence context
Therefore, we want exactly one EntityManger per transac3on, as
different EntitManagers correspond to different persistence
contexts
135. Persistence context propaga/on
We want to automa&cally propagate the same persistence context
to all the beans involved in the same transac5on
@Repository public class AccountRepositoryImpl implements AccountRepository {...}
@Repository public class LogRepositoryImpl implements LogRepository {...}
136. Persistence context propaga/on
This amounts to injec/ng the same EntityManager to all the
components involved
@Repository public class JpaAccountRepository implements AccountRepository {...}
@Repository public class JpaLogRepository implements LogRepository {...}
137. @PersistenceContext
The @PersistenceContext annota)on automa&cally
propagates the persistence context
@Repository
public class JpaAccountRepository implements AccountRepository {
@PersistenceContext
private EntityManager em;
@Override
public Account findById(int id) {
return em.find(Account.class, id);
}
}
139. En##es and rela#onships
If en&&es were isolated from one another, the issue of ORM would
be a trivial one
+------------+ +--------------+
| | | |
| Employee | | Department |
| | | |
+------------+ +--------------+
140. En##es and rela#onships
In reality, most en//es need to be able to have rela%onships with
other en//es
+------------+ +--------------+
| | | |
| Employee +-------------> Department |
| | * 1 | |
+------------+ +--------------+
141. En##es and rela#onships
This is what produces the domain model of the applica2on
+------------+ +--------------+
| | | |
| Employee +-------------> Department |
| | * 1 | |
+------------+ +--------------+
143. Direc&onality
Each en(ty in a rela(onship may have a pointer to the other en(ty
+------------+ +--------------+
| | | |
| Employee +-------------> Department |
| | * 1 | |
+------------+ +--------------+
144. Direc&onality
If only one en)ty has a pointer to the other, the rela)onship is said
to be unidirec(onal
+------------+ +--------------+
| | | |
| Employee +-------------> Department |
| | * 1 | |
+------------+ +--------------+
145. Direc&onality
When each en(ty points to the other, the rela(onship is said to be
bidirec'onal
+------------+ +--------------+
| | | |
| Employee <-------------> Department |
| | * 1 | |
+------------+ +--------------+
146. Direc&onality
All rela'onships in JPA are unidirec(onal. A bidirec'onal
rela'onship has to be intended as a pair of unidirec'onal mappings
+------------+ * 1 +--------------+
| +-------------> |
| Employee | | Department |
| <-------------+ |
+------------+ * 1 +--------------+
147. Role
Depending on the direc.onality, we can iden.fy the en.ty playing
the role of source and the en.ty playing the role of target
+------------+ +--------------+
| | | |
| Employee +-------------> Department |
| | * 1 | |
+------------+ +--------------+
148. Role
Employee and Department are involved in a unidirec(onal
rela(onship
+------------+ +--------------+
| | | |
| Employee +-------------> Department |
| | * 1 | |
+------------+ +--------------+
149. Role
Employee is the source en)ty
+------------+ +--------------+
| | | |
| Employee +-------------> Department |
| | * 1 | |
+------------+ +--------------+
150. Role
Department is the target en(ty
+------------+ +--------------+
| | | |
| Employee +-------------> Department |
| | * 1 | |
+------------+ +--------------+
151. Cardinality
Each role in the rela-onship has its own cardinality
• Many-to-one: many source en..es, one target en.ty
• One-to-many: one source en.ty, many target en..es
• One-to-one: one source en.ty, one target en.ty
• Many-to-many: many source en..es, many target en..es
152. Ownership
In the database, almost every rela2onship is implemented by
introducing a column that refers to a key in another table
154. Ownership
The underlying Employee table has a join column containing the
Department primary key
┌─────────────┬───────────────┬─────────────┬──────────────┐
│ employeeId │ name │ gender │ departmentId │
├─────────────┼───────────────┼─────────────┼──────────────┤
│ 12 │ Jon Snow │ male │ 7 │
└─────────────┴───────────────┴─────────────┴──────────────┘
155. Ownership
The en&ty holding the join column is called the owner of the
rela&onship and its side is called the owning side
┌─────────────┬───────────────┬─────────────┬──────────────┐
│ employeeId │ name │ gender │ departmentId │
├─────────────┼───────────────┼─────────────┼──────────────┤
│ 12 │ Jon Snow │ male │ 7 │
└─────────────┴───────────────┴─────────────┴──────────────┘
156. Ownership
Employee is the owner of the rela,onship
+------------+ +--------------+
| | | |
| Employee +-------------> Department |
| | * 1 | |
+------------+ +--------------+
157. Many-to-one mappings
In a many-to-one mapping, the owner of the rela2onship is the
source en2ty
@Entity
public class Employee {
@Id private int id;
@ManyToOne
private Department department;
}
158. Many-to-one mappings
A many-to-one mapping is defined by annota2ng the source en)ty
with the @ManyToOne annota2on
@Entity
public class Employee {
@Id private int id;
@ManyToOne
private Department department;
}
159. One-to-many mappings
In a one-to-many mapping, the owner of the rela2onship is the
target en2ty
@Entity
public class Department {
@Id private int id;
@OneToMany(mappedBy="department")
private List<Employee> employees;
}
160. One-to-many mappings
Therefore, the @OneToMany annota,on must come with the
mappedBy a3ribute
@Entity
public class Department {
@Id private int id;
@OneToMany(mappedBy="department")
private List<Employee> employees;
}
161. One-to-many mappings
The mappedBy a&ribute indicates that the owning side resides at
the other end of the rela5onship
@Entity
public class Department {
@Id private int id;
@OneToMany(mappedBy="department")
private List<Employee> employees;
}
162. One-to-one mappings
In a one-to-one mapping, the owner can be either the source or
the target en4ty
@Entity
public class Employee {
@Id private int id;
@OneToOne
private ParkingSpace parkingSpace;
}
163. One-to-one mappings
A one-to-one mapping is defined by annota2ng the owner en'ty
with the @OneToOne annota2on
@Entity
public class Employee {
@Id private int id;
@OneToOne
private ParkingSpace parkingSpace;
}
164. One-to-one mappings
If the one-to-one mapping is bidirec4onal, the inverse side of the
rela4onship needs to be specified as well
@Entity
public class ParkingSpace {
@Id private int id;
@OneToOne(mappedBy="parkingSpace")
private Employee employee;
}
165. One-to-one mappings
In the non-owner en+ty, the @OneToOne annota+ons must come
with the mappedBy element
@Entity
public class ParkingSpace {
@Id private int id;
@OneToOne(mappedBy="parkingSpace")
private Employee employee;
}
166. Many-to-many mappings
In a many-to-many mapping there is no join column. The only way
to implement such a mapping is by means of a join table
┌─────────────┬─────────────┐
│ employeeId │ projectId │
├─────────────┼─────────────┤
│ 12 │ 7 │
├─────────────┼─────────────┤
│ 1 │ 33 │
├─────────────┼─────────────┤
│ 76 │ 7 │
└─────────────┴─────────────┘
167. Many-to-many mappings
Therefore, we can arbitrarily specify as owner either the source or
the target en6ty
@Entity
public class Employee {
@Id private int id;
@ManyToMany
private List<Project> projects;
}
168. Many-to-many mappings
If the many-to-many mapping is bidirec5onal, the inverse side of
the rela5onship needs to be specified as well
@Entity
public class Project {
@Id private int id;
@ManyToMany(mappedBy="projects")
private List<Employee> employees;
}
169. Many-to-many mappings
In the non-owner en+ty, the @ManyToMany annota+on must come
with the mappedBy element
@Entity
public class Project {
@Id private int id;
@ManyToMany(mappedBy="projects")
private List<Employee> employees;
}
170. Cascading opera.ons
By default, every EntityManager’s opera2on applies only to the
en2ty object supplied as the opera2on argument
171. Cascading opera.ons
The opera)on will not cascade to other en))es that have a
rela)onship with the en)ty that is being operated on
172. Cascading opera.ons
For some opera*ons, this is usually the desired behavior
// we do not want to also delete her department
entityManager.remove(employ);
173. Cascading opera.ons
For some other opera,ons, this is instead an unfortunate
circumstances
// we want to persist also the related department
entityManager.persist(employ);
174. Cascading opera.ons
If a transient en+ty has a rela+onship with another transient en+ty,
the two must be persisted together
175. Manually cascading
A naive approach would be to manually cascade related en33es
Employee emp = new Employee(...);
Department dep = new Department(...);
emp.setDepartment(dep);
entityManager.persist(dep);
entityManager.persist(emp);
176. Manually cascading
This is however inconvenient
Employee emp = new Employee(...);
Department dep = new Department(...);
emp.setDepartment(dep);
entityManager.persist(dep);
entityManager.persist(emp);
177. Manually cascading
We do not want to explicitly persist the Department instance
Employee emp = new Employee(...);
Department dep = new Department(...);
emp.setDepartment(dep);
entityManager.persist(dep);
entityManager.persist(emp);
178. Cascading opera.ons
The cascade a&ribute allows defining when opera5ons such as
persist() should be automa&cally cascaded across rela5onships
@Entity
public class Employee {
@ManyToOne(cascade=CascadeType.PERSIST)
Department department;
}
179. Cascading opera.ons
The cascade a&ribute allows defining when opera5ons such as
persist() should be automa&cally cascaded across rela5onships
Employee emp = new Employee(...);
Department dep = new Department(...);
emp.setDepartment(dep);
entityManager.persist(emp); // dep gets persisted as well
180. Cascading opera.ons
You need to be sure that the Department instance has been set
on the Employee instance before persist()-ing the la4er
Employee emp = new Employee(...);
Department dep = new Department(...);
emp.setDepartment(dep);
entityManager.persist(emp); // dep gets persisted as well
181. Cascading opera.ons
The cascade a&ribute accepts several possible values coming
from the CascadeType enumera4on
• PERSIST, REFRESH, REMOVE, MERGE and DETACH
182. Cascading opera.ons
The constant ALL is a shorthand for declaring that all five
opera4ons should be cascaded
@Entity
public class Employee {
@ManyToOne(cascade=CascadeType.ALL)
Department department;
}
183. Cascading opera.ons
As with rela,onships, cascade se3ngs are unidirec(onal
@Entity
public class Employee {
@Id private int id;
@ManyToOne(cascade=CascadeType.PERSIST)
Department department;
}
@Entity
public class Department {
@Id private int id;
@OneToMany(cascade=CascadeType.PERSIST, mappedBy="department")
private List<Employee> employees;
}
184. Cascading opera.ons
They must be explicitly set on both sides of a rela3onship if the
same behavior is intended for both situa3ons
@Entity
public class Employee {
@Id private int id;
@ManyToOne(cascade=CascadeType.PERSIST)
Department department;
}
@Entity
public class Department {
@Id private int id;
@OneToMany(cascade=CascadeType.PERSIST, mappedBy="department")
private List<Employee> employees;
}
185. Lazy loading
In many real situa.ons, certain por.ons of an en.ty will be seldom
accessed
+------------+ +--------------+
| | | |
| Employee <-------------> Department |
| | * 1 | |
+------------+ +--------------+
186. Lazy loading
Lazy loading is a design pa*ern that allows deferring the fetching
of data un4l they are actually needed
187. Lazy loading
The employees a&ribute may not be loaded each 3me a
Department is loaded
@Entity
public class Department {
@Id private int id;
@OneToMany(fetch=FetchType.LAZY, ...)
private List<Employee> employees;
}
188. Lazy loading
Lazy loading can improve performance because of the reduced
amount of SQL that gets executed
189. Lazy loading
In case of bidirec.onal rela.onships, the fetch mode might be lazy
on one side but eager on the other
@Entity
public class Employee {
@Id private int id;
@ManyToOne
Department department;
}
@Entity
public class Department {
@Id private int id;
@OneToMany(mappedBy="department", fetch=FetchType.LAZY)
private List<Employee> employees;
}
190. Lazy loading
As a ma&er of fact, rela/onships are o4en accessed in different
ways depending on the direc/on from which naviga/on occurs
@Entity
public class Employee {
@Id private int id;
@ManyToOne
Department department;
}
@Entity
public class Department {
@Id private int id;
@OneToMany(mappedBy="department", fetch=FetchType.LAZY)
private List<Employee> employees;
}
191. Lazy loading
Note that the direc,ve to lazily fetch an a/ribute is meant only to
be a hint to the persistence provider
@Entity
public class Department {
@Id private int id;
@OneToMany(fetch=FetchType.LAZY, ...)
private List<Employee> employees;
}
192. Lazy loading
The provider is not required to honor the request, as the behavior
of the en4ty is not compromised if data get eagerly loaded
@Entity
public class Department {
@Id private int id;
@OneToMany(fetch=FetchType.LAZY, ...)
private List<Employee> employees;
}
193. Lazy loading
The converse is not true: specifying that an a3ribute be eagerly
fetched might be cri9cal to access the en9ty once detached
@Entity
public class Employee {
@Id private int id;
@ManyToOne
Department department;
}
197. Java Persistence Query Language
The Java Persistence Query Language (JPQL) is a pla0orm-
independent object-oriented query language defined as part of the
JPA specificaBon
198. Java Persistence Query Language
The main difference with SQL is that
• JPQL operates on classes and objects
• SQL operates on tables, columns and rows
199. Java Persistence Query Language
Therefore, the outcome of a JPQL query is a collec%on of objects,
rather than a list of tuples
200. Java Persistence Query Language
Note that JPQL syntax looks like SQL, but JPQL is not SQL
SELECT e FROM Employee e
201. JQPL statements
JPQL supports three types of statements
• SELECT statements retrieve en,,es or en,ty-related data
• UPDATE statements update one or more en,,es
• DELETE statements delete one or more en,,es
202. FROM clause
The FROM clause defines the domain for the query, that is, the
en55es that will be used in the query
SELECT e FROM Employee e
203. FROM clause
Employee is the domain that we want to query, and e is intended
as an iden(fier of type Employee
SELECT e FROM Employee e
204. FROM clause
Iden%fiers can be used in other clauses of the same query (e.g.,
WHERE clauses)
SELECT e
FROM Employee e
WHERE e.name = "Jon Snow"
205. Path Expressions
Given an iden)fier, we can use dot nota'on to access a specific
field of the en)ty
SELECT e
FROM Employee e
WHERE e.phones is NOT EMPTY
207. Path Expressions
Path expressions are commonly used in
• WHERE clauses so as to narrow the domain for a query
• ORDER BY clauses so as to order the retrieved result set
208. JOIN operator
In many common situa-ons, there is the need to join two or more
en--es based on their rela-onship
209. JOIN operator
To this end, joins can be specified either in the WHERE clause...
SELECT p.number
FROM Employee e, Phone p
WHERE e = p.employee AND e.department.name = 'NA42'
210. JOIN operator
...or in the FROM clause by means of the JOIN operator
SELECT p.number
FROM Employee e JOIN e.phones p
WHERE e.department.name = 'NA42'
212. Query API
The required steps to create a JPA query are similar to those of a
tradi7onal JDBC query
┌────────────────────────────────┬─────────────────────────────────────────┐
│///////////// JDBC /////////////│/////////////// Query API //////////////│
├────────────────────────────────┼─────────────────────────────────────────┤
│ Obtain a database connection │ Obtain an EntityManager instance │
├────────────────────────────────┼─────────────────────────────────────────┤
│ Create a query statement │ Create a query statement │
├────────────────────────────────┼─────────────────────────────────────────┤
│ Execute the query │ Execute the query │
├────────────────────────────────┼─────────────────────────────────────────┤
│ Retrieve the result (tuples) │ Retrieve the result (objects) │
└────────────────────────────────┴─────────────────────────────────────────┘
213. Query API
The Query API supports two types of queries
• Named queries, which are meant to be stored and reused
• Dynamic queries, which are created and executed on the fly
214. Named query
Named query are stored on the en'ty
@Entity
@NamedQuery(
name = "findSalaries",
query = "SELECT e.salary FROM Employee")
public class Employee { ... }
215. Named query
Any query that is used in mul$ple components of the applica4on is
a candidate for a named query
@Entity
@NamedQuery(
name = "findSalaries",
query = "SELECT e.salary FROM Employee")
public class Employee { ... }
216. Named query
Named queries can enhance performance because they are
prepared once and then efficiently reused
@Entity
@NamedQuery(
name = "findSalaries",
query = "SELECT e.salary FROM Employee")
public class Employee { ... }
217. Named query
Named query are globally scoped and instan/ated by name
TypedQuery<Integer> query = entityManager
.createNamedQuery("findSalaries");
218. Named query
That is, named query instances can be created from any
component that can access the persistence unit
TypedQuery<Integer> query = entityManager
.createNamedQuery("findSalaries");
219. Named query
Consequently, a named queries must have a unique name in the
whole persistence unit
@Entity
@NamedQuery(name = "findSalaries", query = "...")
public class Employee { ... }
220. Dynamic query
Dynamic queries are created at run 0me, and they are normally
used when the query depends on the context
String stmt = "SELECT e FROM Employee e WHERE e.name = :empName";
TypedQuery<Employee> query = entityManager.createQuery(stmt);
221. Dynamic query
A dynamic query can be created wherever the EntityManager is
available. The only requirement is to pass a valid JPQL statement
String stmt = "SELECT e FROM Employee e WHERE e.name = :empName";
TypedQuery<Employee> query = entityManager.createQuery(stmt);
222. Execu&ng queries
A TypedQuery object represents a query instance
String stmt = "SELECT e FROM Employee e WHERE e.name = :empName";
TypedQuery<Employee> query = entityManager.createQuery(stmt);
223. Execu&ng queries
The TypedQuery interface defines several methods for
parameterizing and execu.ng the query
┌────────────────────────────────────────────┬─────────────────────────────────────────┐
│///////////// Method signature /////////////│////////////// Description //////////////│
├────────────────────────────────────────────┼─────────────────────────────────────────┤
│ public List getResultList(); │ Retrieves the result set │
├────────────────────────────────────────────┼─────────────────────────────────────────┤
│ public │ Sets the maximum number of objects to be│
│ TypedQuery<T> setMaxResults(int maxResult);│ retrieved │
├────────────────────────────────────────────┼─────────────────────────────────────────┤
│ public │ │
│ TypedQuery<T> setParameter(int position, │ Sets the value for a positional │
│ Object value); │ parameter │
│ │ │
├────────────────────────────────────────────┼─────────────────────────────────────────┤
│ public │ │
│ TypedQuery<T> setParameter(String name, │ Sets the value for a named parameter │
│ Object value); │ │
└────────────────────────────────────────────┴─────────────────────────────────────────┘
224. Parameters
The number of en,,es retrieved in a query may be limited by
specifying a WHERE clause, which can be parameterized
SELECT e.salary
FROM Employee e
WHERE e.name = :empName
225. Parameters
In JPA, There exist two types of parameters
• Posi&onal parameters
• Named parameters
226. Parameters
Before execu*ng a query, all parameters need to be set
SELECT e.salary
FROM Employee e
WHERE e.name = :empName
227. Parameters
This can be done using the TypedQuery’s setParameter()
method
SELECT e.salary
FROM Employee e
WHERE e.name = :empName
228. Posi%onal parameters
Posi%onal parameters are iden(fied by number
String stmt = "SELECT i FROM Item i WHERE i.initialPrice = ?1";
TypedQuery<Item> query = em.createQuery(stmt);
query.setParameter(1, 100.00);
List<Item> items = query.getResultList();
229. Named parameters
Named parameters are iden(fied by label
String stmt = "SELECT i FROM Item i WHERE i.initialPrice = :price";
TypedQuery<Item> query = em.createQuery(stmt);
query.setParameter("price", 100.00);
List<Item> items = query.getResultList();
231. The problem with the Query API
The Query API cannot verify the correctness of a JPQL query
before its actual execu:on
// This will compile despite the incorrect JQPL query
TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee t");
232. The problem with the Query API
We would much prefer to let the compila(on fail in the presence
of incorrect JQPL queries
233. Criteria API
The Criteria API provides a way of crea6ng type-safe queries, i.e.,
queries the compiler can check at compile-2me
234. Crea%ng a new query
The steps for crea-ng a Criteria API-based query are
1. Obtaining a CriteriaBuilder object
2. Using this instance to compose a CriteriaQuery object
3. Execu9ng the query
235. Crea%ng a new query
The CriteriaQuery instance represents the query we would like
to execute
236. Crea%ng a new query
The CriteriaBuilder interface provides methods for all
keywords, operators, and func8ons from JPQL
public interface CriteriaBuilder {
CriteriaQuery<T> createQuery(Class<T> resultClass);
Predicate and(Expression<Boolean> x, Expression<Boolean> y);
Predicate or(Expression<Boolean> x, Expression<Boolean> y);
Predicate isNotNull(Expression<?> x);
...
}
237. Crea%ng a new query
That is, the CriteriaBuilder is a factory for all the individual
pieces of the query
public interface CriteriaBuilder {
CriteriaQuery<T> createQuery(Class<T> resultClass);
Predicate and(Expression<Boolean> x, Expression<Boolean> y);
Predicate or(Expression<Boolean> x, Expression<Boolean> y);
Predicate isNotNull(Expression<?> x);
...
}
238. Crea%ng a new query
A CriteriaBuilder object can be obtained from an
EntityManager instance
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
239. Crea%ng a new query
Once available, a CriteraBuilder can be used to create
CriteriaQuery objects
CriteriaQuery<Employee> c = cb.createQuery(Employee.class);
240. Crea%ng a new query
To ensure type-safety, the CriteriaQuery's type parameter
should be set to the result type of the query
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> c = cb.createQuery(Employee.class);
241. Root object
Every CriteriaQuery defines at least one Root object, whose
role is analogous to that of an iden%fier in a JPQL query
Root<Employee> e = c.from(Employee.class);
c.select(e);
242. Root object
Every CriteriaQuery defines at least one Root object, whose
role is analogous to that of an iden%fier in a JPQL query
SELECT e
FROM Employee e
243. Root object
Like JPQL iden+fiers, Root objects are commonly used in SELECT
and WHERE clauses
Root<Employee> e = c.from(Employee.class);
c.select(e);
244. Canonical metamodel
The Criteria API ensures type-safety by means of a canonical
metamodel
@StaticMetamodel(Employee.class) public class Employee_ {...}
@StaticMetamodel(Department.class) public class Department_ {...}
@StaticMetamodel(Project.class) public class Project_ {...}
245. Canonical metamodel
The canonical metamodel of a persistence unit is a descrip1on of
the persistent type, state, and rela1onships of en11es
@StaticMetamodel(Employee.class) public class Employee_ {...}
@StaticMetamodel(Department.class) public class Department_ {...}
@StaticMetamodel(Project.class) public class Project_ {...}
246. Canonical metamodel
In prac(ce, the canonical metamodel is implemented as a series of
classes that mirror the en((es in the domain model
@StaticMetamodel(Employee.class) public class Employee_ {...}
@StaticMetamodel(Department.class) public class Department_ {...}
@StaticMetamodel(Project.class) public class Project_ {...}
247. Canonical metamodel
Such metamodel classes provide access to metadata about the
associated domain class
@StaticMetamodel(Employee.class)
public class Employee_ {
public static volatile SingularAttribute<Employee, Integer> id;
public static volatile SingularAttribute<Employee, String> name;
public static volatile SingularAttribute<Employee, String> salary;
public static volatile SingularAttribute<Employee, Department> dept;
public static volatile SingularAttribute<Employee, Address> address;
public static volatile CollectionAttribute<Employee, Project> project;
}
248. Canonical metamodel
For each en*ty E, there should exist a metamodel class E_ in the
same package
@StaticMetamodel(Employee.class)
public class Employee_ {
public static volatile SingularAttribute<Employee, Integer> id;
public static volatile SingularAttribute<Employee, String> name;
public static volatile SingularAttribute<Employee, String> salary;
public static volatile SingularAttribute<Employee, Department> dept;
public static volatile SingularAttribute<Employee, Address> address;
public static volatile CollectionAttribute<Employee, Project> project;
}
249. Canonical metamodel
Each metamodel class must be annotated with the
@StaticMetamodel annota2on
@StaticMetamodel(Employee.class)
public class Employee_ {
public static volatile SingularAttribute<Employee, Integer> id;
public static volatile SingularAttribute<Employee, String> name;
public static volatile SingularAttribute<Employee, String> salary;
public static volatile SingularAttribute<Employee, Department> dept;
public static volatile SingularAttribute<Employee, Address> address;
public static volatile CollectionAttribute<Employee, Project> project;
}
250. Path expressions
Root objects and metamodel classes are employed together to
form path expressions
Root<Employee> e = c.from(Employee.class);
c.select( e.get(Employee_.department).get(Department_.id) );
251. Path expressions
The Root object and the metamodel classes are employed together
to form path expressions
SELECT e.department.id
FROM Employee e
252. JOIN opera'on
Joins can be performed by calling the join() method on the Root
object
Root<Employee> e = c.from(Employee.class);
Join<Employee, Phone> p = e.join(Employee_.phones);
c.select(p.get(Phone_.number))
c.where(cb.equal(e.get(Employee_.name), "Jon Snow"));
253. JOIN opera'on
Joins can be performed by calling the join() method on the Root
object
SELECT p.number
FROM Employee e JOIN e.phones p
WHERE e.name = "Jon Snow"
254. JOIN opera'on
Note that the resul,ng Join object behaves like a Root object,
meaning that joins can be cascaded
255. WHERE clause
WHERE clauses can be used to narrow the result set
Root<Employee> e = c.from(Employee.class);
c.select(e);
c.where(cb.equal(e.get(Employee_.name), "Jon Snow"));
256. WHERE clause
WHERE clauses can be used to narrow the result set
SELECT e
FROM Employee e
WHERE e.name = "Jon Snow"
257. WHERE clause
Each condi*on in a WHERE clause is expressed as a Predicate
instance
// Incremental construction
Predicate predicates = cb.conjunction();
predicates = cb.and(predicates, cb.equal(e.get(Employee_.name), "Jon Snow"));
predicates = cb.and(predicates, cb.equal(e.get(Employee_.dept).get(Department_.id), 7));
c.where(predicates);
258. WHERE clause
Predicates can be combined by means of AND or OR operators
// Incremental construction
Predicate predicates = cb.conjunction();
predicates = cb.and(predicates, cb.equal(e.get(Employee_.name), "Jon Snow"));
predicates = cb.and(predicates, cb.equal(e.get(Employee_.dept).get(Department_.id), 7));
c.where(predicates);
259. WHERE clause
Predicates can be combined by means of AND or OR operators
// List-based construction
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(e.get(Employee_.name), "Jon Snow"));
predicates.add(cb.equal(e.get(Employee_.dept).get(Department_.id), 7));
Predicate[] predArray = predicates.toArray(new Predicate[predicates.size()]);
c.where(cb.and(predArray));
260. WHERE clause
Predicates can be combined by means of AND or OR operators
SELECT e
FROM Employee e
WHERE e.name = "Jon Snow" AND
d.department.id = 7
261. Defining parameters
To parameterize queries using the Criteria API, a
ParameterExpression object must be created
ParameterExpression<String> deptName = cb.parameter(String.class, "deptName");
262. Execu&ng queries
Once the query is composed, it is possible to obtain a
TypedQuery object out of a CriteriaQuery object
TypedQuery<Employee> q = entityManager.createQuery(c);
263. Execu&ng queries
As with any TypedQuery, parameters need to be provided before
the actual execu9on
TypedQuery<Employee> q = em.createQuery(c);
q.setParameter("deptName", "NA42")
return q.getResultList();
265. References
• Java Community Process, JPA 2.1 specifica:on
• Hibernate Community Documenta:on, EntityManager
• Hibernate Community Documenta:on, Transac:ons and
Concurrency
• Wikipedia, Data Access Object
• SpringSource, Spring Framework Reference
266. References
• Hibernate Wiki, Data Access Objects
• Hibernate Wiki, Open Session in View pa9ern
• Hibernate Community Documenta>on, Metamodel
• Hibernate Community Documenta>on, Criteria Queries
• OpenJPA, JPA Concepts
267. References
• M. Keith, M. Schincariol, Pro JPA 2, Mastering The Java
Persistence API, Apress Media LLC
• D. Panda et al., EJB3 In AcCon, Manning PublicaCons
• C. Baver, G.King, Java Persistence With Hibernate, Manning
PublicaCons
• S. Guruzu, G. Mak, Hibernate Recipes - A Problem-SoluCon
Approach, Apress Media LLC
268. References
• A.L. Rubinger, B.Burke, Enterprise JavaBeans 3.1, O’Reilly Media
• R.M. Reese, EJB 3.1 Cookbook, Packt Publishing
• Craig Walls, Spring in AcGon (3rd EdiGon), Manning PublicaGons
• Willie Wheeler, Spring in PracGce, Manning PublicaGons
269. Topics not covered
• Physical annota.ons
• Cascading policies other than PERSIST
• Vender-based APIs (e.g., Hibernate APIs)
• Advanced JPQL and Criteria API-based queries
• Long units of work