Jee Ejb
Jee Ejb
Jee Ejb
0
Agenda
Introducción
Session beans
Session beans 2.1 vs. Session beans 3.0
Analizando session beans 3.0
Inyección de dependencias
Transacciones
Entity beans
Entity beans 2.1 vs. Entity beans 3.0
Analizando entity beans 3.0
Relaciones
Herencia
JPA: Java Persistence API
Analizando JPA
Ciclo de vida de los entities
Query API y JPQL
Agenda
Introducción
Session beans
Session beans 2.1 vs. Session beans 3.0
Analizando session beans 3.0
Inyección de dependencias
Transacciones
Entity beans
Entity beans 2.1 vs. Entity beans 3.0
Analizando entity beans 3.0
Relaciones
Herencia
JPA: Java Persistence API
Analizando JPA
Ciclo de vida de los entities
Query API y JPQL
Características principales de EJB 3
Simplificación del modelo de componentes desde el punto
de vista del desarrollador
Modelo de componentes menos intrusivo
Utilización de POJOs como componentes
Utilización de POJIs como interfaces
Utilización de anotaciones (metadata)
Eliminación del uso de los descriptores (opcional)
Inyección de dependencias (inversión de control)
Standarización de la API de persistencia para la plataforma
Java (basada en ORMs tales como Hibernate y Toplink)
Facilitación del testeo de EJBs fuera del container
EJB 3 de capas
Agenda
Introducción
Session beans
Session beans 2.1 vs. Session beans 3.0
Analizando session beans 3.0
Inyección de dependencias
Transacciones
Entity beans
Entity beans 2.1 vs. Entity beans 3.0
Analizando entity beans 3.0
Relaciones
Herencia
JPA: Java Persistence API
Analizando JPA
Ciclo de vida de los entities
Query API y JPQL
Session beans 2.1
public interface CalculatorRm extends EJBObject
{
public int add(int a, int b) throws RemoteException;
}
<enterprise-beans>
<session>
<ejb-name>CalculatorEJB</ejb-name>
<home>CalculatorRmHm</home>
<remote>CalculatorRm</remote>
<local-home>CalculatorLcHm</local-home>
<local>CalculatorLc</local>
<ejb-class>CalculatorBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
Session beans 2.1: Desventajas
Necesidad de crear varios artefactos para definir el bean
(homes, interfaces, bean, descriptor)
Alto acoplamiento con la API de EJB: modelo altamente
intrusivo. Necesidad de implementación de callbacks en el
bean
Descriptores de deploy: complejidad en su mantenimiento.
Necesidad adicional de un descriptor propietario del EJB
container
Session beans 3.0
@Remote
public interface CalculatorRm
{
public int add(int a, int b);
}
@Local
public interface CalculatorLc
{
public int add(int a, int b);
}
@Stateless
public class CalculatorBean implements CalculatorRm, CalculatorLc
{
public int add(int a, int b) {return a + b;}
}
Session beans 3.0: Ventajas
Modelo de desarrollo simplificado
Las interfaces no necesitan extender interfaces EJB (son
POJIs)
Los métodos de la interfaz remota no necesitan arrojar
RemoteException
El bean no necesita implementar la interfaz callback
(SessionBean)
El bean puede implementar varias interfaces de negocio
de una manera natural
No existen componentes Home
No se requiere el uso de descriptores (opcional)
Agenda
Introducción
Session beans
Session beans 2.1 vs. Session beans 3.0
Analizando session beans 3.0
Inyección de dependencias
Transacciones
Entity beans
Entity beans 2.1 vs. Entity beans 3.0
Analizando entity beans 3.0
Relaciones
Herencia
JPA: Java Persistence API
Analizando JPA
Ciclo de vida de los entities
Query API y JPQL
Business Interfaces (1)
Un session bean puede implementar “n” interfaces de
negocio. La especificación preescribe que al menos una
debe implementar
Pueden ser remotas o locales y se definen con
anotaciones
Si sólo implementa una interfaz y la misma no está
anotada con la anotación @Remote o @Local se asume
que la misma es local
Si el session no implementa interfaces el container puede
generar una automáticamente
Business Interfaces (2)
Cuando las interfaces no están anotadas la accesibilidad
puede declararse en el mismo bean (de hecho el bean
puede no implementar las interfaces, aunque se
recomienda):
@Stateless
@Remote({CalculatorRm.class})
@Local({CalculatorLc.class})
public class CalculatorBean //implements CalculatorRm, CalculatorLc
{
…
}
Stateless Session beans
Se define con la anotación @Stateless
La anotación @Stateless puede opcionalmente definir un
atributo name que será el nombre JNDI con el que será
registrado el componente
@Stateless(name="Calculadora")
public class CalculatorBean implements CalculatorRm, CalculatorLc
{
public int add(int a, int b)
{
return a + b;
}
}
Stateful Session beans
Se define con la anotación @Stateful
La anotación @Stateful puede opcionalmente definir un
atributo name que será el nombre JNDI con el que será
registrado el componente
Dado que no existen homes, se utilizan métodos de la
interfaz de negocio que adopten carácter de inicializadores
de la instancia
@Remote @Local
public interface ShoppingCartRm public interface ShoppingCartLc
{ {
public void addProduct(Product p); public void addProduct(Product p);
} }
@Stateful(name="ShoppingCart")
public class ShoppingCartBean
implements ShoppingCartRm, ShoppingCartLc
{ … }
Callbacks (1)
EJB 3 evita al programador el tener que implementar
interfaces callbacks (SessionBean, por ej.)
Cuando se necesita implementar lógica en alguno o todos
los puntos del ciclo de vida de los EJB, se utilizan
anotaciones para indicar los métodos del bean que
responderán ante los mismos
Los métodos deben respetar una signature particular
Esto resulta en un modelo mucho más flexible y menos
intrusivo
Callbacks (2)
@PostConstruct: invocado luego de creada la instancia del
bean y resuelta la inyección de dependencias (Stateless,
Stateful)
@PreDestroy: invocado previa a la eliminación de la
instancia del bean (Stateless, Stateful)
@PrePasivate: invocado previo a la pasivación del bean
(Stateful)
@PostActivate: invocado luego de la activación del bean
(Stateful)
@Remove: invocado al momento de destruir la instancia
del bean. Finaliza con la vida de un session stateful
Callbacks (3)
@Stateless
public class CalculatorBean implements CalculatorRm, CalculatorLc
{
…
@PostConstruct
public void despuesDeConstruido() { … }
@PreDestroy
public void antesDeDestruir() { … }
}
@Stateful
public class ShoppingCartBean implements ShoppingCartRm, ShoppingCartLc
{
…
@PostActivate
public void luegoDeActivar() { … }
@Remove(retainIfException=true)
public void finalizarCompra() { … }
}
El atributo retainIfException indica al container si el bean debe conservarse activo aun a pesar de que el
método arroje una excepción
Interceptores (1)
EJB 3 introduce algunos conceptos de AOP de una manera
simplificada dentro del modelo de componentes
Los interceptores son métodos que se ejecutan
transparentemente antes de la invocación a los métodos
de negocio del bean
Se externalizan en clases separadas
Se aplican a sessions stateless y stateful
Interceptores (2)
Pueden definirse varios interceptores para un EJB y un
interceptor puede compartirse entre varios EJBs
Cuando varios interceptores se definen para un EJB los
mismos forman una cadena de invocación de interceptores
Existen 2 tipos:
Delegados del ciclo de vida
Interceptores AOP
Interceptores como delegados del
ciclo de vida
Los métodos anotados dentro del bean como métodos del
ciclo de vida, también pueden definirse en una clase
externa
La anotación @Interceptors define el arreglo de
interceptores que se registra para el bean
public class CalculatorCallbacks {
@PostConstruct
public void construct(InvocationContext ctx) { … }
@PreDestroy
public void destroy(InvocationContext ctx) { … }
@Stateless
@Interceptors({CalculatorCallbacks.class})
public class CalculatorBean implements CalculatorRm, CalculatorLc {
…
}
Interceptores AOP (1)
El uso más interesante de los interceptores se da cuando
de aplica al uso de AOP sobre el bean. Ej clásico:
interceptor de logging
public class LoggerInterceptor {
@AroundInvoke
public Object logger(InvocationContext inv) throws Exception
{
System.out.println("Interceptando: " + inv.getMethod().getName());
Object[] params = inv.getParameters();
for (int i=0;i<params.length;i++)
{
System.out.println("\tparam: "+params[i]);
}
return inv.proceed();
}
}
@Stateless
@Interceptors({LoggerInterceptor.class})
public class CalculatorBean implements CalculatorRm, CalculatorLc {
…
}
Interceptores AOP (2)
La anotación @AroundInvoke define al método como
método interceptor
InvocationContext es pasado por parámetro por el
container para que el método acceda al contexto de la
llamada, tal como el bean target de la invocación, método
del bean llamado, sus parámetros, etc (recordar que un
interceptor puede reusarse en varios beans)
Con InvocationContext el método puede decidir si
proceder la secuencia de ejecución (al próximo interceptor
o al bean) o abortarla
Agenda
Introducción
Session beans
Session beans 2.1 vs. Session beans 3.0
Analizando session beans 3.0
Inyección de dependencias
Transacciones
Entity beans
Entity beans 2.1 vs. Entity beans 3.0
Analizando entity beans 3.0
Relaciones
Herencia
JPA: Java Persistence API
Analizando JPA
Ciclo de vida de los entities
Query API y JPQL
Inyección de dependencias (1)
El EJB 3 container provee un mecanismo de inyección de
dependencias, o más genéricamente, recursos (referencias
a otros EJBs, datasources, sessionContext, colas de
mensajería, userTransaction, etc)
La inyección de dependencias implica la existencia de un
tercer agente diferente a las entidades “dependiente” y
“dependencia” el cual es instruido para hacer
corresponder la dependencia con el objeto dependiente
Se utiliza la anotación @Resource
El container soporta 2 mecanismos de inyección:
Inyección por campo (variable)
Inyección por setters
Inyección de dependencias (2)
Inyecciones a nivel de campo:
@Resource
SessionContext context;
TaxRate tr = (TaxRate)context.lookup(TaxRate.class.getName());
@Resource(name="jdbc/__default", type=Datasource.class)
DataSource dataSource;
…
}
Agenda
Introducción
Session beans
Session beans 2.1 vs. Session beans 3.0
Analizando session beans 3.0
Inyección de dependencias
Transacciones
Entity beans
Entity beans 2.1 vs. Entity beans 3.0
Analizando entity beans 3.0
Relaciones
Herencia
JPA: Java Persistence API
Analizando JPA
Ciclo de vida de los entities
Query API y JPQL
Transacciones (1)
El modelo de transacciones de EJB 3 permanece igual al
impuesto por EJB 2.1, excepto por el hecho de no puede
asignarse transaccionabilidad directamente a un método
de un entity
JTA API se utiliza para administrar programáticamente
transacciones
Se utilizan anotaciones para definir a nivel del session
tanto el tipo de transacción a utilizar (BMT o CMT), como
los atributos de transaccionabilidad asociados a los
métodos cuando el modelo elegido es CMT
Transacciones (2)
El tipo de transacción se define con la anotación
@TransactionManagement, la cual recibe los valores:
TransactionManagementType.CONTAINER
TransactionManagementType.BEAN
Los atributos transaccionables de los métodos se definen
con la anotación @TransactionAttribute la cual recibe los
valores:
TransactionAttributeType.MANDATORY
TransactionAttributeType.NEVER
TransactionAttributeType.NOT_SUPPORTED
TransactionAttributeType.REQUIRED
TransactionAttributeType.REQUIRES_NEW
TransactionAttributeType.SUPPORTS
Transacciones (3)
Ejemplo:
@Stateful
@TransactionManagement(TransactionManagementType.CONTAINER)
public class ShoppingCartBean implements ShoppingCartRm
{
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void addProduct(Product p) { … }
}
public String ejbCreate (String id, String street, String city) throws
CreateException
{
setAddressID(id);
setStreet(street);
setCity(city);
setZip(zip);
setState(state);
return id;
}
...
}
EJB Entity Beans 2.1 (CMP)
<enterprise-beans>
<entity>
<ejb-name>AddressBean</ejb-name>
<local-home>AddressLcHm</local-home>
<local>AddressLc</local>
<ejb-class>AddressBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>false</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>Address</abstract-schema-name>
<cmp-field>
<field-name>addressID</field-name>
</cmp-field>
<cmp-field>
<field-name>street</field-name>
</cmp-field>
<cmp-field>
<field-name>city</field-name>
</cmp-field>
<primkey-field>addressID</primkey-field>
</entity>
</enterprise-beans>
EJB Entity Beans 2.1 (CMP):
Desventajas
Necesidad de crear varios artefactos para definir el bean
(homes, interfaces, bean, descriptor)
Alto acoplamiento con la API de EJB: modelo altamente
intrusivo. Necesidad de implementación de callbacks en el
bean
Descriptores de deploy: complejidad en su mantenimiento
Complejidad en el manejo de relaciones entre entities
(CMP)
Si el entity es BMP, la dificultad en el desarrollo y en el
mantenimiento es aún mayor
Este modelo no soporta herencia ni polimorfismo
Entity bean 3.0
@Entity
@Table(name="ADDRESS")
public class AddressBean
{
private String addressId;
private String street;
private String city;
@Id
@Column(name="AddressId", primaryKey="true")
public String getAddressId() { return addressId; }
@Column(name="Street")
public String getStreet() { return street; }
@Column(name="City")
public String getCity() { return city; }
@Entity
@Table(name="ADDRESS")
public class AddressBean
{
@Column(name="Street") //Mapeo por campo
protected String street;
}
Mapeo de entity beans 3.0 (5)
Cuando el entity necesita persistirse en más de una tabla,
dichas tablas adicionales pueden indicarse con la
anotación @SecondaryTable
De esta manera, algunos campos o propiedades pueden
persistirse en la tabla principal y otros en la tabla
secundaria
@Entity
@Table(name="CUSTOMER_TABLE")
@SecondaryTable(name="ADDRESS_TABLE",
pkJoinColumns={@PrimaryKeyJoinColumn(name="ADDRESS_ID")})
public class Customer {
private long id;
private String street;
private String city;
... //campos de Customer
@Column(name="STREET", table="ADDRESS_TABLE")
public String getStreet( ) { return street; }
@Column(name="CITY", table="ADDRESS_TABLE")
public String getCity( ) { return city; }
}
Mapeo de entity beans 3.0 (6)
En el caso del ejemplo anterior la dirección se relaciona
con su cliente a través de una FK la cual es a su vez PK de
la tabla de direcciones
La anotación @PrimaryKeyJoinColumn especifica la
columna en la tabla de direcciones que hará join con la PK
de la tabla de clientes. El JPA provider deduce cuál es la
PK de la tabla de clientes
Si un entity necesita más de una tabla secundaria se
utiliza la anotación @SecondaryTables
@Entity
@Table(name="CUSTOMER_TABLE")
@SecondaryTables({
@SecondaryTable(name="ADDRESS_TABLE",
pkJoinColumns={@PrimaryKeyJoinColumn (name="ADDRESS_ID")}),
@SecondaryTable(name="CREDIT_CARD_TABLE",
pkJoinColumns={@PrimaryKeyJoinColumn (name="CC_ID")})})
public class Customer{ … }
Claves primarias (1)
En EJB 3 existen 3 formas para indicar al JPA provider cuál
es la clave primaria del POJO, en grado ascendente de
complejidad:
@Id
@IdClass
@EmbeddedId
Claves primarias (2)
La anotación @Id marca un campo o una property como
la clave primaria del mismo
Acepta tipos primitivos, wrappers de primitivos y tipos
serializables como String, java.util.Date y java.sql.Date
Sólo funciona con claves simples de un campo, no
funciona con claves compuestas
@Entity
public class Product
{
private Long id = null;
@Id
public Long getId()
{
return id;
}
}
Claves primarias (3)
La anotación @IdClass se utiliza para claves compuestas
Externaliza el comportamiento de comparación de claves
del que hace uso el JPA provider
La clase de la pk debe ser Serializable y debe tener una
implementación válida de hashCode()
El POJO conserva los campos de su pk y no necesita
conocer de la existencia de la misma
Claves primarias (4)
public class AutoPKey implements Serializable
{
String marca, modelo;
public AutoPKey() { }
@Entity
@IdClass(AutoPKey .class)
public class Auto
{
@Id
protected String marca;
@Id
protected String modelo;
public Auto() { }
...
}
Claves primarias (5)
La anotación EmbeddedId se utiliza para claves
compuestas
Similar a @IdClass excepto que el POJO sí debe conocer la
pk ya que la misma está embebida en el objeto
La pk no necesita ser Serializable
Claves primarias (6)
@Embeddable
public class AutoPKey
{
String marca, modelo;
public AutoPKey() { }
@Entity
public class Auto
{
@EmbeddedId
protected AutoPKey autoPKey;
public Auto() { }
...
}
Entities embebibles (1)
Son objetos dependientes de entities JPA
No tienen identidad propia (PK), sino que comparten la
identidad del owner
“Viven” dentro de una entidad
Normalmente se persisten en la misma tabla (y mismo
registro) que el entity padre
En caso de necesitar persistir el objeto embebible en otra
tabla, utilizar @SecondaryTable
Entities embebibles (2)
@Entity
@Table(name="USERS")
public class User implements Serializable
{
@Id
@Column(name="USER_ID", nullable=false)
protected Long userId;
...
@Embedded
protected Address address;
...
}
@Embeddable
public class Address implements Serializable
{
//Los nombres de columna hacen referencia a columnas
//de la tabla del owner ("USERS")
@Column(name="STREET", nullable=false)
protected String street;
...
@Column(name="ZIP_CODE", nullable=false)
protected String zipCode;
...
}
Agenda
Introducción
Session beans
Session beans 2.1 vs. Session beans 3.0
Analizando session beans 3.0
Inyección de dependencias
Transacciones
Entity beans
Entity beans 2.1 vs. Entity beans 3.0
Analizando entity beans 3.0
Relaciones
Herencia
JPA: Java Persistence API
Analizando JPA
Ciclo de vida de los entities
Query API y JPQL
Relaciones entre entities
JPA soporta 4 tipos de relaciones entre entities expresadas
a través de anotaciones
Uno a uno
Uno a muchos
Muchos a uno
Muchos a muchos
@Entity
public class Address
{
...
}
Relación uno a uno unidireccional
(2)
La anotación @JoinColumn establece el enlace entre las
tablas (en el esquema típicamente será una relación de FK
a PK)
@OneToOne recibe un atributo boolean optional en el cual
se indica si la relación debe ser no nula (optional=false) o
si acepta null (optional=true). El default es true
La anotación @OneToOne así como todas las anotaciones
que establecen relaciones pueden recibir un atributo
cascade que indica al motor qué operaciones realizadas
sobre un entity deben también aplicarse hacia su o sus
entities relacionados
Relación uno a uno unidireccional
(3)
El atributo cascade puede recibir un array de los
siguientes valores de la enumeración CascadeType:
PERSIST, MERGE, REMOVE, REFRESH y ALL.
CascadeType.ALL es equivalente a enumerar todos los
tipos
@Entity
public class Customer implements Serializable
{
...
@OneToOne(cascade={CascadeType.PERSIST})
@JoinColumn(name="MAILING_ADDRESS_REF",
referencedColumnName="ADDRESS_PK")
protected Address address;
...
} //Esto implica que ante una operación de
//persistencia de Customer también se persiste la Dirección
Relación uno a uno bidireccional
Implica utilizar además la anotación @OneToOne en el
otro extremo de la relación indicando la property del entity
origen que referencia a este extremo de la relación
@Entity
public class Address implements Serializable
{
...
//"address" es el nombre de la property en
//Customer que referencia a este entity
@OneToOne(mappedBy="address")
protected Customer customer;
...
}
Relación uno a muchos
unidireccional (1)
Se utiliza la anotación @OneToMany en el entity owner de
la relación:
@Entity
public class Company implements Serializable
{
...
private Collection<Employee> employees;
...
@OneToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER)
public Collection<Employee> getEmployees()
{
return employees;
}
@Entity
public class Employee
{
private int id;
private String name;
private char sex;
...
}
Relación uno a muchos
bidireccional (1)
Implica utilizar la anotación @OneToMany en el entity
origen de la relación indicando el nombre de la property
en el entity destino que participa de la relación
@Entity
public class Company implements Serializable
{
...
private Collection<Employee> employees;
...
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER,
mappedBy=”company”)
public Collection<Employee> getEmployees()
{
return employees;
}
@ManyToMany
@JoinTable(name="CATEGORY_ITEMS",
joinColumns=
@JoinColumn(name="CI_CATEGORY_ID",
referencedColumnName="CATEGORY_ID"),
inverseJoinColumns=
@JoinColumn(name="CI_ITEM_ID",
referencedColumnName="ITEM_ID"))
protected Set<Item> items;
...
}
Relación muchos a muchos (3)
El mapeo para el entity subordinado sería el siguiente:
@Entity
@Table(name="ITEMS")
public class Item implements Serializable
{
@Id
@Column(name="ITEM_ID")
protected Long itemId;
...
@ManyToMany(mappedBy="items")
protected Set<Category> categories;
...
}
Relación muchos a muchos (4)
La anotación @JoinTable describe el mapeo entre las
tablas a través de la tabla asociativa
Los atributos joinColumns e inverseJoinColumns describen
la condición de join a ambos lados de la relación
joinColumn identifica al owner de la relación (Category)
inverseJoinColumns identifica al subordinado de la relación
(Item)
Agenda
Introducción
Session beans
Session beans 2.1 vs. Session beans 3.0
Analizando session beans 3.0
Inyección de dependencias
Transacciones
Entity beans
Entity beans 2.1 vs. Entity beans 3.0
Analizando entity beans 3.0
Relaciones
Herencia
JPA: Java Persistence API
Analizando JPA
Ciclo de vida de los entities
Query API y JPQL
Herencia de entities (1)
JPA soporta 2 mecanismos para el mapeo de herencia de
entities en tablas:
Single table per class hierarchy
public Roadster()
{
numPassengers = 2;
}
// setters and getters go here
...
public Coupe()
{
numPassengers = 5;
}
// setters and getters go here
...
@Entity
@DiscriminatorValue("MOTORCYCLE")
public class Motorcycle extends RoadVehicle implements Serializable
{
...
}
@Entity
@DiscriminatorValue("CAR")
public class Car extends RoadVehicle implements Serializable
{
...
}
Single Table per Class Hierarchy
(3)
@Entity
@DiscriminatorValue("ROADSTER")
public class Roadster extends Car implements Serializable
{
...
}
@Entity
@DiscriminatorValue("COUPE")
public class Coupe extends Car implements Serializable
{
...
}
Single Table per Class Hierarchy:
Ventajas y desventajas
Ventajas:
Es eficiente en la persistencia y obtención de los
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="DISC", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("ROADVEHICLE")
public class RoadVehicle
{
...
}
Joined subclass strategy: Ventajas
y desventajas
Ventajas:
Es mejor que la estrategia anterior desde el punto de
vista de diseño
Encapsula los atributos propios de cada clase en tablas
separadas
Desventajas:
Performance: debido a que para materializar una
Lookup JNDI
Extended-scoped
el entity
@PostRemove: luego de que un entity haya sido
removido
Ciclo de vida de los entities:
callbacks (3)
Las anotaciones pueden utilizarse directamente sobre
métodos del entity o bien sobre una clase listener
separada
public class ItemMonitor {
...
public ItemMonitor() {}
@PrePersist
@PreUpdate
public void monitorItem(Item item) {
System.out.println("Monitoreando entity antes de sincronizar...")
}
}
@Entity
@EntityListeners(ItemMonitor.class)
public class Item implements Serializable {
...
}
Agenda
Introducción
Session beans
Session beans 2.1 vs. Session beans 3.0
Analizando session beans 3.0
Inyección de dependencias
Transacciones
Entity beans
Entity beans 2.1 vs. Entity beans 3.0
Analizando entity beans 3.0
Relaciones
Herencia
JPA: Java Persistence API
Analizando JPA
Ciclo de vida de los entities
Query API y JPQL
Query API
Está formada por los métodos del EntityManager para
crear queries, los métodos en la interfaz Query para
ejecutarlos y el lenguaje de consulta: JPQL
JPQL: Java Persistence Query
Languaje
Lenguaje de consulta, delete y update que opera sobre
entities
Similar a SQL pero no está orientado al mundo relacional
(tablas y columnas) sino al mundo de objetos (entities y
atributos)
Es básicamente una extensión de EJB QL 2.1 con algunas
características adicionales
Permite independizarse de la base de datos y del esquema
relacional
Permite la utilización de queries nativos en SQL
JPQL: Queries
EntityManager provee el método find para localizar
entities, de la forma:
@PersistentContext em;
...
public List findAllEmployees()
{
Query query = em.createNamedQuery("findAllEmployees");
return query.getResultList();
}
Parametrización de queries
Un query puede parametrizarse mediante 2 tipos de
parámetros:
Posicionales
Por nombre
@PersistentContext em;
...
public List findAllEmployees() {
Query query = em.createQuery(
"SELECT e FROM Employee e WHERE e.age > ?1 AND e.age < ?2");
query.setParameter(1, 25);
query.setParameter(2, 40);
return query.getResultList();
}
Parámetros por nombre
Se los identifica con un nombre o una etiqueta dentro de
la cadena del query
Mismo ejemplo: obtener todos los entities de empleados
que tienen entre 25 y 40 años
@PersistentContext em;
...
public List findAllEmployees() {
Query query = em.createQuery(
"SELECT e FROM Employee e WHERE e.age > :lowerLimit AND e.age
< :upperLimit");
query.setParameter("lowerLimit", 25);
query.setParameter("upperLimit", 40);
return query.getResultList();
}
Capacidades de Query API
Esto solo raya la superficie de esta API
JPQL agrega a EJB QL 2.1, además de
los visto:
Queries polimórficos
Updates y deletes batch (bulk)
Subqueries
Uso de JOIN, GROUP BY, HAVING
Etc.
EJB 3.0
?
Referencias
Libros:
Mastering Enterprise JavaBeans 3.0. Ed: Wiley
EJB 3 In Action. Ed: Manning
Beginning EJB 3 Application Development. Ed: Appres
Especificación en:
http://java.sun.com/products/ejb/docs.html