[go: up one dir, main page]

0% found this document useful (0 votes)
15 views151 pages

Orm Jpa

The document provides an overview of the Java Persistence API (JPA) and Object Relational Mapping (ORM), highlighting key concepts such as JDBC, entity classes, and transaction management. It explains how JPA facilitates database interactions by mapping Java classes to database tables and managing CRUD operations through the EntityManager. Additionally, it discusses the architecture of JDBC, the role of ORM frameworks, and the history of JPA development in the Java ecosystem.

Uploaded by

joel.desmul
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views151 pages

Orm Jpa

The document provides an overview of the Java Persistence API (JPA) and Object Relational Mapping (ORM), highlighting key concepts such as JDBC, entity classes, and transaction management. It explains how JPA facilitates database interactions by mapping Java classes to database tables and managing CRUD operations through the EntityManager. Additionally, it discusses the architecture of JDBC, the role of ORM frameworks, and the history of JPA development in the Java ecosystem.

Uploaded by

joel.desmul
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 151

Java Persistence API (JPA)

and Object Relational Mapping

Sadegh Aliakbary
Table of Contents
 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)
JPA www.asta.ir 2
Getting Ready

JPA www.asta.ir 3
Start the Exercise Project
 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…

JPA www.asta.ir 4
Java Database Connectivity (JDBC)

JPA www.asta.ir 5
JDBC
 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
JPA www.asta.ir 6
JDBC Driver
 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

JPA www.asta.ir 7
The Architecture of JDBC

JPA www.asta.ir 8
JDBC Example
//Class.forName("com.mysql.jdbc.Driver"); Now: Optional
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"));
}
}
JPA www.asta.ir 9
JDBC
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
JPA www.asta.ir 10
‘Statement’ interface
 ‘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.
JPA www.asta.ir 11
Commit & Rollback
 The ‘auto-commit’ property for the ‘Connection’ object
 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

JPA www.asta.ir 12
AutoCommit
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();
}
JPA www.asta.ir 13
ResultSet Example
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 14
Overview of JDBC Concepts
 JDBC Driver
 Connection
 Statement
 ResultSet
 Commit & rollback

JPA www.asta.ir 15
JDBC Pros and Cons
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

JPA www.asta.ir 16
JDBC Exercise
 Implement save and load methods in ContactDAO
 Using JDBC

 Add “age” field to ContactEntity


 Revise the ContactDAO class

 How much effort is needed?!

JPA www.asta.ir 17
Other Concepts in JDBC
 PreparedStatement
 And CallableStatement

 RowSet
 SQL Injection

JPA www.asta.ir 18
Object Relational Mapping

JPA www.asta.ir 19
What is ORM?
 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

OO
ORM Relational
Programming
Framework Database
Language
JPA www.asta.ir 20
ORM – Example

JPA www.asta.ir 21
Simple Scenarios (Pseudocode)
Person person = new Person(“Ali Alavi”, 22, “0078934563”);
orm.save(person);

Person[] people = orm.loadAll(Person.class);

query = “SELECT from Student where instructor.dep.name=‘ce’ ”;


Entity[] found = orm.find(query);
JPA www.asta.ir 22
How does an ORM framework work?
 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

JPA www.asta.ir 23
How does an ORM framework work? (cont’d)
 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
JPA www.asta.ir 24
ORM Technologies
 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)
 …
JPA www.asta.ir 25
ORM in Java: Products and History
 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


JPA www.asta.ir 26
ORM in Java: Products and History (2)
 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

JPA www.asta.ir 27
History
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

JPA www.asta.ir 28
Introduction to JPA

JPA www.asta.ir 29
About JPA
 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
JPA www.asta.ir 30
Entities in JPA
 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)
JPA www.asta.ir 31
The Minimal JPA Entity: Class Definition
 Must be indicated as an Entity
 @Entity annotation on the class:

@Entity
public class Employee {

}

JPA www.asta.ir 32
The Minimal JPA Entity: Primary Key
 Must have a persistent identifier (primary key):
@Entity
public class Employee {
@Id int id;

public int getId() {


return id;
}
public void setId(int id) {
this.id = id;
}
}
JPA www.asta.ir 33
Primary Key (Id) Definitions
 Simple id – single field/property
@Id int id;

 Compound id – multiple fields


@Id String firstName;
@Id String lastName;

JPA www.asta.ir 34
Primary Key Identifier Generation
 Identifiers can be generated in the database
 @GeneratedValue on the ID field

@Id @GeneratedValue int id;

 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)
JPA www.asta.ir 35
Simple Column Mappings
 Mapping a class field to a database column:
@Entity
public class Message {
private String message;
public void setMessage(String msg) { message = msg; }
public String getMessage() { return message; }
}

 A column name can be explicitly given:


@Column(name="SAL")
private double salary;
JPA www.asta.ir 36
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;
...
}
JPA www.asta.ir 37
Persistence Contexts and
EntityManager

Manipulating Database Entities


JPA www.asta.ir 38
Persistence Context (PC)
 The persistence context (PC)
 Holds a set of “managed” entity 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

JPA www.asta.ir 39
The EntityManager
 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

JPA www.asta.ir 40
Persistence Context (PC) and Entities

Application Persistence
Context
EntityManager
MyEntity A

MyEntity C
MyEntity a MyEntity B
MyEntity b

Entities

Entity
state

JPA www.asta.ir 41
Overview of PC
 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
JPA www.asta.ir 42
Operations on Entities
 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)

JPA www.asta.ir 43
EntityManager.flush() method
 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
JPA www.asta.ir 44
Other EntityManager Operations
 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

JPA www.asta.ir 45
EntityManager.persist()
 Insert a new entity instance into the database

 Save the persistent state of the entity and any owned relationship
references
 Entity instance becomes managed
public Customer createCustomer(int id, String name) {
Customer cust = new Customer(id, name);
entityManager.persist(cust);
return cust;
}
JPA www.asta.ir 46
Updating an Entity
 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

JPA www.asta.ir 47
find() and remove()
 find()
 Obtain a managed entity instance (SQL SELECT by PK)

 Return null if not found

 remove()
 Delete a managed entity by PK

public void removeCustomer(Long custId) {


Customer cust = entityManager.find(Customer.class, custId);
entityManager.remove(cust);
}
JPA www.asta.ir 48
Using the Persistence API

Creating Standalone JPA Applications

JPA www.asta.ir 49
EntityManagerFactory Class
 javax.persistence.EntityManagerFactory
 Obtained by the Persistance
 Creates EntityManager for a named
persistence unit or configuration
 In Java SE environment the persistence unit configuration is
defined in the META-INF/persistence.xml file

JPA www.asta.ir 50
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 51
Automatic Table Generation
 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

JPA www.asta.ir 52
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>

 Since JPA 2.1 (2013)


 Possible values:
 none, create, drop-and-create, …
JPA www.asta.ir 53
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 www.asta.ir 54
JPA Configuration in Spring
JPA Configuration with 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 www.asta.ir 56
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 id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
</bean> <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>
JPA <tx:annotation-driven /> www.asta.ir 57
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 58
Exercise on JPA and Spring
 Review the Layers
 Review the Spring configurations

JPA www.asta.ir 59
DAO and Generic DAO Patterns

JPA www.asta.ir 60
Layering
 Enterprise applications usually are
Presentation Layer
divided into logical layers
 Three-layer Service Layer
 UI, Business Logic, Data
Manager Layer
 Four-Layer
 UI, Service, Business Logic, Data
DAO Layer
 Data Layer: Collection of classes related to
data access (DAO layer) DB
JPA www.asta.ir 61
Data Access Object Pattern (DAO)

(Entity)

JPA www.asta.ir 62
DAO
 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

JPA www.asta.ir 63
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 64
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 65
Generic DAO
 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

JPA
 and implement the DAO interface
www.asta.ir 66
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 67
Exercise on JPA Basics
 Implement find method in ContactDAO
 Using JPA

JPA www.asta.ir 68
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
Using Spring @Transactional
 With Spring @Transactional, the transaction management is made simple

@Transactional
public void businessLogic() {
... use entity manager inside a transaction ...
}

 This declarative transactions are much more convenient and readable


 To use declarative transactions, we should configure it:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven />

JPA www.asta.ir 71
Layering and Transactions
 Methods of which layer become transactional?
Presentation Layer
 Manager
 Why? Service Layer

Manager Layer

DAO Layer

DB
JPA www.asta.ir 72
Exercise on JPA
 Implement save method in ContactDAO
 Using JPA
 Note to Transactions
 Add “email” field to ContactEntity
 Revise the ContactDAO class
 How much effort is needed?!
 Compare it with the JDBC approach
 Simulate an “account-transfer” method in Manager
 Which invokes two dao methods in a transactional method
 Test the transactionality! Does it roll-back?
JPA www.asta.ir 73
JPA Queries
Using JPQL

JPA www.asta.ir 74
JPA Queries
 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 www.asta.ir 75
JPA Query API
 Query instances are obtained from factory methods on
EntityManager, e.g.
Query query = entityManager.createQuery(
"SELECT e from Employee e");

 JPA query API:


 getResultList() – execute query returning multiple results

 getSingleResult() – execute query returning single result

 executeUpdate() – execute bulk update or delete


JPA www.asta.ir 76
JPA Query API (2)
 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 www.asta.ir 77
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 78
Dynamic Queries – Example
 Use createQuery() factory method at runtime
 Pass in the JPQL query string

 Get results by getResultList() / getSingleResult()


public List findAll(String entityName){
return entityManager.createQuery(
"select e from " + entityName + " e")
.setMaxResults(100)
.getResultList();
}

JPA www.asta.ir 79
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 80
Named Queries
 Named queries are once defined and invoked later many times
@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 81
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 82
Exercise on JPA
 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||'%'
JPA www.asta.ir 83
Mapping Tables to Classes by
Annotations
ORM Mappings

JPA www.asta.ir 84
Object / Relational Mapping
 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

JPA www.asta.ir 85
Simple Mappings
 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
JPA www.asta.ir 86
Simple Mappings (Annotations)

@Entity
public class Customer {
CUSTOMER
@Id
ID NAME CREDIT PHOTO
int id;
@Basic @Column(name="name")
String name;
@Basic @Column(name="CREDIT")
int creditRating;
@Lob
Image photo;
}
JPA www.asta.ir 87
Simple Mappings (XML)
 It is also possible to describe mappings by XML files
 But we focus on annotation-based mappings
<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 88
Relationship Mappings
 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
JPA www.asta.ir 89
Many-To-One Mapping (Annotations)

@Entity
public class Sale { SALE
@Id ID … CUST_ID
int id;
...
@ManyToOne
@JoinColumn(name="CUST_ID") CUSTOMER
Customer cust; ID …
}

JPA www.asta.ir 90
One-To-Many Mapping (Attributes)
@Entity
public class Customer {
CUSTOMER
@Id ID …
int id;
@OneToMany(mappedBy="cust")
Set<Sale> sales;
}
SALE
@Entity
public class Sale { ID … CUST_ID

@Id
int id;
@ManyToOne
Customer cust;
}
JPA www.asta.ir 91
Many-To-Many Example @Entity
public class Project {
@Entity @Id
public class Employee { @Column(name="ID")
@Id private long id;
@Column(name="ID") ...
private long id; @ManyToMany(mappedBy="projects")
... private List<Employee> employees;
@ManyToMany ...
@JoinTable( }
name="EMP_PROJ",
joinColumns=@JoinColumn(name="EMP_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="PROJ_ID", referencedColumnName="ID"))
private List<Project> projects;
.....
}
JPA www.asta.ir 92
Bi-directional and Unidirectional Relationships
 The relationship may be unidirectional
 If one end does not need to use the relationship
 Example: Unidirectional ManyToMany relationship:
@Entity 0* 0*

public class Employee{ Employee Project


@Id
private Integer id;

@JoinTable(name = "PROJECT_EMPLOYEE",
joinColumns={@JoinColumn(name="EMPLOYEES_ID", @Entity
referencedColumnName="ID")},inverseJoinColumns public class Project {
={@JoinColumn(name="PROJECTS_ID", @Id
referencedColumnName = "ID")}) private Integer id;
@ManyToMany ...
private List<Project> projectList; }
...
}
JPA www.asta.ir 93
Lazy Collection Fetching
 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)
JPA www.asta.ir 94
Lazy Fetching Example

@Entity
public class ProductEntity {
... @ManyToMany(fetch=FetchType.LAZY)
@ManyToMany(fetch=FetchType.EAGER)
private List<CategoryEntity> categories;
}

JPA www.asta.ir 95
Cascade Strategies
Cascading Actions
 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

JPA www.asta.ir 97
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
Cascade Types:
 ALL
 Cascade all operations
 PERSIST
 Cascade persist operation
 MERGE
 Cascade merge operation
 REMOVE
 REFRESH
 DETACH
JPA www.asta.ir 99
Exercise
 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)
JPA www.asta.ir 100
Exercise (cont’d)
 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

JPA www.asta.ir 101


Bean Validation
Introduction to 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.

JPA www.asta.ir 103


Built-In Bean Validation Constraints
Constraint Description Example

@AssertFalse
@AssertFalse The value of the field or property must be false.
boolean isUnsupported;
@AssertTrue
@AssertTrue The value of the field or property must be true.
boolean isActive;
The value of the field or property must be a decimal
@DecimalMax("30.00")
@DecimalMax value lower than or equal to the number in the value
BigDecimal discount;
element.
The value of the field or property must be a decimal
@DecimalMin("5.00")
@DecimalMin value greater than or equal to the number in the value
BigDecimal discount;
element.

JPA www.asta.ir 104


Built-In Bean Validation Constraints
Constraint Description Example

The value of the field or property must be a number within a specified


@Digits(integer=6
range. The integer element specifies the maximum integral digits for the
@Digits ,fraction=2)
number, and the fraction element specifies the maximum fractional digits
BigDecimal price;
for the number.

@Future
@Future The value of the field or property must be a date in the future.
Date eventDate;

The value of the field or property must be an integer value lower than or @Max(10)
@Max
equal to the number in the value element. int quantity;

The value of the field or property must be an integer value greater than or @Min(5)
@Min
equal to the number in the value element. int quantity;

JPA www.asta.ir 105


Built-In Bean Validation Constraints
Constraint Description Example

@NotNull
@NotNull The value of the field or property must not be null.
String username;
@Null
@Null The value of the field or property must be null.
String unusedString;
@Past
@Past The value of the field or property must be a date in the past.
Date birthday;
@Pattern(regexp="\\(\\d{3}\\)\\d
The value of the field or property must match the regular
@Pattern {3}-\\d{4}")
expression defined in the regexp element.
String phoneNumber;

JPA www.asta.ir 106


Built-In Bean Validation Constraints
Constraint Description Example

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(min=2, max=240)
@Size size of the Collection is evaluated. If the field or property is a Map,
String briefMessage;
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.

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


Validating Constructors and Methods

public class Employee {


...
public Employee(@NotNull String name) { ... }

public void setSalary(


@NotNull
@Digits(integer = 6, fraction = 2) BigDecimal salary,
@NotNull
String currencyType) {

}
...
}

JPA www.asta.ir 109


Summary
 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

JPA www.asta.ir 110


Exercise
 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

JPA www.asta.ir 111


Managed vs Detached

JPA www.asta.ir 112


Life cycle of Entity

JPA www.asta.ir 113


Managed Objects
 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().
JPA www.asta.ir 114
Detached Objects
 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

JPA www.asta.ir 115


Entities Lifecycle

merge() – synchronize the state of


JPA detached entity with the PC www.asta.ir 117
merge()
 Merges the state of detached entity into a managed copy of the
detached entity
 Returned entity has a different Java identity than the detached
entity

public Customer storeUpdatedCustomer(Customer cust) {


return entityManager.merge(cust);
}

JPA www.asta.ir 118


Life cycle of Entity
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.
JPA www.asta.ir 119
Life cycle of Entity
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.

JPA www.asta.ir 120


When will the JPA Entities become Detached?
 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
JPA www.asta.ir 121
Criteria APIs
Criteria API
 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
JPA www.asta.ir 123
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.

JPA www.asta.ir 124


The First Example
 Consider this simple Criteria query:
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();

 returns all instances of the User entity in the data source


 The equivalent JPQL query is: SELECT u FROM User u

JPA www.asta.ir 125


JPQL vs Criteria API, an Example:
 With JPQL:
List<User> users =
entityManager.createQuery("select e from User e").getResultList();
 With criteria API:
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
JPQL may look simpler, but criteria API
www.asta.ir
has its own advantages 126
CriteriaBuilder
 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 cb = entityManager.getCriteriaBuilder();
JPA
CriteriaQuery<User> cq = cb.createQuery(User.class);
www.asta.ir 127
CriteriaQuery API
 (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.
JPA www.asta.ir 128
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 129
Other CriteriaQuery API
 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.
JPA www.asta.ir 130
Multiple Selects in One CriteriaQuery
 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
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
JPA www.asta.ir 131
Path Expressions
 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

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


Basic Structure

JPQL Clause Criteria API Method


SELECT select()
FROM from()
WHERE where()
ORDER BY orderBy()
GROUP BY groupBy()
HAVING having()

JPA www.asta.ir 133


Building Expressions

JPQL Operator CriteriaBuilder Method


AND and()
OR or()
NOT not()
= equal()
<> notEqual()
> gt()
>= ge()
< lt()
<= le()

JPA www.asta.ir 134


Building Expressions
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()
JPA
IS NOT NULL isNotNull()
www.asta.ir 135
Building Expressions

JPQL Operator CriteriaBuilder Method


AVG avg()
MIN min()
MAX max()
COUNT count()
COUNT DISTINCT countDistinct()
LOWER lower()
UPPER upper()
CONCAT concat()
CURRENT_TIME currentTime()

JPA www.asta.ir 136


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"));

SELECT e FROM Employee e


WHERE e.address.state IN ('Yazd', 'Qom')

JPA www.asta.ir 137


Join 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"));

 teacher.join("phones") creates a join


 on the collection field named phones

 Variable phones is similar to the p variable


JPA
 that represents join in JPQL www.asta.ir 138
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 139


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();

JPA www.asta.ir 140


The ORDER BY Clause
 The orderBy() method
 Accepts one or more Order objects
 created by the asc() and desc() methods of CriteriaBuilder

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
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));

UPDATE Employee e SET e.salary = e.salary + 5000 WHERE e.salary<1000000

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 143
JPQL vs Criteria API
 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
JPA www.asta.ir 144
Exercise
 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

JPA www.asta.ir 145


Appropriate inheritance
strategies
1- Mapped Superclass Strategy
 It maps each concrete class to its own table
 A mapped superclass is not an entity, and there is no table for it
@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
2- Table per Class Strategy
 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
@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 148
3- Single Table Strategy
 It maps all entities of the inheritance structure to the same table
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = “Publication_Type”)
public abstract class Publication {...}

JPA www.asta.ir 149


4- Joined Strategy
 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.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Publication {
JPA www.asta.ir 150
Choosing a Strategy
 1- Mapped Superclass Strategy
 2- Table per Class Strategy
 3- Single Table Strategy
 4- Joined Strategy

JPA www.asta.ir 151


The End

JPA www.asta.ir 152

You might also like