JPA

41
JPA Java Persistence API (JPA) proporciona un modelo de persistencia basado en POJO"s para mapear bases de datos relacionales en Java. El Java Persistence API fue desarrollado por el grupo de expertos de EJB 3.0, aunque su uso no se limita a los componentes software EJB. También puede utilizarse directamente en aplicaciones web y aplicaciones clientes; incluso fuera de la plataforma Java EE, por ejemplo, en aplicaciones Java SE. En su definición, se han combinado ideas y conceptos de los principales frameworks de persistencia como Hibernate, Toplink y JDO, y de las versiones anteriores de EJB. Todos estos cuentan actualmente con una implementación JPA. El mapeo objeto/relacional, es decir, la relación entre entidades Java y tablas de la base de datos, se realiza mediante anotaciones en las propias clases de entidad, por lo que no se requieren ficheros descriptores XML. También pueden definirse transacciones como anotaciones JPA. Java Persistence API consta de tres áreas: El Java Persistence API El lenguaje de query El mapeo de los metadatos objeto/relacional Basicamente JPA es una API para ORMs (Object-Relational mapping), el cual permite: Abstraer del proveedor de persistencias, que no es mas que la implementacion que se use. Por ejemplo puede utilizar Hibernate, Toplink, JDO y otros utilizando la misma API (al estilo de JDBC y los drives para cada BD) Eliminar la necesidad de escribir el SQL que mapea la base de datos a los objetos utilizando simples anotaciones. Ya no se escribiran líneas sql en los programas, sino que se realizaran consultas sobre los objetos.

Transcript of JPA

Page 1: JPA

JPA

Java Persistence API (JPA) proporciona un modelo de persistencia basado en POJO"s para mapear bases de datos relacionales en Java. El Java Persistence API fue desarrollado por el grupo de expertos de EJB 3.0, aunque su uso no se limita a los componentes software EJB. También puede utilizarse directamente en aplicaciones web y aplicaciones clientes; incluso fuera de la plataforma Java EE, por ejemplo, en aplicaciones Java SE.

En su definición, se han combinado ideas y conceptos de los principales frameworks de persistencia como Hibernate, Toplink y JDO, y de las versiones anteriores de EJB. Todos estos cuentan actualmente con una implementación JPA.

El mapeo objeto/relacional, es decir, la relación entre entidades Java y tablas de la base de datos, se realiza mediante anotaciones en las propias clases de entidad, por lo que no se requieren ficheros descriptores XML. También pueden definirse transacciones como anotaciones JPA.Java Persistence API consta de tres áreas:

El Java Persistence API

El lenguaje de query

El mapeo de los metadatos objeto/relacional

Basicamente JPA es una API para ORMs (Object-Relational mapping), el cual permite:

Abstraer del proveedor de persistencias, que no es mas que la implementacion que se use. Por ejemplo puede utilizar Hibernate, Toplink, JDO y otros utilizando la misma API (al estilo de JDBC y los drives para cada BD)

Eliminar la necesidad de escribir el SQL que mapea la base de datos a los objetos utilizando simples anotaciones. Ya no se escribiran líneas sql en los programas, sino que se realizaran consultas sobre los objetos.

Poder crear relaciones muchos a uno, uno a uno, uno a muchos y muchos a muchos entre cualquier cantidad de objetos que se quieras una vez mas solo con anotaciones

Controlar la transaccionalidad (utilizando JTA o JDBC) de las consultas y demás. Obviamente ayuda mucho con el tema de la concurrencia y en la forma en que se gestiona

Tiene un cache de primer nivel que por defecto evita estar viendo a la BD muchas veces para lo mismo en una misma transaccion.

Puede utilizar un cache de segundo nivel que incrementara en gran mayoria el rendimiento de la aplicacion y la escalabildidad

Trae un lenguaje de consultas OO facil de usar que permite hacer navegacion entre tablas como si fueran objetos.

por ejemplo,

Page 2: JPA

where empresa.ciudad.pais.nombre = "El Salvador"

donde empresa ciudad y pais son tres tablas diferentes y nombre es una propiedad de Pais.

Requisitos de una Entity JPA

Se anotan con @Entity

Tienen una propiedad anotada con @Id

Constructor sin argumentos public/protected

No puede ser final

Puede extender de otra

Puede ser abstracta

Es un POJO (Plain Old Java Objects), objeto

liviano que no implementan ninguna interfaz

INCO - Facultad de Ingeniería – Montevideo, Uruguay 10

Estado Persistente

Definido por atributos con visibilidad no

pública (privada, protegida, o de paquete)

Atributos persistentes

o Tipos primitivos

o Wrappers de tipos primitivos

o Otras entidades

o Colecciones

INCO - Facultad de Ingeniería – Montevideo, Uruguay 11

Entity JPA - Ejemplo

@Entity

public class Employee {

@Id private int id;

private String name;

private long salary;

public Employee() {}

public Employee(int id) { this.id = id; }

public int getId() { return id; }

public void setId(int id) { this.id = id; }

INCO - Facultad de Ingeniería – Montevideo, Uruguay 12

Page 3: JPA

Entity JPA - Ejemplo

public String getName() { return name; }

public void setName(String name) {

this.name = name;

}

public long getSalary() { return salary; }

public void setSalary (long salary) {

this.salary = salary; }

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 13

@Table

Es una anotación opcional

Por defecto, la entidad se mapea en el

esquema actual, a una tabla con el mismo

nombre que la entidad

INCO - Facultad de Ingeniería – Montevideo, Uruguay 14

@UniqueConstraints

Permite definir restricciones de integridad

sobre la tabla que estamos creando

En general es usada cuando utilizamos la

facilidad de auto-creación de esquema

@Table(name="CATEGORIES",

uniqueConstraints=

{@UniqueConstraint(

columnNames={"CATEGORY_ID"})

}

)

INCO - Facultad de Ingeniería – Montevideo, Uruguay 15

@Column

Mapea una propiedad o campo persistente a

una columna de una tabla de la base de

datos

@Column(name="USER_ID")

Page 4: JPA

protected Long userId;

INCO - Facultad de Ingeniería – Montevideo, Uruguay 16

@Column

String name

boolean unique

boolean nullable

String table

length (255)

@Column(name=“DESC”,

nullable=false,

length=512, ...

)

private String description;

INCO - Facultad de Ingeniería – Montevideo, Uruguay 17

@Enumerated

Permite mapear enumerados en columnas

de la base de datos

o public enum UserType {SELLER, ADMIN};

Al persistir, tenemos dos opciones

o Salvar el ordinal

o Salvar el string

INCO - Facultad de Ingeniería – Montevideo, Uruguay 18

@Enumerated

Salvamos 0, 1

o @Enumerated(EnumType.ORDINAL)

o protected UserType userType;

Salvamos los strings “SELLER” o “ADMIN”

o @Enumerated(EnumType.STRING)

o protected UserType userType;

Por defecto, se salva el ordinal

INCO - Facultad de Ingeniería – Montevideo, Uruguay 19

Tipos de datos temporales

Las bases de datos hoy día soportan

Page 5: JPA

diferentes tipos de datos temporales

o DATE

o TIME

o TIMESTAMP (DATE + TIME)

@Temporal

o define contra cual de los tipos anteriores

queremos mapear un java.util.Date o un

java.util.Calendar

INCO - Facultad de Ingeniería – Montevideo, Uruguay 20

Tipos de datos temporales

Usamos el enumerado TemporalType

@Temporal(TemporalType.DATE)

protected Date creationDate;

Por defecto, se asume TIMESTAMP,

el de menor granularidad

INCO - Facultad de Ingeniería – Montevideo, Uruguay 21

Tipos de datos temporales

En el caso de los tipos de datos…

o java.sql.Data

o java.sql.Time

o java.sql.TimeStamp

…el mapeo es redundante

INCO - Facultad de Ingeniería – Montevideo, Uruguay 22

Generación de PKs

Cuando identificamos una columna como PK,

lo que le estamos pidiendo a la base es que

fuerce unicidad

Las claves primarias que consisten en datos

del negocio, se denominan natural keys

Un ejemplo de esto, es el número de cédula

de identidad

INCO - Facultad de Ingeniería – Montevideo, Uruguay 23

Generación de PKs

Page 6: JPA

Claves de la forma CATEGORY_ID,

USER_ID se denominan surrogate keys

Estas últimas son muy populares, por su

facilidad de autogeneración

En sistemas que utilizan frameworks de

persistencia, son altamente recomendadas

INCO - Facultad de Ingeniería – Montevideo, Uruguay 24

Generación de PKs

Existen tres formas populares de generar

claves primarias

o A través de campos identity

o A través de secuencias

o Utilizando una tabla numeradora

Cualquiera de los tres mecanismos se

soportan a través de la anotación

@GeneratedValue

INCO - Facultad de Ingeniería – Montevideo, Uruguay 25

Identities

Muchas bases de datos soportan el tipo de

datos IDENTITY

En el caso del usuario, podemos generar la

PK de esta forma:

@Id

@GeneratedValue(strategy=

GenerationType.IDENTITY

)

@Column(name="USER_ID")

protected Long userId;

INCO - Facultad de Ingeniería – Montevideo, Uruguay 26

Identities

Cuidado …

En general este valor es obtenido una vez

que el registro es “commiteado” en la base

Page 7: JPA

Tener en cuenta que no siempre estará

disponible en el programa

INCO - Facultad de Ingeniería – Montevideo, Uruguay 27

Sequences

En este caso, se necesita un generador para

la clave primaria

Las secuencias de la BD cumplen ese rol

Por ejemplo, una secuencia Oracle se puede

declarar de esta forma:

CREATE SEQUENCE USER_SEQUENCE

START WITH 1

INCREMENT BY 10;

INCO - Facultad de Ingeniería – Montevideo, Uruguay 28

@SequenceGenerator

La utilizamos para declarar un generador

asociado a la secuencia

@SequenceGenerator(

name="USER_SEQUENCE_GENERATOR",

sequenceName="USER_SEQUENCE",

initialValue=1,

allocationSize=10

)

INCO - Facultad de Ingeniería – Montevideo, Uruguay 29

Sequence Generator

En la entidad que utiliza el generador,

podemos generar la clave de esta forma:

@Id

@GeneratedValue(

strategy=GenerationType.SEQUENCE,

generator="USER_SEQUENCE_GENERATOR")

@Column(name="USER_ID")

protected Long userId;

INCO - Facultad de Ingeniería – Montevideo, Uruguay 30

Page 8: JPA

Table Generator

Es muy similar al caso anterior, solo que los

valores salen de una tabla numeradora, con

un formato similar a este:

CREATE TABLE SEQUENCE_GENERATOR_TABLE (

SEQUENCE_NAME VARCHAR2(80) NOT NULL,

SEQUENCE_VALUE NUMBER(15) NOT NULL,

PRIMARY KEY (SEQUENCE_NAME)

);

INCO - Facultad de Ingeniería – Montevideo, Uruguay 31

Table Generator

Luego, debemos preparar la tabla para

insertar el primer valor de la secuencia

INSERT INTO SEQUENCE_GENERATOR_TABLE

(SEQUENCE_NAME, SEQUENCE_VALUE)

VALUES

('USER_SEQUENCE', 1);

INCO - Facultad de Ingeniería – Montevideo, Uruguay 32

Table Generator

Luego, configuramos el TableGenerator en el

código

@TableGenerator (

name="USER_TABLE_GENERATOR",

table="SEQUENCE_GENERATOR_TABLE",

pkColumnName="SEQUENCE_NAME",

valueColumnName="SEQUENCE_VALUE",

pkColumnValue="USER_SEQUENCE“

)

INCO - Facultad de Ingeniería – Montevideo, Uruguay 33

Table Generator

Por último, referenciamos este generador

desde la entidad

@Id

Page 9: JPA

@GeneratedValue(

strategy=GenerationType.TABLE,

generator="USER_TABLE_GENERATOR")

@Column(name="USER_ID")

protected Long userId;

INCO - Facultad de Ingeniería – Montevideo, Uruguay 34

Estrategia por defecto

La última opción para la estrategia de

generación, es dejar que el provider de base

de datos decida la mejor alternativa

@Id

@GeneratedValue(

strategy=GenerationType.AUTO)

@Column(name="USER_ID")

protected Long userId;

Herencia

Entidades Concretas (hojas)

Entidades Abstractas: definen estado y

comportamiento a heredar por las subclases

– No anotada: define estado persistente y puede

participar en queries y relaciones con entidades

– Anotada con @MappedSuperclass: define estado

persistente ; no participa en queries ni en relaciones

con entidades

Transient Classes: no definen estado persistente;

pueden ser heredadas

INCO - Facultad de Ingeniería – Montevideo, Uruguay 43

Herencia

INCO - Facultad de Ingeniería – Montevideo, Uruguay 44

Herencia

@Entity

Page 10: JPA

public class Employee {

@Id private int id;

private String name;

@Temporal(TemporalType.DATE)

@Column(name="S_DATE")

private Date startDate;

// ...

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 45

Herencia

@Entity

public class ContractEmployee extends

Employee {

@Column(name="D_RATE")

private int dailyRate;

private int term;

// ...

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 46

@MappedSuperclass

public abstract class CompanyEmployee

extends Employee {

private int vacation;

// ...

}

@Entity

public class PartTimeEmployee

extends CompanyEmployee {

@Column(name="H_RATE")

private float hourlyRate;

// ...

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 47

Page 11: JPA

Herencia

@MappedSuperclass

public abstract class CompanyEmployee extends

Employee {

private int vacation;

// ...

}

@Entity

public class FullTimeEmployee

extends CompanyEmployee {

private long salary;

private long pension;

// ...

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 48

Transient Classes

public abstract class CachedEntity {

private long createTime;

public CachedEntity() {

createTime =

System.currentTimeMillis();

}

public long getCacheAge() {

return System.currentTimeMillis() -createTime;

}

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 49

Transient Classes

@Entity

public class Employee extends CachedEntity {

public Employee() {

super();

}

Page 12: JPA

// ...

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 50

Mapeo de Herencia

Estrategia Single-Table

Estrategia Joined

Estrategia Table-per-Concrete-Class

INCO - Facultad de Ingeniería – Montevideo, Uruguay 51

Estrategia Single-Table

Una sola tabla para guardar instancias de

todas las entidades concretas

Se diferencian por un campo discriminador

Eficiente (no requiere join)

Gran cantidad de valores nulos (una entidad

utiliza sólo sus atributos)

INCO - Facultad de Ingeniería – Montevideo, Uruguay 52

Estrategia Single-Table

@Entity

@Table(name="EMP")

@Inheritance

@DiscriminatorColumn(name="EMP_TYPE")

public abstract class Employee { ... }

INCO - Facultad de Ingeniería – Montevideo, Uruguay 53

Estrategia Single-Table

@MappedSuperclass

public abstract class CompanyEmployee

extends Employee { ... }

@Entity

@DiscriminatorValue("FTEmp")

public class FullTimeEmployee

extends CompanyEmployee { ... }

INCO - Facultad de Ingeniería – Montevideo, Uruguay 54

Estrategia Single-Table

Page 13: JPA

INCO - Facultad de Ingeniería – Montevideo, Uruguay 55

Estrategia Joined

Cada entidad de la jerarquía tiene una tabla

asociada

Refleja la jerarquía

Guarda los datos en forma normalizada sin

desperdiciar espacio

Una instancia de entidad se guarda en

múltiples tablas

Requiere joins para obtener una instancia de

una entidad concreta

INCO - Facultad de Ingeniería – Montevideo, Uruguay 56

Estrategia Joined

INCO - Facultad de Ingeniería – Montevideo, Uruguay 57

Estrategia Joined

@Entity

@Table(name="EMP")

@Inheritance(strategy=InheritanceType.JOINED)

@DiscriminatorColumn(name="EMP_TYPE",

discriminatorType=DiscriminatorType.INTEGER)

public abstract class Employee { ... }

INCO - Facultad de Ingeniería – Montevideo, Uruguay 58

Estrategia Joined

@Entity

@Table(name="CONTRACT_EMP")

@DiscriminatorValue("1")

public class ContractEmployee

extends Employee { ... }

INCO - Facultad de Ingeniería – Montevideo, Uruguay 59

Estrategia Joined

@MappedSuperclass

public abstract class CompanyEmployee

extends Employee { ... }

Page 14: JPA

@Entity

@Table(name="FT_EMP")

@DiscriminatorValue("2")

public class FullTimeEmployee

extends CompanyEmployee { ... }

INCO - Facultad de Ingeniería – Montevideo, Uruguay 60

Estrategia Joined

@Entity

@Table(name="PT_EMP")

@DiscriminatorValue("3")

public class PartTimeEmployee

extends CompanyEmployee { ... }

INCO - Facultad de Ingeniería – Montevideo, Uruguay 61

Estrategia

Table-per-Concrete-Class

Una tabla por cada clase no abstracta

Las propiedades heredadas se repiten en

cada tabla

Se evita la redundancia y también se

evitan todos los joins a nivel de base de

datos

Mapeo

o En la clase raíz añadir @DiscriminatorColumn

o En cada clase hija añadir @DiscriminatorValue

INCO - Facultad de Ingeniería – Montevideo, Uruguay 62

Estrategia

Table-per-Concrete-Class

INCO - Facultad de Ingeniería – Montevideo, Uruguay 63

Estrategia

Table-per-Concrete-Class

@Entity

@Inheritance(strategy=

InheritanceType.TABLE_PER_CLASS)

Page 15: JPA

public abstract class Employee {

@Id private int id;

private String name;

@Temporal(TemporalType.DATE)

@Column(name="S_DATE")

private Date startDate;

// ...

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 64

Estrategia

Table-per-Concrete-Class

public class ContractEmployee extends

Employee {

@Column(name="D_RATE")

private int dailyRate;

private int term;

// ...

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 65

Estrategia

Table-per-Concrete-Class

@Entity @Table(name="FT_EMP")

public class FullTimeEmployee extends

CompanyEmployee {

private long salary;

@Column(name="PENSION")

private long pensionContribution;

// ...

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 66

Entity manager

El API del EntityManager es la parte más

importante e interesante de JPA

Page 16: JPA

Maneja el ciclo de vida de las entidades

Actúa de puente entre el mundo O.O y el

mundo relacional

INCO - Facultad de Ingeniería – Montevideo, Uruguay 67

Entity manager – métodos

public void persist(Object entity);

public <T> T merge(T entity);

public void remove(Object entity);

public <T> T find(Class<T> entityClass,

Object primaryKey);

public void flush();

public void setFlushMode(FlushModeType

flushMode);

public FlushModeType getFlushMode();

INCO - Facultad de Ingeniería – Montevideo, Uruguay 68

Entity manager – metodos

public void refresh(Object entity);

public Query createQuery(String

jpqlString);

public Query createNamedQuery(String

name);

INCO - Facultad de Ingeniería – Montevideo, Uruguay 69

Ciclo de vida

Por más que anotemos una entidad con

@Entity, el EntityManager no sabe nada de

estas, hasta que no se asocia la misma con

el EntityManager

Esta idea es opuesta a como funciona un

MDB o un Session bean

Es más, la idea del EM, es manejar una

entidad el menor tiempo posible

INCO - Facultad de Ingeniería – Montevideo, Uruguay 70

Ciclo de vida

Page 17: JPA

Una entidad que esta siendo administrada

por el EntityManager, se considera managed

o attached

Cuando el EntityManager termina de

administrar la entidad, decimos que esta en

estado detached

Cuando una entidad no pasa por el

EntityMangaer, decimos que esta en estado

transient

INCO - Facultad de Ingeniería – Montevideo, Uruguay 71

Transient entities

Cuando una entidad es recien creada a

traves de new, entonces esta en estado new

o transient

Bid bid = new Bid();

INCO - Facultad de Ingeniería – Montevideo, Uruguay 72

Managed entities

Una entidad entra a estado managed,

cuando es pasada como parámetro a los

métodos persist, merge o refresh

También una entidad esta en estado

managed cuando es recibida como resultado

de un método find

INCO - Facultad de Ingeniería – Montevideo, Uruguay 73

Detached entities

Es una entidad que ya no esta asociada a un

EntityManager

En este estado, ya no tenemos garantía de

que el estado de la entidad se encuentre

sincronizado con la base de datos

La acción de perder ese vinculo, se

denomina Detachment, la de volver a

vincularlo, se denomina Merge

Page 18: JPA

INCO - Facultad de Ingeniería – Montevideo, Uruguay 74

Detached entities

Este tipo de estado es importante, ya que es

necesario cuando una entidad cruza entre

capas de una aplicación

INCO - Facultad de Ingeniería – Montevideo, Uruguay 75

Ciclo de vida de la entidad

INCO - Facultad de Ingeniería – Montevideo, Uruguay 76

Persistence context

Formalmente, un persistence context es un

conjunto de entidades administradas,

controladas por un EntityMangager, durante

un persistence scope

El persistence scope, es el tiempo que un

conjunto de entidades permanecen

administradas

INCO - Facultad de Ingeniería – Montevideo, Uruguay 77

Persistence context

Tenemos dos tipos de persistence scopes

o Transaction

o Extended

INCO - Facultad de Ingeniería – Montevideo, Uruguay 78

Transaction-scoped

EntityManager

Es un entity manager asociado con

persistence scope transaccional

Las entidades “attacheadas” durante la

transacción, son automáticamente

“desatacheadas” al terminar la misma

INCO - Facultad de Ingeniería – Montevideo, Uruguay 79

Extended EntityManager

Un entity manager tiene un tiempo de vida

que abarca varias transacciones

Page 19: JPA

Solo puede ser utilizado dentro de un

Session Bean stateful, durando tanto como la

instancia permanezca activa

INCO - Facultad de Ingeniería – Montevideo, Uruguay 80

Persistiendo entidades

public Item addItem(String title,

String description, byte[] picture,

double initialPrice, long sellerId) {

Item item = new Item();

item.setTitle(title);

item.setDescription(description);

item.setPicture(picture);

item.setInitialPrice(initialPrice);

INCO - Facultad de Ingeniería – Montevideo, Uruguay 81

Persistiendo entidades

Seller seller = entityManager.find(

Seller.class,

sellerId);

item.setSeller(seller);

entityManager.persist(item);

return item;

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 82

Persistiendo relaciones

public User addUser(String username,

String email, String creditCardType,

String creditCardNumber,

Date creditCardExpiration) {

User user = new User();

user.setUsername(username);

user.setEmail(email);

BillingInfo billing = new BillingInfo();

Page 20: JPA

billing.setCreditCardType(creditCardType);

INCO - Facultad de Ingeniería – Montevideo, Uruguay 83

Persistiendo relaciones

billing.setCreditCardNumber(

creditCardNumber);

billing.setCreditCardExpiration(

creditCardExpiration);

user.setBillingInfo(billing);

entityManager.persist(user);

return user;

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 84

Cascading

Por defecto, el comportamiento de JPA es

de NO persistir entidades relacionadas

En el caso anterior, el BillingInfo no sería

insertado automáticamente

Para que esto funcione, debemos modificar

el cascading de la relación

INCO - Facultad de Ingeniería – Montevideo, Uruguay 85

Cascading

El cascading define como se propaga la

operación sobre los elementos relacionados,

cuando hacemos una operación en el

elemento “padre”

public class User {

@OneToOne(cascade=CascadeType.PERSIST)

public void setBillingInfo(

BillingInfo billing) {

INCO - Facultad de Ingeniería – Montevideo, Uruguay 86

Cascading

La idea es similar al cascading en base de

Page 21: JPA

datos

Por defecto el cascading esta vacío, por lo

que no existe propagación de operaciones de

persistencia

Los valores posibles salen del enumerado

CascadeType

o ALL, MERGE, PERSIST, REFRESH, o REMOVE

INCO - Facultad de Ingeniería – Montevideo, Uruguay 87

Cascading

Si el cascading no es especificado, entonces

deberemos manualmente propagar las

operaciones de persistencia

Para esto, en el ejemplo anterior, debemos

primero persistir el BillingInfo y luego el User

INCO - Facultad de Ingeniería – Montevideo, Uruguay 88

Recuperación por primary key

JPA soporta el método find en el

EntityManager

A este método debemos pasarle la clase que

estamos buscando, y el valor de la primary

key que estamos filtrando

Seller seller = entityManager.find(

Seller.class,

sellerId);

INCO - Facultad de Ingeniería – Montevideo, Uruguay 89

Fetch modes

Tenemos dos posibilidades

o Eager o Lazy

En el modo Lazy, los datos son cargados de

la base de datos en demanda, cuando son

utilizados

En el modo Eager, los datos son cargados al

levantar la entidad

Page 22: JPA

INCO - Facultad de Ingeniería – Montevideo, Uruguay 90

Ejemplo de Fetch mode

A nivel de relación:

@ManyToOne(fetch=FetchType.LAZY)

public Seller getSeller() {

return seller;

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 91

Fetch modes por defecto

Por la característica especial de alguna

relaciones, el comportamiento por defecto del

fetch para relaciones es diferente según el

tipo de relación

o One-to-one = EAGER

o One-to-many = LAZY

o Many-to-one = EAGER

o Many-to-many = LAZY

INCO - Facultad de Ingeniería – Montevideo, Uruguay 92

Actualizando entidades

Lo interesante de utilizar JPA como

mecanismo de ORM, es que todos los

detalles de la actualización de entidades

persistentes, es transparente

Esto es debido a que los objetos que están

asociados al EntitiyManager, son

administrados por el mismo, lo que incluyeoperaciones de actualización

INCO - Facultad de Ingeniería – Montevideo, Uruguay 93

Actualizando entidades

public void calculateCredit(Long sellerId) {

PowerSeller seller = entityManager.find(

PowerSeller.class, sellerId);

seller.setCreditWorth(100);

.. código ..

Page 23: JPA

seller.setCreditMax(200);

.. código ..

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 94

Detachment y merge

Si bien una entidad attached es

extremadamente útil, es difícil mantenerlas

attacheadas todo el tiempo

Un caso típico se da en las aplicaciones web

Es común que las entidades tengan que ser

serializadas y enviadas a la capa web

En la capa web, las entidades serán

cambiadas, fuera del scope del

EntityManager

INCO - Facultad de Ingeniería – Montevideo, Uruguay 95

Detachment y merge

public Item addItem(String title,

String description, byte[] picture,

double initialPrice, long sellerId) {

Item item = new Item();

item.setTitle(title);

...

entityManager.persist(item);

return item;

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 96

Detachment y merge

El ítem devuelto por el método, será enviado

a presentación (web), donde puede ser

modificado

En algún momento, necesitamos asociar este

elemento con la base de datos nuevamente,

para sincronizar su estado

Page 24: JPA

Para esto usamos el método merge

INCO - Facultad de Ingeniería – Montevideo, Uruguay 97

Detachment y merge

INCO - Facultad de Ingeniería – Montevideo, Uruguay 98

Detachment y merge

merge nos garantiza que el objeto está

asociado nuevamente con el persistence

context, y que eventualmente será

sincronizado con la base de datos

public Item updateItem(Item item) {

entityManager.merge(item);

return item;

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 99

Detachment y merge

Cuando el método updateItem termine, la

base de datos será actualizada con el estado

del ítem

El método merge solo puede ser usado para

entidades que existan en la base de datos

Si tratamos de mergear un elemento no

existente, se producirá una

IllegalArgumentException.

INCO - Facultad de Ingeniería – Montevideo, Uruguay 100

Borrado de entidades

Utilizamos el método remove del entity

manager

El único detalle de este método, es que solo

pueden eliminarse entidades que han sido

“mergeadas” con el persistence context

public void deleteItem(Item item) {

entityManager.remove(

entityManager.merge(item));

Page 25: JPA

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 101

Refresh de entidades

Permite cargar los datos de una entidad,

desde la base de datos

No es muy común de usar, aunque a veces

puede ser útil para deshacer los cambios en

una transacción

public Item undoItemChanges(Item item) {

entityManager.refresh(

entityManager.merge(item));

return item;

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 102

Refresh de entidades

Sin embargo, hay un escenario donde es

muy útil.

Que pasa si al insertar un registro en la base

de datos, la propia base modifica el valor de

algunas columnas a través de un trigger

En este caso, desde Java solo veremos lo

insertado, ya que los datos generados por la

base no serán cargados

INCO - Facultad de Ingeniería – Montevideo, Uruguay 103

Refresh de entidades

public Item addItem(String title,

String description, byte[] picture,

double initialPrice, long sellerId) {

Item item = new Item();

item.setTitle(title);

...

entityManager.persist(item);

entityManager.flush();

Page 26: JPA

entityManager.refresh(item);

return item;

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 104

Flushing

Las operaciones del EntityManager, como

persist, merge y remove, no alteran la base

de datos inmediatamente

Principalmente esto se hace por motivos de

performance

Las operaciones SQL en modo batch suelen

ser mas performantes que las operaciones

emitidas de a una por vez

INCO - Facultad de Ingeniería – Montevideo, Uruguay 105

Flushing

Las operaciones anteriores (alteraciones de

la base) son pospuestas hasta que se

flushee el EntityManager

Por defecto, el modo de flush es AUTO

Esto significa que el flush es emitido por el

EntityManager según sea necesario

INCO - Facultad de Ingeniería – Montevideo, Uruguay 106

Flushing

El modo de flush lo controlamos utilizando el

enumerado FlushModeType

Para efectuar el flush, hacemos:

entityManager.setFlushMode(

FlushModeType.COMMIT);

entityManager.flush();

INCO - Facultad de Ingeniería – Montevideo, Uruguay 107

Entity Manager

Persistence Scope Transaction

@Stateless

Page 27: JPA

public class ProjectServiceBean implements

ProjectService {

@PersistenceContext(

unitName="EmployeeService")

EntityManager em;

INCO - Facultad de Ingeniería – Montevideo, Uruguay 108

Entity Manager

Persistence Scope Transaction

public void assignEmployeeToProject(

int empId, int projectId) {

Project project = em.find(Project.class,

projectId);

Employee employee =

em.find(Employee.class, empId);

project.getEmployees().add(employee);

employee.getProjects().add(project);

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 109

Entity Manager

Persistence Scope Extended

@Stateful

public class DepartmentManagerBean implements

DepartmentManager {

@PersistenceContext(

unitName="EmployeeService",

type=PersistenceContextType.EXTENDED)

EntityManager em;

Department dept;

INCO - Facultad de Ingeniería – Montevideo, Uruguay 110

Entity Manager

Persistence Scope Extended

public void setName(String name) {

dept.setName(name);

Page 28: JPA

}

public void addEmployee(int empId) {

Employee emp = em.find(Employee.class,

empId);

dept.getEmployees().add(emp);

emp.setDepartment(dept);

}

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 111

Entity Manager

Persistence Scope Extended

Que ocurre si en el ejemplo anterior omitimos

declarar como EXTENDED el

PersistenceContextType ?

INCO - Facultad de Ingeniería – Montevideo, Uruguay 112

Entity Manager

Persistence Scope Extended

o Se asume por defecto PersistenceContextType

TRANSACTION

o Asumiendo que no hay una transacción activa en

el cliente, cada método iniciaría y terminará una

transacción (recordar REQUIRED)

o Lo anterior hará que el entity manager use

diferentes Persistence Contexts cada vez

o Si ya pasamos por el método init, se tendrá una

instancia creada de Departament, por lo tanto

cada vez que se invoque por ejemplo setName,

actuará sobre esta entidad. Y ???

INCO - Facultad de Ingeniería – Montevideo, Uruguay 113

Entity Manager

Persistence Scope Extended

o Como la ejecución de init terminó su transacción,

dejó a la instancia Departament detached

Page 29: JPA

o Las sucesivas invocaciones a setName actuarán

sobre la misma instancia, cambiando el valor del

atributo name

o Pero …

o Los cambios nunca se impactarán en la base

de datos

INCO - Facultad de Ingeniería – Montevideo, Uruguay 114

Recuperando información

Con JPA podemos usar los siguientes

métodos para recuperar información

o El metodo EntityManager.find(…)

o Queries escritas en JPQL

o Queries nativas escritas en SQL

INCO - Facultad de Ingeniería – Montevideo, Uruguay 115

Query API

Los pasos para utilizar una consulta con JPA

son los siguientes:

o Obtener una referencia al EntityManager

o Crear una instancia de una Query

o Ejecutar la query

o Recuperar los resultados (entities)

INCO - Facultad de Ingeniería – Montevideo, Uruguay 116

Queries

El API de consultas de JPA soporta dos tipos

de consultas:

o Named

o Dynamic

INCO - Facultad de Ingeniería – Montevideo, Uruguay 117

Queries

Las Named queries son consultas

almacenadas que pueden ser reutilizadas en

un programa

Las Dynamic queries son consultas que se

Page 30: JPA

forman dinámicamente en el programa

Su estructura se construye

programáticamente

En cualquier caso, su uso es similar

INCO - Facultad de Ingeniería – Montevideo, Uruguay 118

Queries

@PersistenceContext em;

...

public List findAllCategories() {

Query query = em.createQuery(

"SELECT c FROM Category c");

...

return query.getResultList();

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 119

Named Queries

Se crean asociadas a la entidad que

queremos consultar

La definición puede ser almacenada en

formato XML o en el propio código de la

clase

Las named queries deben tener nombre

único dentro de una persistence unit

INCO - Facultad de Ingeniería – Montevideo, Uruguay 120

Named Queries

@Entity

@NamedQuery(

name = "findAllCategories",

query = "SELECT c

FROM Category c

WHERE c.categoryName

LIKE :categoryName ")

public class Category

Page 31: JPA

implements Serializable {

...

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 121

Named Queries

@Entity

@NamedQueries({

@NamedQuery(

name = "findCategoryByName",

query = "SELECT c FROM Category c

WHERE c.categoryName LIKE

:categoryName

order by c.categoryId"

),

INCO - Facultad de Ingeniería – Montevideo, Uruguay 122

Named Queries

@NamedQuery(

name = "findCategoryByUser",

query = "SELECT c FROM Category c

JOIN c.user u

WHERE u.userId = ?1“

)

})

@Table(name = "CATEGORIES")

public class Category implements Serializable

INCO - Facultad de Ingeniería – Montevideo, Uruguay 123

Creando una instancia de la

Query

public Query createQuery(String qlString);

public Query createNamedQuery(String name);

public Query createNativeQuery(String,

sqlString);

INCO - Facultad de Ingeniería – Montevideo, Uruguay 124

Page 32: JPA

Creando una instancia de la

Query

public Query createNativeQuery(String

sqlString,Class result-class);

public Query createNativeQuery(String

sqlString,String result-setMapping);

INCO - Facultad de Ingeniería – Montevideo, Uruguay 125

Creando una instancia de la

Query

Algunos ejemplos…

Named

o Query query =

em.createNamedQuery("findAllCategories");

Dynamic

o Query query = em.createQuery("SELECT i

FROM Item i");

INCO - Facultad de Ingeniería – Montevideo, Uruguay 126

Utilizando la interfaz Query

Para ejecutar la consulta…

query = em.createNamedQuery(

"findCategoryByName");

query.setParameter("categoryName",

categoryName);

query.setMaxResults(10);

query.setFirstResult(3);

List categories = query.getResultList();

INCO - Facultad de Ingeniería – Montevideo, Uruguay 127

Parámetros en la Query

En una query, podemos usar una cláusula

WHERE para restringir los valores obtenidos

Por ejemplo, todos los ítems con un precio

determinado, pueden obtenerse así:

SELECT i FROM Item i

Page 33: JPA

WHERE i.initialPrice = ?1

INCO - Facultad de Ingeniería – Montevideo, Uruguay 128

Parámetros en la Query

En el caso anterior, parametrizamos la

consulta utilizando parámetros posicionales

Para establecer el valor del parámetro, basta

con hacer:

query.setParameter(1,100)

INCO - Facultad de Ingeniería – Montevideo, Uruguay 129

Parámetros en la Query

Podemos usar otro tipo de parámetros,

llamados parámetros nombrados (named

parameters)

Son de la forma:

SELECT i FROM Item i

WHERE i.initialPrice = :price

INCO - Facultad de Ingeniería – Montevideo, Uruguay 130

Parámetros en la Query

Estos mejoran muchísima la legibilidad y

búsqueda de errores de una query

Establecer el valor de uno de estos, se

realiza de la siguiente forma:

query.setParameter(“price”,100)

INCO - Facultad de Ingeniería – Montevideo, Uruguay 131

Recuperando una entidad

Si nuestra consulta devuelve una instancia

(tupla) resultado, con el método

getSingleResult podemos obtenerla

Produce error si retorna mas de una tupla

query.setParameter(1,“Categoria”);

Category cat =

(Category)query.getSingleResult();

INCO - Facultad de Ingeniería – Montevideo, Uruguay 132

Page 34: JPA

Recuperando una entidad

try {

...

query.setParameter(1,“Categoria”);

Category cat =

(Category)query.getSingleResult();

...

}catch (NonUniqueResultException ex) {

handleException(ex);

} catch (NoResultException ex) {

handleException(ex);

}

INCO - Facultad de Ingeniería – Montevideo, Uruguay 133

Recuperando una colección

La mayoría de las queries retorna mas de

una tupla resultado

Para esto, podemos usar el método

getResultList()

query.setParameter("lowPrice",

lowPriceValue);

query.setParameter("highPrice",

highPriceValue);

List items = query.getResultList();

INCO - Facultad de Ingeniería – Montevideo, Uruguay 134

Paginado de resultados

setMaxResults permite definir el máximo

numero de entidades que serán traídas en el

result set

setFirstResult permite definir la posición del

primer resultado en el result set

INCO - Facultad de Ingeniería – Montevideo, Uruguay 135

Paginado de resultados

Por ejemplo para traer los próximos 50

Page 35: JPA

resultados, haríamos:

query.setMaxResults(50);

query.setFirstResult(50);

List items = query.getResultList();

INCO - Facultad de Ingeniería – Montevideo, Uruguay 136

JPQL

El procesador de consultas de JPA,

transforma una consulta JPQL en una

consulta SQL

INCO - Facultad de Ingeniería – Montevideo, Uruguay 137

SELECT

Es de la forma:

SELECT c

FROM Category c

WHERE c.categoryName LIKE :categoryName

ORDER BY c.categoryId

INCO - Facultad de Ingeniería – Montevideo, Uruguay 138

SELECT

Una consulta puede tener los siguientes

elementos:

o SELECT

o FROM

o WHERE

o ORDER BY

o GROUP BY

o HAVING

INCO - Facultad de Ingeniería – Montevideo, Uruguay 139

Empaquetado

Se debe definir un descriptor de la unidad de persistencia

o META-INF/persistence.xml

JBoss utiliza Hibernate 3 para implementar JPA

<persistence>

<persistence-unit name=“tsi2_PU">

Page 36: JPA

<jta-data-source>java:myDS</jta-data-source>

<properties>

<property name="hibernate.show_sql" value="false" />

<property name="hibernate.dialect"

value="org.hibernate.dialect.PostgtreSQLDialect" />

<property name="hibernate.hbm2ddl.auto"

value="update" />

</properties>

</persistence-unit>

</persistence>

INCO - Facultad de Ingeniería – Montevideo, Uruguay 140

Empaquetado

Posibles valores de la propiedad

hibernate.hbm2ddl.auto

o validate

o update

o create

o create-drop

INCO - Facultad de Ingeniería – Montevideo, Uruguay 141

Empaquetado

Dos formas de declarar las entidades que

conforman una unidad de persistencia:

o Declarando cada una de sus clases

o Declarando el nombre de un archivo .jar que

contiene las entidades

INCO - Facultad de Ingeniería – Montevideo, Uruguay 142

Empaquetado

<persistence>

<persistence-unit name=“tsi2_PU“>

<jta-data-source>java:myDS</jta-data-source>

<class>tsi2.entities.Cliente</class>

<class>tsi2.entities.Empresa</class>

Page 37: JPA

</persistence-unit>

</persistence>

INCO - Facultad de Ingeniería – Montevideo, Uruguay 143

Empaquetado

<persistence>

<persistence-unit name=“tsi2_PU">

<jta-data-source>java:myDS</jta-data-source>

<jar-file>myEntities.jar</jar-file>

</persistence-unit>

</persistence>

INCO - Facultad de Ingeniería – Montevideo, Uruguay 144

Ventajas y Desventajas de JPA

Ventajas

o Simplicidad: una única clase para declarar la

persistencia (con la ayuda de anotaciones)

o Transparencia: las clases a persistir son simples

POJOs

o No hay restricciones con respecto a relaciones entre

objetos (herencia, poliformismo)

Desventajas

o Anotaciones (Descripción de la Base de Datos en el

código) dificultan el mantenimiento.

o Solución: Siempre se puede utilizar un XML