Está en la página 1de 12

Java Persistence API

Taller de Sistemas de  Provee facilidades de mapeo


objeto/relacional para poder manipular datos
Informacin 2 relacionales dentro de programas Java en
una modalidad orientada a objetos

Clase 5a
EJB3 JPA (Java Persistence API)

Java Persistence API Entidades

 Compuesta por 6 partes  Las entidades u objetos del modelo de


 Requerimientos para los objetos del modelo de dominio soportan las tcnicas estndar para
dominio el desarrollo de sistemas OO
 Metadatos  Herencia
 Encapsulamiento
 API
 Polimorfismo
 Consultas
 Pueden ser creadas con el operador new,
 Modelo del ciclo de vida
como las clases tradicionales
 Callbacks
 No se requiere una interfaz o superclase
especial dentro de EJB3

Entidades Entidades

 Representa un objeto de dominio (liviano)


persistente
 Representa por lo general una tabla en una
base de datos relacional
 Cada instancia de estas entidades,
corresponde a una tupla en dicha tabla
 El artefacto primario de desarrollo de
entidades, es la Entity Class
 Aunque la Entity Class puede tener Helper
Classes

1
Entidades Requerimientos para Entidades

 El estado persistente de una propiedad, esta  La clase debe estar anotada con la
representado por campos persistentes o annotation javax.persistence.Entity
propiedades persistentes  La clase debe tener un constructor que no
 Se utilizan annotations de mapeo O/R para reciba argumentos
mapear entidades y relaciones entre  Puede tener otros constructores
entidades, a elementos de la base de datos  Ni la clase, ni los mtodos, ni los atributos
relacional persistentes, pueden ser declarados final
 Si la clase debe ser utilizada en una interfaz
remota, entonces debe ser serializable

Requerimientos para Entidades Requerimientos para Entidades

 Las entidades pueden extender tanto  Los tipos para los atributos persistentes,
entidades como clases que no son entidades deben ser alguno de estos
 Las clases que no son entidades, tambin  Tipos primitivos
pueden extender a las entidades  java.lang.String
 Los atributos persistentes deben ser  Tipos serializables
 Wrappers para tipos primitivos
declarados privados, default o protected
 java.math.BigInteger, java.math.BigDecimal,
 Los usuarios de una entidad, deben acceder a su java.util.Date, java.util.Calendar, java.sql.Date,
estado a travs de accessors o mtodos de java.sql.Time, java.sql.Timestamp
negocios

Requerimientos para Entidades Atributos persistentes

 (Cont.)  Si la clase utiliza atributos persistentes,


 Tipos serializables entonces el runtime de persistencia accede a
 Tipos definidos por el usuario los atributos persistentes directamente
 byte[], Byte[], char[], Character[]
 Los campos anotados con
 Tipos enumerados javax.persistence.Transient son
 Otras entidades o colecciones de entidades ignorados
 Clases embebidas
 Las anotaciones que mapean con el medio
relacional, deben ser aplicadas a todos los
campos a persistir

2
Propiedades persistentes Propiedades persistentes

 Si la clase usa propiedades persistentes, la  Si los valores son colecciones, entonces


clase debe seguir la norma utilizada para los deben utilizarse las interfaces de colecciones
JavaBeans  java.util.Collection, java.util.Set, java.util.List,
 Mtodos get/set, seguidos del nombre de la java.util.Map
propiedad con la primer letra en mayscula  En caso de usar generics, esto debe
 Type getProperty() especificarse en la firma de los mtodos
 void setProperty(Type type)  Set<PhoneNumber> getPhoneNumbers() {}
 void setPhoneNumbers(Set<PhoneNumber>) {}

Propiedades persistentes Claves primarias

 Los tipos de datos primitivos, wrapper y  Cada entidad tiene un objeto nico que la
Strings, se mapean a columnas en la base identifica
de datos  Este identificador o primary key sirve para
 Las relaciones con otras entidades localizar instancias especificas de una
persistentes, deben marcarse explcitamente, entidad
mapeandose a claves forneas o tablas de  Una entidad puede tener claves primarias
join simples o compuestas
 Las claves primarias simples, utilizan la
anotacin javax.persistence.Id

Claves primarias Claves primarias

 Las claves primarias compuestas deben ser  Los componentes de una clave primaria debe
declaradas en una primary key class ser de alguno de los siguientes tipos Java:
 Para este tipo de claves, se utilizan las  Tipos primitivos
anotaciones  Wrapper classes
javax.persistence.EmbededId y  java.lang.String
javax.persistence.IdClass  java.util.Date
 java.sql.Date

3
Primary Key Class Primary Key Class

 Debe cumplir los siguientes requisitos  (Cont.) Debe cumplir los siguientes requisitos
 La clase debe ser publica  Los campos de una clave primaria (simple o
 Las propiedades deben tener acceso publico o compuesta), deben mapearse con propiedades
protected dentro de la clase de la entidad
 La clase debe tener un constructor publico sin  En este caso, los nombres y tipos de los atributos
argumentos de la clave primaria, mapeados a la entidad,
 La clase debe implementar los mtodos deben ser iguales
hashCode() e equals(Object arg)
 La clase debe ser serializable

Primary Key Class Relaciones entre las entidades


public final class LineItemKey implements Serializable {
public Integer orderId;
public int itemId;

public LineItemKey() {}
 Existen cuatro tipos de multiplicidad
public LineItemKey(Integer orderId, int itemId) {
this.orderId = orderId;
 one-to-one, one-to-many, many-to-one y many-to-
}
this.itemId = itemId; many
public boolean equals(Object otherOb) {  One-to-one
if (this == otherOb) {
return true;  Cada instancia de una entidad, esta relacionada
}
if (!(otherOb instanceof LineItemKey)) { con una nica instancia de otra entidad
return false;
}
LineItemKey other = (LineItemKey) otherOb;
 Usan la anotacin
return ((orderId==null?other.orderId==null:orderId.equals javax.persistence.OneToOne en la propiedad
(other.orderId)) && (itemId == other.itemId));
} o campo que establece la relacin
public int hashCode() {
return ((orderId==null?0:orderId.hashCode()) ^ ((int) itemId));
}
}

JPA Metadata JPA Metadata


Logical

 Existen dos tipos de metadata que podemos


utilizar en JPA
 Logical: Describe el modelo lgico
 Mapping: Describe como el modelo lgico se
mapea con la base de datos subyacente
 Usamos Annotations o XML
 La mayora de los settings tienen valores por
defecto inteligentes

4
JPA Metadata JPA Metadata
Logical

 La ORM Metadata puede ser especificada en


annotations o XML
 El uso de annotations es recomendable en
ambientes de desarrollo
 En ambientes de produccin, el uso de XML es
recomendable
 El ciclo de vida de la base de datos no tiene porque
acompaar el del cdigo
 El tipo de la base de datos o el esquema de la misma
puede variar segn el ambiente (produccin, testing, QA)

JPA Metadata JPA Metadata


Mapping Mapping

 En el ejemplo anterior, no aparecen las


annotations @TABLE o @COLUMN
 El proveedor de persistencia utiliza valores
por defecto para estas propiedades
 Para la tabla, el nombre de la clase de la entidad
 Para los campos, el nombre de las propiedades
dentro de la clase de la entidad

@Entity
@Table(name="ORDER_TABLE")
public class Order {
Relaciones entre las entidades
private int id;
private String address;

@Id  One-to-many
@Column(name="ORDER_ID")  Cada instancia de una entidad, esta relacionada con
public int getId() {
return id; mltiples instancias de otra entidad
Anotaciones
}  Usan la anotacin javax.persistence.OneToMany en la
public void setId(int id) { propiedad o campo que establece la relacin
this.id = id;
}  Many-to-one
 Mltiples instancias de una entidad, estn relacionadas
@Column(name="SHIPPING_ADDRESS")
public String getAddress() { con una nica instancia de otra entidad
return address;  Usan la anotacin javax.persistence.ManyToOne en la
}
propiedad o campo que establece la relacin
public void setAddress(String address) {
this.address = address;
}
}

5
Relaciones entre las entidades Relaciones entre las entidades

 Many-to-many  Las relaciones pueden ser bidireccionales o


 Mltiples instancias de una entidad, estn unidireccionales
relacionadas con mltiples instancias de otra  Las relaciones bidireccionales, tienen un owning
entidad side y un inverse side
 Usan la anotacin  Las relaciones unidireccionales solo tienen un
javax.persistence.ManyToMany en la owning side
propiedad o campo que establece la relacin
 El owning side determina como el runtime
de persistencia actualiza las relaciones en la
base de datos

Relaciones entre las entidades Relaciones y Queries

 En una relacin bidireccional, cada entidad posee  El API de persistencia de Java, utiliza la
un campo que lo relaciona con la otra entidad direccion en la relacin para navegar entre
El inverse side de la relacin debe referir a su owning


side usando la propiedad mappedBy de las anotaciones


las entidades
OneToOne, OneToMany, ManyToOne y ManyToMany
 En una relacin, el lado Many siempre es el owning side
 En relaciones OneToOne, el lado que defina la foreignKey,
es el owning side
 En las ManyToMany, cualquier participante de la relacin
puede ser el owning side

APIs Administrando entidades

 Se basan en las interfaces definidas en el  Las entidades son administradas por el


paquete javax.persistence entity manager
 Interfaces clave:  Esta representado por instancias de
 EntityManager javax.persistence.EntityManager
 Query  Cada una de estas instancias, esta asociada
 En un contexto EJB (Application Server), el a un persistence context
EntityManager es:  Un persistence context, define el scope
 Inyectado dentro de los EJB bajo el cual las entidades son creadas,
 Integrado con el contexto transaccional activo persistidas y removidas

6
Persistence Context Entity Manager

 Es un conjunto de instancias de entidades,  Provee un API para crear y remover


administradas, que existen en un data store instancias de entidades persistentes
particular  Provee tambin funcionalidades para
 La interfaz EntityManager provee mtodos localizar por clave primaria un determinada
para interactuar con el pesistence context entidad
 Asimismo, permite realizar queries sobre las
entidades

Entity Manager Entity Manager


Container Managed Container Managed

 El persistence context asociado a las  Para obtener una instancia de un Entity


entidades del Entity Manager, es Manager, debemos inyectar este dentro del
automticamente propagado a todos los componente de aplicacin
componentes que usan dicho EntityManager  Usamos:
 Todo esto ocurre dentro de una nica @PersistenceContext
transaccin JTA EntityManager em;

Entity Manager Entity Manager


Container Managed Application Managed

 La propagacin automtica del persistence  En este caso, el persistence context no es


context tiene como ventaja que los propagado automticamente a los
componentes de negocio no tienen que componentes
hacerlo explcitamente  El ciclo de vida de las instancias de los
 Esto facilita realizar mltiples cambios, en Entity Managers, es manejado por la
lugares diferentes, pero dentro de la misma aplicacin
transaccin  Las aplicaciones crean instancias de
EntityManagers usando el mtodo
createEntityManager()

7
Entity Manager Algunos ejemplos
Application Managed

 Para poder realizar esto, debemos inyectar  Usamos el EntityManager para localizar y crear
una referencia a una instancia de la clase entidades
EntityManagerFactory

@PersistenceUnit
EntityManagerFactory emf;
EntityManager em = emf.createEntityManager();

Algunos ejemplos Entity Manager


Find

 Usamos el Entity Manager dentro de un Session Bean  El mtodo find() de EntityManager permite
recuperar instancias de entidades

@PersistenceContext
EntityManager em;
public void enterOrder(int custID, Order newOrder) {
Customer cust = em.find(Customer.class, custID);
cust.getOrders().add(newOrder);
newOrder.setCustomer(cust);
}

Java SE Java SE

 JPA puede ser utilizada dentro de una


aplicacin Java SE
 El nico cuidado a tener es que la creacin e
inicializacin debe ser manejada por la
aplicacin
 Las clases e interfaces clave son:
 Persistence
 EntityManagerFactory
 EntityManager

8
Ciclo de vida Ciclo de vida

 Administramos las instancias de entidades,  Las entidades new aun no poseen identidad
invocando mtodos sobre la interfaz persistente y no estn asociadas a un
EntityManager persistence context
 Las instancias de entidades, pueden estar en  Las entidades managed poseen una
4 estados posibles identidad persistente y estn asociadas a
 New un persistence context
 Managed
 Detached
 Removed

Ciclo de vida Ciclo de vida

 Las entidades detached, poseen una  Las nuevas instancias de entidades, pueden
identidad persistente y no estn asociadas ser registradas con el EntityManager
a un persistence context Person p = new Person(Pepe,
 Las entidades removed poseen una Perez);
identidad persistente, estn asociadas a un em.persist(p);
persistence context y se agendan para  Los registros pueden ser agendados para
eliminar del datastore borrado
em.remove(p.getAddress());

Ciclo de vida Callbacks

 Las instancias de entidades pasan a estado  Como en el caso de los Session Beans y los
detached cuando el persistence context finaliza Message Driven Beans, podemos attachear
 Los cambios a las entidades detached, pueden ser un EntityListener para capturar ciertos
combinados en la transaccin actual eventos en el ciclo de vida de la entidad
 PrePersist: Cuando la aplicacin invoca persist()
void updatePerson(Person personVO) {  PostPersist: Luego del INSERT
Person p = em.merge(personVO);
p.setLastUpdated(new Date());  PreRemove: Cuando la aplicacin invoca
} remove()
 PostRemove: Luego del DELETE

9
Callbacks Callbacks

 (Cont.)
 PreUpdate: Cuando el container detecta que una
entidad esta en estado dirty
 PostUpdate: Luego del UPDATE
Declaramos el
 PostLoad: Luego de que una instancia fue listener
cargada
 Attacheamos un listener a la entidad usando
la anotacin @EntityListener

Java Persistence Query Language Algunos trminos

 El lenguaje de consulta permite definir  Abstract Schema


queries para las entidades y su estado  Es la abstraccion del esquema persistente, sobre
persistente el cual las consultas operan
 Permite escribir queries portables,  El lenguaje de consulta, mapea consultas sobre el
independizando del datastore particular Abstract Schema, en consultas sobre el esquema
de base de datos
 Abstract Schema Type
 El abstract schema type de una entidad, se deriva
de la clase de la entidad

Algunos trminos Sintaxis

 Navigation  Una consulta de select tiene 6 elementos


 Es la accin de atravesar una relacin en una query  SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER
particular
 El operador de navegacin es el . BY
 Path expression  SELECT y FROM son requeridos
 Una expresin que navega en el estado de la entidad o sus  Los dems son opcionales
relaciones  La forma general de una consulta de Select es:
 State field  QL_statement ::= select_clause from_clause
 Un campo o propiedad persistente de la entidad [where_clause][groupby_clause][having_claus
 Relationship field e][orderby_clause]
 Es un campo que representa una relacin, cuyo tipo
corresponde al Abstract Schema Type de la entidad
relacionada

10
Sintaxis Sintaxis

 La select_clause define el tipo de los objetos  La where_clause es una expresin que


o valores devueltos restringe los objetos o valores devuelto por
 La from_clause define el scope de la query una query
 Define variables de identificacin que pueden ser  group_by, having, order_by tienen la
referenciadas en el SELECT o WHERE semntica tradicional de SQL
 Una variable de identificacin representa:
 El abstract schema de una entidad
 Un elemento de una coleccin que representa
una relacin

Sintaxis Ejemplos

 Las consultas de delete o update tienen la  Todos los Players


siguiente forma:  SELECT p FROM Player p
 update_statement :: = update_clause  Datos duplicados eliminados
[where_clause]  SELECT DISTINCT p
 delete_statement :: = delete_clause FROM Player p WHERE p.position = ?1
[where_clause]
 Named parameters
 La where_clause tiene el mismo significado  SELECT DISTINCT p
que en el caso del SELECT FROM Player p
WHERE p.position = :position
AND p.name = :name

Ejemplos Ejemplos

 Queries que navegan a entidades  Queries que navegan usando relaciones con
relacionadas valores sencillos
SELECT DISTINCT p SELECT t
FROM Team t JOIN t.league l
FROM Player p, IN(p.teams) t
WHERE l.sport = 'soccer'
SELECT DISTINCT p
OR l.sport ='football'
FROM Player p JOIN p.teams t
SELECT DISTINCT p
 Filtrado en los campos relacionados
SELECT DISTINCT p
FROM Player p
FROM Player p, IN (p.teams) t
WHERE p.team IS NOT EMPTY
WHERE t.league.sport = :sport

11
Ejemplos Ejemplos

 LIKE  BETWEEN
SELECT p FROM Player p SELECT DISTINCT p FROM Player p
WHERE p.name LIKE 'Mich%' WHERE p.salary
 IS NULL BETWEEN :lowerSalary AND :higherSalary
SELECT t FROM Team t  Operadores de comparacion
WHERE t.league IS NULL SELECT DISTINCT p1
 IS EMPTY FROM Player p1, Player p2
SELECT p FROM Player p WHERE p1.salary > p2.salary
WHERE p.teams IS EMPTY AND p2.name = :name

Creando queries

 Utilizamos el EntityManager para crear una


consulta
em = emf.createEntityManager();
Query q = em.createQuery(select c from Customer c +
where c.name = :name");
q.setParameter("name", "Joe Smith");
Customer c = (Customer)q.getSingleResult();
Collection<Order> orders = c.getOrders();
if (orders == null || orders.size() != 2) {
throw new RuntimeException("Unexpected number of orders:"
+ ((orders == null)? "null" : "" + orders.size()));
}

12