Está en la página 1de 206

Cuestionario de VC 2: Attempt review

ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on sábado, 13 mayo 2023, 9:58

State Finished

Completed on sábado, 13 mayo 2023, 10:00

Time taken 2 mins 34 secs

Marks 4.00/4.00

Grade 100.00 out of 100.00

Question 1
Correct

Mark 1.00 out of 1.00

Flag question

Question text

Dada la siguiente imagen del servidor wildfly que tenemos instalados :

Como se recomienda que se configure el Runtime JRE ?


a.
Como esta en la imagen con Java SE-1.8

1/4
b.
Se debe modificar la imagen y seleccionar el de alternate JRE con el jdk de nuestro Java que tenemos
instalado.

c.
En la imagen se debe modificar y colocar Java SE-10

d.
En la imagen se debe modificar y colocar Java SE-17

Feedback

Respuesta correcta

The correct answer is:


Se debe modificar la imagen y seleccionar el de alternate JRE con el jdk de nuestro Java que tenemos
instalado.

Question 2
Correct

Mark 1.00 out of 1.00

Flag question

Question text

Cuando se modifica algo en el proyecto EJB del servidor que debemos hacer para que funcionen los
cambios, si cuando hacemos el cambio el servidor está prendido (deployado).

a.
No debemos hacer nada ya que funcionan los cambios correctamente.

b.
Debemos para el servidor y parar el cliente , y arrancar el cliente para que los cambios funcionen.

c.
Debemos parar el servidor y prenderlo nuevamente para que los cambios funcionen.

d.
Debemos parar solo el cliente y luego darle start para que funcione.

Feedback

Respuesta correcta

The correct answer is:


Debemos parar el servidor y prenderlo nuevamente para que los cambios funcionen.

Question 3
Correct

Mark 1.00 out of 1.00

Flag question

2/4
Question text

En la VC descargamos la última versión de Eclipse (2023-03), vimos como debemos configurar varios
aspectos para que nuestros proyectos funcionen correctamente.

Que archivo debemos modificar para que no tenga problemas cada vez que deseamos arrancar Eclipse ?

a.
starteclipse.bat

b.
standalone.bat

c.
adduser.bat

d.
eclipse.ini

Feedback

Respuesta correcta

The correct answer is:


eclipse.ini

Question 4
Correct

Mark 1.00 out of 1.00

Flag question

Question text

Dada la siguiente imagen :

3/4
Las letras rojas en la consola nos están indicando que tenemos un error al ejecutar el cliente.

Select one:

Feedback

The correct answer is 'False'.

4/4
Cuestionario de VC 1: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Question text

Cuando se modifica algo en el proyecto EJB del servidor que debemos hacer para que
funcionen los cambios, si cuando hacemos el cambio el servidor está prendido
(deployado).

a.
Debemos para el servidor y parar el cliente , y arrancar el cliente para que los cambios
funcionen.

b.
Debemos parar el servidor y prenderlo nuevamente para que los cambios funcionen.

c.
No debemos hacer nada ya que funcionan los cambios correctamente.

d.
Debemos parar solo el cliente y luego darle start para que funcione.

Feedback

Respuesta correcta

The correct answer is:


Debemos parar el servidor y prenderlo nuevamente para que los cambios funcionen.

1/1
Cuestionario de VC 2: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on viernes, 9 junio 2023, 12:22

State Finished

Completed on viernes, 9 junio 2023, 12:23

Time taken 1 min 5 secs

Marks 4.00/4.00

Grade 100.00 out of 100.00

Question 1

Correct

Mark 1.00 out of 1.00

Flag question

Question text

En que lugar colocamos el nombre del datasource que hace referencia al esquema de la
base de datos que vamos a trabajar

a.
Dentro de jndi.properties

b.
Dentro de la carpeta entidades

c.
En el archivo persistence.xml

d.
Dentro del archivo orm.mxl

Feedback

Respuesta correcta

The correct answer is:


En el archivo persistence.xml

Question 2

1/3
Correct

Mark 1.00 out of 1.00

Flag question

Question text

Si tenemos un atributo que es enum, se le coloca encima la anotacion @Enumerated,  si


no le indicamos nada, como guarda JPA los enumerados en la tabla.

a.
Guarda el String correspondiente al enumerado

b.
Guarda dos datos el ordinal y el string

c.
Como no se especifica no se guarda nada en ese campo

d.
Guarda el numero del orden que se encuentra el dato ubicado en la clase enum

Feedback

Respuesta correcta

The correct answer is: Guarda el numero del orden que se encuentra el dato ubicado en
la clase enum

Question 3
Correct

Mark 1.00 out of 1.00

Flag question

Question text

Cual opción tenia en el proyecto creado y mostrado hoy, adentro del archivo
properties.xml, para trabajar con la base de datos, en la property que dice :

<property name="hibernate.hbm2ddl.auto" value=


a.
create-drop

2/3
b.
create

c.
update

d.
drop-create

Feedback

Respuesta correcta

The correct answer is:


create-drop

Question 4

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Para utilizar entidades que debemos configurar luego de creado el proyecto EJB

a.
El agregado de servltes

b.
seleccionar el JPA dentro de java facets

c.
crear dentro del paquete servicios las entidades

d.
crear un paquete con las entidades

Feedback

Respuesta correcta

The correct answer is: seleccionar el JPA dentro de java facets

3/3
Cuestionario de VC 1: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on viernes, 9 junio 2023, 12:23

State Finished

Completed on viernes, 9 junio 2023, 12:24

Time taken 1 min

Marks 4.00/4.00

Grade 100.00 out of 100.00

Question 1

Correct

Mark 1.00 out of 1.00

Flag question

Question text

El datasource que tenemos que crear, el recomendado es el NoXA


Select one:

Feedback

The correct answer is 'False'.

Question 2
Correct

Mark 1.00 out of 1.00

Flag question

Question text

Poniendo la siguiente anotación @Transient arriba del nombre de un atributo de una


clase, esta anotación hace que ese dato que está debajo no se persista en la base de
datos.

Select one:

1/3
Feedback

The correct answer is 'True'.

Question 3
Correct

Mark 1.00 out of 1.00

Flag question

Question text

Para utilizar entidades que debemos configurar luego de creado el proyecto EJB

a.
crear un paquete con las entidades

b.
seleccionar el JPA dentro de java facets

c.
El agregado de servltes

d.
crear dentro del paquete servicios las entidades

Feedback

Respuesta correcta

The correct answer is: seleccionar el JPA dentro de java facets

Question 4

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Cual de los siguientes drivers de oracle es el más recomendado para trabajar con
nuestras versiones de Oracle y Java:

a.

2/3
ojdbc7.jar

b.
ojdbc14.jar

c.
ojdbc6.jar

d.
ojdbc11.jar

Feedback

Respuesta correcta

The correct answer is:


ojdbc11.jar

3/3
Cuestionario de VC 4 - Semana 6: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on viernes, 16 junio 2023, 9:12

State Finished

Completed on viernes, 16 junio 2023, 9:13

Time taken 1 min 13 secs

Marks 3.00/3.00

Grade 100.00 out of 100.00

Question 1

Correct

Mark 1.00 out of 1.00

Flag question

Question text

En que se diferencia la Collection de Java List con Set


a.
La List no admite valores repetidos y la Set si.

b.
La Set no admite valores repetidos y la List si.

c.
La Set admite valores repetidos y la List no

d.
Las dos admiten valores repetidos

Feedback

Respuesta correcta

The correct answer is: La Set no admite valores repetidos y la List si.

Question 2

Correct

1/2
Mark 1.00 out of 1.00

Flag question

Question text

En la VC de hoy estuvimos viendo un ejemplo de un caso de relación de N a N, cual era


el ejemplo que vimos

a.
Ramo - Flor

b.
Libro - Autor

c.
Estudiante - Materia

d.
Rol - Funcionalidad

Feedback

Respuesta correcta

The correct answer is: Libro - Autor

Question 3

Correct

Mark 1.00 out of 1.00

Flag question

Question text

La prueba de la Unidad Curricular del miércoles que viene va a ser en la mañana y con
materiales para consultar.

Select one:

Feedback

The correct answer is 'False'.

2/2
Cuestionario de VC 3 - Semana 6: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on miércoles, 14 junio 2023, 5:45

State Finished

Completed on miércoles, 14 junio 2023, 7:21

Time taken 1 hour 35 mins

Marks 4.00/4.00

Grade 100.00 out of 100.00

Question 1

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Cuando probamos el ejercicio del proyecto PermasEJB, que tenia una relación de 1 a N
entre Persona y Mascota, en los servicios con qué método del Entity Manager creamos
las Personas y las Mascotas ?

a.
insert

b.
merge

c.
create

d.
persist

Feedback

Respuesta correcta

The correct answer is: merge

Question 2

1/3
Correct

Mark 1.00 out of 1.00

Flag question

Question text

En que se diferencia la Collection de Java List con Set


a.
La Set no admite valores repetidos y la List si.

b.
La Set admite valores repetidos y la List no

c.
La List no admite valores repetidos y la Set si.

d.
Las dos admiten valores repetidos

Feedback

Respuesta correcta

The correct answer is: La Set no admite valores repetidos y la List si.

Question 3

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Cuando vimos el método crear personas y mascotas en el cliente, estuvimos llamando a


dos métodos del servidor para crear en forma separada las mascotas y por el otro lado
las personas.

Select one:

Feedback

The correct answer is 'False'.

2/3
Question 4

Correct

Mark 1.00 out of 1.00

Flag question

Question text

En la VC de hoy estuvimos viendo un ejemplo de un caso de relación de N a N, cual era


el ejemplo que vimos

a.
Libro - Autor

b.
Estudiante - Materia

c.
Ramo - Flor

d.
Rol - Funcionalidad

Feedback

Respuesta correcta

The correct answer is: Libro - Autor

3/3
Cuestionario de VC 2 Semana 5: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on sábado, 10 junio 2023, 12:32

State Finished

Completed on sábado, 10 junio 2023, 12:44

Time taken 11 mins 9 secs

Marks 5.00/5.00

Grade 100.00 out of 100.00

Question 1

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Cuando probamos el ejercicio del proyecto PermasEJB, que tenia una relación de 1 a N
entre Persona y Mascota, en los servicios con qué método del Entity Manager creamos
las Personas y las Mascotas ?

a.
persist

b.
merge

c.
create

d.
insert

Feedback

Respuesta correcta

The correct answer is: merge

Question 2

1/4
Correct

Mark 1.00 out of 1.00

Flag question

Question text

En que se diferencia la Collection de Java List con Set


a.
La Set no admite valores repetidos y la List si.

b.
La Set admite valores repetidos y la List no

c.
Las dos admiten valores repetidos

d.
La List no admite valores repetidos y la Set si.

Feedback

Respuesta correcta

The correct answer is: La Set no admite valores repetidos y la List si.

Question 3

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Con que Entidad presentamos el ejemplo de usar la anotación @Embeddable


a.
Calle

b.
Usuario

c.
Persona

2/4
d.
Piso

Feedback

Respuesta correcta

The correct answer is:


Usuario

Question 4

Correct

Mark 1.00 out of 1.00

Flag question

Question text

En la VC de hoy estuvimos viendo un ejemplo de un caso de relación de N a N, cual era


el ejemplo que vimos

a.
Libro - Autor

b.
Estudiante - Materia

c.
Rol - Funcionalidad

d.
Ramo - Flor

Feedback

Respuesta correcta

The correct answer is: Libro - Autor

Question 5
Correct

Mark 1.00 out of 1.00

Flag question

Question text

3/4
De acuerdo a lo visto en la VC y un link que está en la semana 5 y 6, se deben anotar
colocando el nombre del grupo en una planilla para seleccionar fecha y hora para hacer
una meet para comentar como van con el proyecto colaborativo de la semana 5 y 6.

Select one:

Feedback

The correct answer is 'True'.

4/4
Cuestionario de VC 1 Semana 5: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on martes, 6 junio 2023, 5:01

State Finished

Completed on martes, 6 junio 2023, 5:10

Time taken 8 mins 50 secs

Marks 2.00/4.00

Grade 50.00 out of 100.00

Question 1

Incorrect

Mark 0.00 out of 1.00

Flag question

Question text

De acuerdo a lo visto en la VC y un link que está en la semana 5 y 6, se deben anotar


colocando el nombre del grupo en una planilla para seleccionar fecha y hora para hacer
una meet para comentar como van con el proyecto colaborativo de la semana 5 y 6.

Select one:

Feedback

The correct answer is 'True'.

Question 2
Incorrect

Mark 0.00 out of 1.00

Flag question

Question text

En la VC de hoy estuvimos viendo un ejemplo de un caso de relación de N a N, cual era


el ejemplo que vimos

1/3
a.
Rol - Funcionalidad

b.
Ramo - Flor

c.
Libro - Autor

d.
Estudiante - Materia

Feedback

Respuesta incorrecta.

The correct answer is: Libro - Autor

Question 3

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Con que Entidad presentamos el ejemplo de usar la anotación @Embeddable


a.
Piso

b.
Persona

c.
Usuario

d.
Calle

Feedback

Respuesta correcta

The correct answer is:


Usuario

2/3
Question 4

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Cuando probamos el ejercicio del proyecto PermasEJB, que tenia una relación de 1 a N
entre Persona y Mascota, en los servicios con qué método del Entity Manager creamos
las Personas y las Mascotas ?

a.
create

b.
merge

c.
persist

d.
insert

Feedback

Respuesta correcta

The correct answer is: merge

3/3
Cuestionario de VC 1: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on miércoles, 31 mayo 2023, 2:14

State Finished

Completed on miércoles, 31 mayo 2023, 2:15

Time taken 1 min 21 secs

Marks 3.00/3.00

Grade 100.00 out of 100.00

Question 1

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Las Named Querys, donde se definen para que funcionen ?


a.
En el cliente

b.
En el servidor en el bean de sesion que maneja la entidad

c.
No hay una opción correcta.

d.
En el servidor dentro de la entidad .

Feedback

Respuesta correcta

The correct answer is:


En el servidor dentro de la entidad .

Question 2

1/3
Correct

Mark 1.00 out of 1.00

Flag question

Question text

Dentro de las definiciónes de las entidades, si selecciono el generated value como


.AUTO, y tengo que trabajar con 4 entidades, puedo decir que todas las entidades sus id
van a arrancar desde 1.

Select one:

Feedback

The correct answer is 'False'.

Question 3

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Para persistir en la base de datos tenemos que usar el EntityManager, para eso, para dar
de alta precisamos el metodo :

a.
persist

b.
save

c.
dispatch

d.
insert table

Feedback

Respuesta correcta

The correct answer is:

2/3
persist

3/3
Cuestionario de VC 1: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on lunes, 15 mayo 2023, 7:46

State Finished

Completed on lunes, 15 mayo 2023, 7:48

Time taken 2 mins 37 secs

Marks 3.00/4.00

Grade 75.00 out of 100.00

Question 1

Correct

Mark 1.00 out of 1.00

Flag question

Question text

Para poder aprobar esta unidad curricular no es necesario contestar los cuestionarios
luego de las Vc .

Select one:

Feedback

The correct answer is 'False'.

Question 2

Correct

Mark 1.00 out of 1.00

Flag question

Question text

En la VC de hoy cuantos ejemplos vimos de proyectos EJB su explicación y ejecución :

c.
1

1/3
d.
2

Feedback

Respuesta correcta

The correct answer is:


3

Question 3
Incorrect

Mark 0.00 out of 1.00

Flag question

Question text

Puede ser que no coloquemos el archivo jndi.properties en el proyecto cliente, y el


Cliente se pueda conectar con el servidor.

Select one:

Feedback

The correct answer is 'True'.

Question 4

Correct

Mark 1.00 out of 1.00

Flag question

Question text

En el proyecto cliente, como asociamos a este el proyecto el servidor que le corresponde


?

a.
En buildpath y dentro de este en Projects y lo colocamos en classPath

2/3
b.
En buildpath y dentro de este en Projects y lo colocamos en modulePath

c.
En buildpath y dentro de este en Source y lo colocamos en classPath

d.
En buildpath y dentro de este en Libraries y lo colocamos en classPath

Feedback

Respuesta correcta

The correct answer is:


En buildpath y dentro de este en Projects y lo colocamos en classPath

3/3
Cuestionario - individual: Attempt review
ev1.utec.edu.uy/moodle/mod/quiz/review.php

Started on jueves, 11 mayo 2023, 9:03

State Finished

Completed on jueves, 11 mayo 2023, 9:12

Time taken 9 mins 13 secs

Marks 80.00/80.00

Grade 100.00 out of 100.00

Question 1

Correct

Mark 5.00 out of 5.00

Flag question

Question text

Los sistemas de base de datos están contenidos dentro de la capa EIS

Select one:

Feedback

The correct answer is 'True'.

Question 2
Correct

Mark 5.00 out of 5.00

Flag question

Question text

Algunas de las características de Java EE son:

Select one or more:

a.

1/8
Aplicaciones distribuidas

b.
Proveen mecanismos de seguridad

c.
Los componentes de lógica de negocios no son reutilizables

d.
Multicapa

e.
Basada en componentes

f.
Depende de la plataforma

Feedback

Respuesta correcta

The correct answers are: Multicapa, Aplicaciones distribuidas, Proveen mecanismos de


seguridad, Basada en componentes

Question 3

Correct

Mark 5.00 out of 5.00

Flag question

Question text

Los servlets son componentes Web que se ejecutan en el lado del cliente

Select one:

Feedback

The correct answer is 'False'.

Question 4

2/8
Correct

Mark 5.00 out of 5.00

Flag question

Question text

Los componentes web contienen la lógica que resuelve las necesidades del negocio.

Select one:

Feedback

The correct answer is 'False'.

Question 5
Correct

Mark 5.00 out of 5.00

Flag question

Question text

Los Enterprise JavaBeans (beans enterprise) son componentes de negocio que se


ejecutan en el servidor de aplicación

Select one:

Feedback

The correct answer is 'True'.

Question 6

Correct

Mark 5.00 out of 5.00

Flag question

Question text

Un archivo EAR contiene módulos Java EE y descriptores de despliegue.

Select one:

3/8
Feedback

The correct answer is 'True'.

Question 7
Correct

Mark 5.00 out of 5.00

Flag question

Question text

Los  mismos componentes de una aplicación Java EE se comportan siempre de igual


manera, no importando donde se desplieguen.

Select one:

Feedback

The correct answer is 'False'.

Question 8

Correct

Mark 5.00 out of 5.00

Flag question

Question text

Un componente Java EE es:

Select one:

a.
Una unidad de software modular y funcional que se comunica con otros componentes

b.
Es una pequeña aplicación cliente que se ejecuta en la máquina virtual Java instalada
en el navegador web

c.
Son objetos que sirven para comunicar la capa servidor con la cliente

4/8
Feedback

Respuesta correcta

The correct answer is: Una unidad de software modular y funcional que se comunica con
otros componentes

Question 9
Correct

Mark 5.00 out of 5.00

Flag question

Question text

El proceso de despliegue instala los componentes de aplicaciones Java EE en los


contenedores Java EE

Select one:

Feedback

The correct answer is 'True'.

Question 10

Correct

Mark 5.00 out of 5.00

Flag question

Question text

Los componentes Web Java EE son servlets o páginas web creadas usando la
tecnología JavaServer Faces y / o la tecnología JSP

Select one:

Feedback

The correct answer is 'True'.

Question 11
Correct

5/8
Mark 5.00 out of 5.00

Flag question

Question text

Un cliente web a veces se llama un cliente pesado porque suelen realizar consultas a la
base de datos y tener reglas de negocios complejas.

Select one:

Feedback

The correct answer is 'False'.

Question 12

Correct

Mark 5.00 out of 5.00

Flag question

Question text

Los módulos web  son empaquetados en archivos comprimidos con una extensión .war

Select one:

Feedback

The correct answer is 'True'.

Question 13
Correct

Mark 5.00 out of 5.00

Flag question

Question text

Un EJB es:

Select one:

a.

6/8
Un componente de negocio que se ejecuta en el servidor

b.
Un componente Web que se ejecuta en el servidor

c.
Un servidor Java EE que proporciona contenedores

Feedback

Respuesta correcta

The correct answer is: Un componente de negocio que se ejecuta en el servidor

Question 14

Correct

Mark 5.00 out of 5.00

Flag question

Question text

Las Aplicaciones Clientes y los Applets son componentes que se ejecutan en el lado del
cliente

Select one:

Feedback

The correct answer is 'True'.

Question 15
Correct

Mark 5.00 out of 5.00

Flag question

Question text

Algunas de las características fundamentales de Java EE son la productividad,


portabilidad y seguridad.

Select one:

7/8
Feedback

The correct answer is 'True'.

Question 16

Correct

Mark 5.00 out of 5.00

Flag question

Question text

Generalmente hay un sólo tipo de cliente Java EE que son los clientes Swing

Select one:

Feedback

The correct answer is 'False'.

8/8
 
 
 

Enterprise Java Beans


 

¿Qué es un Enterprise Java Bean?


 
Un  enterprise  java  bean  (EJB)  es   un  componente  del  lado  del  servidor  que  encapsula  la 
lógica de negocio de una aplicación.  
La  lógica  de  negocio  es  el  código  que  contiene  las  reglas  de  negocio  y  de  proceso  de   una 
aplicación.  En  una  aplicación  de  stock  de  productos,  por  ejemplo,  los  EJBs  pueden 
implementar  su  lógica  de  negocio  en  los  métodos  “agregarProducto”  o 
“chequearStockProducto”.  Al  invocar   estos  métodos,  se  puede  acceder  a  los  servicios  de 
stock de productos que proporciona la aplicación. 

Ventajas del uso de EJBs 


 
Se  podría  decir  que  la  mayor  ventaja  del  uso  de  EJBs  es  simplificar  el  desarrollo  de 
aplicaciones distribuídas.  
Esto  es  debido  a  que  el  contenedor  EJB brinda servicios a nivel de sistema de modo que el 
desarrollador   puede  concentrarse  en  resolver  los problemas de negocio. El contenedor EJB 
es responsable de los servicios como la gestión de transacciones y seguridad. 
Además  como  los beans contienen la lógica  de negocio de la aplicación, el  desarrollador del 
cliente  puede  centrarse  en   la  presentación.  El  desarrollador  no  tendrá  que  programar  las 
rutinas  que  implementan  reglas  de  negocio o bases de datos de acceso; de manera que los 
clientes serán más ligeros. 
También  como  los  enterprise  beans  son  componentes  portables,  el  ensamblador  de 
aplicaciones podrá crear  nuevas aplicaciones con los beans existentes. Siempre que utilicen 
las  API  estándar,  estas  aplicaciones  se  pueden   ejecutar  en  cualquier  servidor  compatible 
con Java EE. 

Cuándo conviene utilizar EJBs


● Cuando  la  aplicación  debe   escalar.  Si  la  aplicación  puede  tener  un  número  de 
usuarios  en  aumento,  es  posible  que  necesite  distribuir  los  componentes  de  la 
aplicación  en  varias  máquinas. Los EJBs podrán ser distribuidos en varias máquinas 
siendo esto transparente para la aplicación. 
● Cuando  se  quiere  garantizar  la  integridad  de  los  datos. Los EJBs permiten el uso de 
transacciones  y  los  mecanismos  que  gestionan  el  acceso  concurrente  de  objetos 
compartidos. 
● Cuando  la  aplicación tiene clientes variados. Un EJB puede interactuar con una gran 
gama de clientes. 

Tipos de EJBs
● Bean de sesión: representa un proceso o una acción de negocio. En general, 
cualquier llamada a un servicio debería comenzar con una llamada a un bean de 
 
sesión. Conceptualmente se asocian los beans de sesión con los verbos: 
agregarProducto, chequearStockProducto, etc. 
● Beans dirigidos por mensajes (MDBs): pueden escuchar mensajes de un servicio de 
mensajes JMS (Java Message Service). Los clientes de estos beans nunca los 
llaman directamente, sino que es necesario enviar un mensaje JMS para 
comunicarse con ellos. Un ejemplo de bean dirigido por mensajes podría ser un 
bean ListenerNuevoProducto que se activa cada vez que se envía un mensaje 
comunicando que se ha dado de alta a un nuevo producto. 
 

Bean de Sesión
Los  beans  de sesión representan sesiones interactivas con uno  o más clientes. Los bean de 
sesión  pueden  mantener  un  estado,  pero  sólo  durante  el  tiempo  que  el  cliente  interactúa 
con  el bean. Esto significa que los beans de sesión no almacenan sus datos en una base de 
datos  después  de que el cliente termine el proceso. Por ello se suele decir que los beans de 
sesión no son persistentes. 
Existe  una  correspondencia  uno  a  uno  entre  beans  de  sesión  y  clientes.  Por  esto,  el 
contenedor  EJB  no   necesita  implementar  mecanismos  de  manejo  de  concurrencia  en  el 
acceso a estos beans. 
 
Los beans de sesión pueden ser de tres tipos: con estado, sin estado, y singleton. 

Beans de sesión con estado


El estado de un objeto consiste en los valores de sus variables de instancia.  
En  un  bean  de  sesión  con  estado,  las  variables  de  instancia  representan  el  estado  de  una 
sesión  de  cliente  /  bean  único.  Debido  a  que  el  cliente  interactúa  (  "habla"),  con  su  bean, 
este estado se llama a menudo “estado de conversación”. 
El estado se mantiene durante la duración de la sesión del cliente / bean.  
Un  ejemplo  típico  de  bean  de  sesión  con  estado  es  un  carrito  de  compra,  en  donde  el  
cliente va guardando uno a uno los ítem que va comprando. 
 

Beans de sesión sin estado


Un  bean  de  sesión  sin  estado  no  mantiene  un  estado  de  conversación  con  el  cliente. 
Cuando  un  cliente  invoca  los  métodos  de  un  bean   sin  estado, las variables de instancia del 
bean  pueden  contener   un  estado  específico  para  ese  cliente,  pero  sólo durante la duración 
de  la  invocación.  Cuando  se  termina el procedimiento, el estado específico del cliente no se 
mantiene.  
Esta  propiedad   permite  que  el  contenedor  EJB  pueda  crear  una  reserva  (​ pool)​
  de 
instancias,  todas  del  mismo  bean  de  sesión  sin  estado  y  asignar  cualquier  instancia   a 
cualquier  cliente.  Incluso  un  único bean puede estar asignado a múltiples clientes, ya que la 
asignación sólo dura el tiempo de invocación del método solicitado por el cliente. 
 
Como  este  tipo  de  beans  pueden  dar  soporte  a  múltiples  clientes,  ofrecen  una  mejor 
escalabilidad  para  aplicaciones  que  requieren  un  gran  número  de  clientes.  Por  lo  general, 
una  aplicación  requiere  un  menor  número  de  beans  de  sesión  sin  estado  que  beans  de 
sesión con estado para atender el mismo número de clientes. 
 

Beans de sesión Singleton


Un  bean  de  sesión  Singleton  se  instancia  una  vez  por  aplicación  y  existe  para  el  ciclo  de 
vida de la aplicación.  
Este  tipo  de  beans  están  diseñados para circunstancias en las que  una sola instancia de un 
bean  enterprise  se  comparte  por   los  clientes  en  forma  concurrente  durante  toda  la 
aplicación. 
Son  similares  a  los  beans  de  sesión sin estado pero se diferencian de ellos en que sólo hay 
un  único  bean  de  sesión  por  aplicación,  en  lugar  de  un   conjunto  de  beans  de  sesión  sin 
estado, cualquiera de los cuales pueden responder a una petición de cliente. 
 
 

Message Driven Bean (MDB)


Un  MDB  es  un  EJB  que  permite  a  las  aplicaciones  Java  EE  procesar  mensajes  de  forma 
asíncrona.  Este  tipo  de  bean  en  general  actúa  como  un  receptor  de mensajes JMS, que es 
similar a un detector de eventos.  
Los  mensajes  se  pueden  enviar  por  cualquiera  de  los  componentes  de  Java EE (un cliente 
de  aplicación,   un  EJB,  o  un  componente  web)  o  por  una  aplicación  JMS  o  un  sistema  que 
no  utiliza  la  tecnología Java EE. Los MDBs pueden procesar mensajes JMS u otros tipos de 
mensajes. 
 
En muchos aspectos, un MDB es parecido a un bean de sesión sin estado. 
● Las  instancias  de  un  MDB  no  almacenan  ningún  estado  conversacional  ni  datos  de 
clientes. 
● Todas  las  instancias  de  los  MDBs  son  equivalentes,  lo  que  permite  al  contenedor 
EJB  asignar  un mensaje a cualquier instancia. El contenedor puede almacenar estas 
instancias  para   permitir  que  los   streams  de  mensajes  sean  procesados  de  forma 
concurrente. 
● Un único MDB puede procesar mensajes de múltiples clientes. 
 
Las  variables  de  instancia  de  estos  beans pueden contener algún estado  referido al manejo 
de  los  mensajes de los clientes. Pueden contener una conexión JMS, una conexión de base 
de datos o una referencia a un EJB. 
 
Cuando  llega  un  mensaje,  el  contenedor  EJB  llama  al  método  “onMessage”   del  bean.  El 
método  onMessage  suele  realizar  un  casteo  del  mensaje  a  uno  de  los  cinco  tipos  de 
mensajes de JMS y manejarlo de forma acorde con la lógica de negocio de la aplicación.  
 
Un  mensaje  puede  enviarse  a  un  MDB  dentro  de  un  contexto  de  transacción,  por  lo  que 
todas las operaciones dentro del método onMessage son parten de un única transacción. 

Acceso a Beans de sesión


 
Los clientes van a acceder a los EJBs de dos maneras posibles: a través de una vista sin 
interfaz o a través de una interfaz de negocio (local o remota).  
 
Todos los métodos públicos del bean (incluyendo aquellos definidos en superclases) están 
disponibles en la vista sin interfaz. 
Los clientes que utilizan la vista sin interfaz de un EJB pueden invocar cualquier método 
público de la clase de implementación del EJB o cualquier superclase de la implementación.  
 
Una interfaz de negocio es una interfaz estándar de lenguaje de programación Java que 
contiene los métodos de negocio del EJB. 
 
Un cliente puede acceder a un bean de sesión sólo a través de los métodos definidos en la 
interfaz de negocio del bean o por medio de los métodos públicos de un EJB con una vista 
sin interfaz.  
 
Es importante tener un modelo de interfaces bien diseñado ya que esto simplifica el 
desarrollo y mantenimiento de la aplicación Java EE.  
 
No sólo las interfaces limpias y las vistas sin interfaz protegen a los clientes de cualquier 
complejidad en el nivel de EJB, sino que también permiten a los EJBs cambiar internamente 
sin afectar a los clientes. Por ejemplo, si cambia la implementación de un método de 
negocio de bean de sesión, no se tendrá que modificar el código del cliente. Pero si tuviera 
que cambiar las definiciones de métodos de las interfaces, es posible que tenga que 
modificar el código del cliente también. Por lo tanto, es importante que el diseño de las 
interfaces y los accesos de vista sin interfaz estén pensados cuidadosamente para evitar 
que los clientes deban realizar cambios al acceder a los EJBs. 
 
Los beans de sesión pueden tener más de una interfaz de negocio. Los beans de sesión 
deben, pero no están obligados a, implementar una interfaz o interfaces de negocio. 
 
Si el bean no expone ninguna interfaz remota o local, entonces el contenedor tiene que 
dejar disponible una vista sin interfaz. En cambio, si el bean expone al menos una interfaz 
remota o una local, entonces el contenedor no provee una vista sin interfaz (a menos que se 
pida explícitamente usando la anotación ​ LocalBean 

Usando EJBs en Clientes


El cliente de un EJB obtiene una referencia a una instancia de un bean enterprise, ya sea a 
través de la inyección de dependencia, mediante anotaciones de lenguaje de programación 
Java, o búsqueda JNDI, utilizando la sintaxis de Java Naming and Directory Interface para 
encontrar la instancia del EJB. 
 
La inyección de dependencia es la forma más sencilla de obtener una referencia a un EJB.  
La inyección de dependencia es una técnica popular en el desarrollo de aplicaciones 
empresariales java, en donde un componente especifica los recursos de los que depende. 
 
 
 
Un inyector, típicamente un contenedor, proporciona los recursos al componente. Aunque la 
inyección de dependencia puede ser implementado de varias maneras, en general se 
realiza con anotaciones. 
 
Los clientes que ejecutan en un entorno gestionado por el servidor Java EE, JavaServer 
Faces aplicaciones web, servicios web JAX­RS, otros EJBs, o clientes de aplicaciones Java 
EE soportan la inyección de dependencias utilizando anotaciones java. 
Una anotación java una es una forma de añadir metadatos al código fuente Java que están 
disponibles para la aplicación en tiempo de ejecución. 
 
Las aplicaciones que se ejecutan fuera de un entorno gestionado por el servidor Java EE, 
tales como aplicaciones Java SE, deben realizar una búsqueda explícita. JNDI soporta una 
sintaxis global para la identificación de los componentes de Java EE para simplificar las 
operaciones de búsqueda este explícita. 

Sintaxis JNDI
Existen tres espacios de nombres JNDI que se utilizan para las búsquedas: java:global , 
java:module , y java:app . 
● java:global es la manera portable de encontrar EJBs remotos mediante búsquedas 
JNDI. Las direcciones JNDI son de la siguiente forma: 
application name]​
java:global[/​ module name/​
/​ enterprise bean name[​
​ interface name]​
/​  
 
● java:module se utiliza para buscar EJBs locales dentro del mismo módulo. Las 
direcciones JNDI son de la siguiente forma: 
java:module/​ enterprise bean name/​ interface name]​
[​  
 
● La java:app se utiliza para buscar EJBs locales envasados ​ ​
dentro de la misma 
aplicación. Es decir, el EJB se empaqueta en un archivo EAR que contiene múltiples 
módulos Java EE. Las direcciones JNDI son de la siguiente forma: 
java:app[/​module name]​ enterprise bean name[​
/​ interface name]​
/​  
 
Por ejemplo: supongamos que tengo un EJB llamado MiPrimerEJB, que se empaqueta 
dentro del archivo web miPrimerApp.war y el nombre del módulo es miPrimerApp. El 
nombre JNDI portable es java:module/MiPrimerEJB . Un nombre JNDI equivalente 
utilizando el java:global es java:global/miPrimerApp/MiPrimerEJB . 
 

La decisión sobre acceso remoto o local


Cuando se diseña una aplicación Java EE, una de las primeras decisiones que hay que 
tomar es el tipo de acceso que le voy a permitir al cliente para acceder a los EJBs: remoto, 
local o usando web services. 
 
Ya sea para permitir el acceso local o remoto depende de los siguientes factores. 
● Alto acoplamiento: Por ejemplo, si un bean de sesión que procesa los pedidos de 
cliente llama a otro bean de sesión que envía correo electrónico con la confirmación 
 
al cliente, estos EJBs están estrechamente unidos. Estos son buenos candidatos 
para el acceso local. Encajan entre sí como una unidad lógica, que normalmente se 
llaman entre sí a menudo y se beneficiarían del aumento de rendimiento que es 
posible con el acceso local. 
● Tipo de cliente: Si un EJB se accede por clientes de la aplicación, se debe permitir el 
acceso remoto. En un entorno de producción, estos clientes casi siempre se 
ejecutan en máquinas distintas de aquellas en las que se ejecuta el servidor JavaEE. 
Si los clientes que acceden al EJB son componentes web u otros EJBs, el tipo de 
acceso depende de cómo desea distribuir sus componentes: si van en el mismo 
servidor o en otros. 
● La distribución de componentes: las aplicaciones Java EE son escalables porque 
sus componentes pueden ser distribuidos a través de múltiples máquinas. En una 
aplicación distribuida, por ejemplo, el servidor en el que los componentes web corren 
puede no ser el mismo en el que los EJBs están desplegados. En este escenario 
distribuido, los EJBs deben permitir el acceso remoto. 
● Rendimiento: Debido a factores tales como la latencia de la red, las llamadas 
remotas puede ser más lentas que las llamadas locales. Por otro lado, si distribuye 
componentes entre los diferentes servidores, es posible mejorar el rendimiento 
general de la aplicación. 
 
Si no se está seguro de qué tipo de acceso debe tener un EJB, debería elegir el acceso 
remoto ya que da más flexibilidad. Esto permitirá distribuir sus componentes para escalar la 
aplicación. 
 
También es posible que un EJB permita el acceso remoto y local. Si este es el caso, se 
necesitará una interfaz remota y otra local. La misma interfaz de negocio no puede ser a la 
vez una interfaz local y remota. 

Los clientes locales


 
Un cliente local: 
● Debe correr en la misma aplicación a la que accede el EJB. 
● Puede ser un componente Web u otro EJB. 
 
La vista sin interfaz de un EJB es una vista local. Los métodos públicos de la clase de 
implementación de un EJB están expuestos a los clientes locales que acceden a la vista sin 
interfaz del EJB. Los EJBs que utilizan la vista sin interfaz no implementan una interfaz de 
negocio. 
 
La interfaz de negocio local define los métodos y el ciclo de vida del bean.  
Si interfaz de negocio del bean no está anotada con @Local o @Remote , y si la clase de 
bean no especifica la interfaz mediante @Local o @Remote, la interfaz de negocio es por 
defecto una interfaz local. 
 
 
Para construir un EJB que permite sólo el acceso local, se puede seguir uno de los 
siguientes pasos: 
● Crear una clase de implementación de EJB que no implementa una interfaz de 
negocio, lo que significa que el bean expone una vista sin interfaz a los clientes. Por 
ejemplo: 
@LocalBean 
 public class myBean {...} 
 
● Anotar la interfaz de negocio como @Local. Por ejemplo: 
@Local 
 public interface InterfaceName { ... } 
 
● Especificar la interfaz mediante la anotación @Local y el nombre de la interfaz. Por 
ejemplo: 
@Local(​ InterfaceName​ .class) 
public class ​BeanName​  implements ​InterfaceName ​
{ ... } 
 

Accediendo EJBs locales utilizando la vista sin interfaz


Para acceder a un EJB con estas características se puede utilizar:  inyección de 
dependencia o de búsqueda JNDI. 
● Para obtener una referencia a la vista sin interfaz de un EJB utilizando la inyección 
de dependencias: 
● @EJB 
 MiPrimerBean miPrimerBean; 
Siendo MiPrimerBean el nombre de la clase del EJB 
 
● Para obtener una referencia a la vista sin interfaz de un EJB utilizando la búsqueda 
JNDI: 
MiPrimerBean miPrimerBean = (MiPrimerBean)InitialContext.lookup 
("java:module/MiPrimerBean"); 
 
Los clientes no utilizan el operador new para obtener una nueva instancia de un EJB que 
utiliza una vista sin interfaz. 

Accediendo EJBs locales que implementan interfaces


El acceso se lleva a cabo a través de inyección de dependencia o de búsqueda JNDI. 
● Para obtener una referencia a la interfaz de negocio local de un EJB utilizando la 
inyección de dependencias, se debe utilizar la anotación  javax.ejb.EJB y especificar 
el nombre de interfaz de negocio local: 
@EJB 
 Ejemplo ejemplo; 
 
● Para obtener una referencia a una interfaz de negocio local de un EJB utilizando la 
búsqueda JNDI, se debe utilizar el método lookup de javax.naming.InitialContext: 
 
EjemploLocal ejemploLocal = (EjemploLocal)InitialContext.lookup 
("java:module/EjemploLocal"); 
 

Los clientes remotos


Un cliente remoto de un EJB tiene las siguientes características. 
● Se puede ejecutar en una máquina diferente y una JVM diferente de la que está el 
EJB. (No es necesario para ejecutar en una JVM diferente). 
● Puede ser un componente web, un cliente de aplicación, u otro EJB. 
● Para un cliente remoto, la ubicación del EJB es transparente. 
● El EJB debe implementar una interfaz de negocio. Es decir, los clientes remotos no 
pueden acceder a un EJB a través de una vista sin interfaz. 
 

Para crear un EJB que permita el acceso remoto, o bien debe 
● Anotar la interfaz de negocio del EJB con @Remote 
@Remote 
public interface InterfaceName { ... } 
 
● O anotar con @Remote la clase del EJB y especificando la interfaz o interfaces de 
negocio: 
@Remote(InterfaceName.class) 
public class BeanName implements InterfaceName { ... } 
 
La interfaz remota define los métodos de negocio y el ciclo de vida que son específicos para 
el EJB. Por ejemplo, la interfaz remota de un bean llamado StockProductosBean podría 
tener los métodos de negocio agregarProducto y quitarProducto  
 
El acceso de un cliente a un EJB que implementa una interfaz de negocio remota se lleva a 
cabo a través de inyección de dependencia o de búsqueda JNDI. 
● Para obtener una referencia a la interfaz de negocio remota de un EJB a través de la 
inyección de dependencias, se debe utilizar la anotación javax.ejb.EJB y especificar 
el nombre de interfaz de negocio remota: 
@EJB 
 Ejemplo ejemplo; 
 
● Para obtener una referencia a una interfaz de negocios remota de un EJB a través 
de la búsqueda JNDI, se debe utilizar el método lookup del 
javax.naming.InitialContext: 
ExampleRemote example = (ExampleRemote) 
        InitialContext.lookup("java:global/myApp/ExampleRemote"); 
 

El contenido de un Bean Enterprise


Para desarrollar un EJB se deben generar los siguientes archivos: 
● Clase EJB: Implementa los métodos de negocio del EJB. 
● Interfaces: Define los métodos de negocio implementados por la clase EJB. No se 
requiere una interfaz de negocio si el EJB expone una vista local sin interfaz. 
● Clases de ayuda: Otras clases que necesita la clase EJB, tales como excepciones y 
servicios públicos. 
 
Los archivos anteriores se empaquetan ya sea en un archivo JAR EJB (un módulo 
independiente que se almacena el EJB) o dentro de un módulo de archivo de la aplicación 
Web (WAR).  
 
Métodos asíncronos
 
Los EJBs pueden implementar métodos asincrónicos​ : ​
son métodos donde se devuelve el 
control al cliente a través del contenedor antes de invocar el método en la instancia de bean 
de sesión. El resultado del método se devuelve al contenedor y no al cliente, por lo que el 
cliente no percibe demoras y puede seguir trabajando. 
Este tipo de métodos se utilizan normalmente para operaciones de larga duración, para las 
tareas de uso intensivo del procesador, para tareas en segundo plano, para aumentar el 
rendimiento de aplicaciones, o para mejorar el tiempo de respuesta de la aplicación. 
 
Ejemplo: 
@Asynchronous 
public void enviarMail(String texto) { 
    ...  

 
 
 
 

Introducción a Aplicaciones Enterprise


 

Aplicaciones empresariales
 
En  la  actualidad  cada vez más se necesita el desarrollo de aplicaciones empresariales. Qué 
son  las  aplicaciones empresariales? Son sistemas que integran  distintas partes del negocio, 
por  ejemplo,  recursos  humanos,  contabilidad,  manejo  de  recursos,  etc.  Gracias  a  este  tipo 
de  aplicaciones,  las  empresas  pueden  aumentar  su  rendimiento  a  un  bajo  costo,  teniendo  
todo integrado en un mismo sistema. 

Modelo Java EE
El  modelo  Java  EE  tiene  como  protagonistas  el  lenguaje  de  programación  Java  y  la 
máquina virtual de Java.  
Las  características  fundamentales  de  este  tipo  de  aplicaciones  son  la  productividad, 
portabilidad y seguridad.  
 
Java  EE   es  un  conjunto  de  especificaciones   Java   que  brindan  la  funcionalidad  necesaria 
para  el  desarrollo  de  aplicaciones  empresariales.  Este  tipo de aplicaciones pueden ser muy 
complejas,  ya   que  pueden  acceder  datos  de  una  gran  variedad  de  fuentes  y  que requieran 
que la aplicación sea distribuida a una gran cantidad de clientes. 
 
Java  EE  incluye  muchos  componentes  de Java Standard Edition, llamada Java SE. JavaSE 
es  un  kit  de  desarrollo  de  software  que  se  utiliza  para   escribir  applets  y aplicaciones con el 
lenguaje  de  programación  Java.  Este  kit  es  el  que  han  utilizado  hasta  el  momento  para las 
materiales  Java  que  ya  tuvieron.  Java  EE  no   es  un  reemplazo  de  Java  SE:  Java  SE 
proporciona el soporte de lenguaje básico sobre el que Java EE ejecuta. 
 
 

 
El  modelo  Java  EE  define   una  arquitectura  para  la  implementación  de  servicios  como 
aplicaciones  de  varios  niveles  que  ofrecen  a  escalabilidad,  accesibilidad  y  capacidad  de 
gestión necesaria para aplicaciones empresariales. 
 
 
Si pensamos en una aplicación empresarial estándar, necesitaremos 3 capas: 
● Capa  de  presentación:  encargada  de  desplegar  y  obtener  información  para  el 
usuario 
● Capa de negocios: encargada de los procesos y reglas de negocio 
● Capa  de  acceso  a  datos:  toda  aplicación requiere alguna forma de persistencia (leer 
/ almacenar datos) 
 
Las aplicaciones Java EE se suelen distribuir en tres lugares diferentes: 
● La máquina cliente 
● La máquina servidor (Servidor Java EE) 
● Base  de  datos  o  sistemas   legados  (Sistema  legado:  se  trata  de  un  sistema 
informático  que  ha  quedado  obsoleto  pero  continúa  siendo  utilizado  por  el usuario y 
no se quiere o no se puede reemplazar o actualizar de forma sencilla) 
 
Java  EE   divide  el  trabajo  necesario  para  implementar   esta  arquitectura  en  las  siguientes 
partes: 
● La lógica de negocio y presentación, implementados por el desarrollador 
● Los servicios del sistema estándar, proporcionados por la plataforma Java EE 
 
Java EE promueve la construcción de sistemas independientes de la plataforma. 
Posee  una  especificación  es   abierta,  por  lo  que  puede  ser  implementada  por  cualquier 
proveedor.  Para  esto,  el  proveedor  deberá  de  seguir  el  estándar,  cumpliendo   con  los 
procesos  de  certificación  existentes.  Debe  cumplir  lo  que  dice  el  estándar,  pero  eso  no 
significa que sólo deba contemplar lo que el estándar establece. 
Un  servidor  de  aplicaciones  que  sea  Java  EE  certificado,  deberá  proveer  los  servicios  que 
define  la  especificación.  Con  esto se  logra que una aplicación que se ejecuta en un servidor 
de aplicaciones A, pueda ejecutarse en un servidor de aplicación B. 
 

Aplicaciones distribuídas
Java  EE   usa  un  modelo   de  varios  niveles   donde  se  distribuyen  las  aplicaciones  de  la 
empresa.  
En  ésta  un  objeto  está  asociado  con  un  nombre,  donde  los  nombres  los  proporciona  un 
servicio  de  nombres,  notificando  a  distintos  componentes  y  resolviendo  las  referencias  de 
clientes para estos componentes de servicio. 
 
La  lógica  de  la  aplicación  se  divide  en  componentes  de  acuerdo  a  su  función,  y  los 
componentes  de  una  aplicación  Java  EE  pueden  estar  instalados  en  distintas  máquinas, 
dependiendo de la capa a la que pertenece el componente de aplicación. 
 
Las  aplicaciones  de  multi­capa  Java  EE son generalmente consideradas como aplicaciones 
de  tres  capas,  porque   están  distribuidas   en  tres  lugares:  máquina  cliente,  la  máquina  del 
servidor Java EE, y la base de datos.  
 

Seguridad
Aunque   otros  modelos   de  aplicaciones  empresariales   requieren  medidas  de  seguridad  
específicas  para  cada  aplicación,  el  entorno  de  seguridad  de  Java  EE  permite  que  las 
 
medidas  de  seguridad  se   definan  durante  el  despliegue  (deploy)  o  momento  de  instalación 
de la aplicación.  
Estas  medidas  protegen  a  los  desarrolladores  de  aplicaciones  de  la  complejidad  de  la 
implementación de elementos de seguridad. 
La  plataforma   Java   EE  proporciona  reglas  de  control  de  acceso  estándar  declarativas  que 
están  definidas   por el desarrollador e interpretadas cuando se realiza el deploy o despliegue 
de la aplicación.  
 

Arquitectura
 
Java  EE   define  un  estándar  para  el   desarrollo  de  aplicaciones  empresariales  multicapa 
basadas en ​ componentes​ . 

 
La  lógica  de  la  aplicación  se  divide  en  componentes  de  acuerdo  a  su  función,  y  cada 
componente  puede ser instalado en una máquina diferente dependiendo de  la capa a la que 
pertenezca 
 
Las aplicaciones se dividen en capas dependiendo de su funcionalidad como pueden ser: 
● Componentes de la capa de cliente corriendo en la máquina cliente 
● Componentes de la capa web corriendo en el servidor Java EE 
● Componentes de la capa de negocio corriendo en el servidor Java EE 
● Software  de  la   capa  EIS  (Enterprise  Information  System)  corriendo  en  un  servidor  
EIS, con bases de datos. 
 
 
 
 

 
 
 
 

Componente Java EE
Un  componente  es  una  unidad  de  software  “autosuficiente”  y  funcional  que  se  ensambla 
dentro de una aplicación Java EE y se comunica con otros componentes. 
Para  que  un  componente  pueda  ser  ejecutado,  debe  de  ser  previamente  desplegado 
(deploy) en el contenedor correspondiente de un servidor Java EE 
 
La especificación Java EE define los siguientes componentes Java EE: 
● Los  clientes  de  aplicaciones  y  applets  son   componentes  que  se  ejecutan  en  el  
cliente. 
● Servlet  Java,  Java  Server  Faces,  y  Java  Server Pages (JSP) son componentes web 
que se ejecutan en el servidor. 
● Enterprise  JavaBeans  (EJBs)  son  componentes  de  negocio   que  se  ejecutan  en  el 
servidor. 
 
Los  componentes  Java  EE  están  escritos  en  Java  y  se   compilan  de   la  misma  forma   que 
cualquier  otro  programa  en  el  lenguaje.  Las  diferencias  entre  los  componentes  Java  EE  y 
las  clases  de  Java   "estándar"  son  que  los  componentes  Java  EE  se  ensamblan  en  una 
aplicación  Java  EE,  que  se  verifican  de  estar  bien  formados  y  de  acuerdo   con  la 
especificación  Java  EE,  y  que  se  implementan  en  la   producción,  en  la  que  están 
gestionados por el servidor Java EE. 
 

Los clientes de Java EE 
Un cliente Java EE es un cliente web, una aplicación de escritorio o un applet. 

Clientes web 
Un cliente web se compone de dos partes: 
● Páginas  web  dinámicas  que  contienen  varios  tipos  de  lenguaje  de  marcado  (HTML, 
XML,  etc.),  que  son  generados  por  los  componentes  Web  que  se  ejecutan   en  la 
capa web 
● Un navegador web, lo que hace que las páginas sean mostradas 
 
Un  cliente  web  a  veces  se  llama  un  cliente  ligero.  Los  clientes  ligeros  no  suelen  consultar 
bases  de  datos,  ejecutar reglas de negocio complejas, ni conectarse con otras aplicaciones. 
Cuando  se  utiliza  un  cliente  ligero,  las  operaciones  “pesadas”  las  realizan  los  bean 
enterprises   que  se  ejecutan  en  el   servidor  Java  EE,  en  el  que  pueden  aprovechar  la 
seguridad,  velocidad,  servicios,   y  la  fiabilidad  de  las  tecnologías  del  lado  del  servidor  Java 
EE. 

Aplicación de escritorio 
Una  aplicación  de  escritorio  se  ejecuta  en  una  máquina   cliente  y  brinda  una  forma  más 
amigable  para  que  los  usuarios  manejen  las  tareas  que   requieren  una  interfaz  de  usuario 
más rica y más customizada que la de un lenguaje de marcas (HTML).  
Normalmente  tiene  una  interfaz  gráfica  de  usuario  basada  en  Swing  o  AWT,  pero  también 
podría ser tan simple como una interfaz de línea de comandos. 
 
Las  aplicaciones  de  escritorio  acceden  directamente a los beans enterprise que se ejecutan  
en la capa de negocio.  
 

Applets 
Un  applet  es  una  pequeña  aplicación  cliente  que  se  ejecuta  en  la  máquina  virtual  Java 
embebida  en  el  navegador  web.  En  las  máquinas   cliente  necesitará   el  plug­in  de  Java  y, 
posiblemente  un  certificado  de  seguridad  para  que  el  applet  pueda  ejecutarse  con  éxito  en 
el navegador web. 
 
JavaBeans
Las  capas  servidor  y  cliente  pueden  incluir  componentes  JavaBeans  para  comunicar  estas 
dos capas que servirán de puente entre ambas.    
Los  componentes  JavaBeans  son  clases  Java  que  tienen  propiedades  y  métodos  get  y set 
para  acceder  a  las  mismas.  Los   componentes   JavaBeans utilizados de esta manera suelen 
ser  simples  en  su  diseño  e  implementación,  pero  deben  ajustarse  a  las  convenciones  de 
nombres y de diseño descritos en la arquitectura de componentes JavaBeans. 
Los  componentes  JavaBeans  no  son  considerados  componentes  Java  EE  por  parte  de  la 
especificación Java EE. 
 

Java Communications Server EE


El  cliente  se  comunica con la capa de negocio que  se ejecuta en el servidor Java EE ya sea 
directamente  o,  como  en  el  caso  de  un  cliente  que  se  ejecuta  en un navegador, pasando a 
través de páginas web o servlets que se ejecutan en la capa web. 
 
 

Componentes web
Los  componentes  Web  Java  EE  son  servlets  o   páginas  web  creadas  usando  la  tecnología 
JavaServer Faces y / o la tecnología JSP (páginas JSP).  
 
Los  servlets  son  clases  Java  que  procesan  en  forma  dinámica  peticiones  y  construyen 
respuestas.  
Las  páginas  JSP  son  documentos  basados  ​ en  texto  que  se  ejecutan  como  servlets  pero 
permiten un enfoque más natural para la creación de contenido estático.  
JavaServer  Faces  se   basa  en  servlets  y  JSP  y  proporciona  un  marco  de  componentes  de 
interfaz de usuario para las aplicaciones web. 
 
 
Las  páginas  HTML estáticas y los applets se  incluyen con los componentes web, pero no se 
consideran componentes web según la especificación Java EE.  
Las  clases  de  utilidades  del  lado  del  servidor  también  pueden  ser  incluidas  con  los 
componentes web y, al igual que las páginas HTML, no se consideran componentes web. 
 
 

Componentes de negocio
Es  la  lógica  que  resuelve  las  necesidades  del  negocio.  Es  manejado  por  los  javabeans,  ya 
sea en la capa de negocio o de la capa web.  
 

 
 
Un  bean  enterprise  recibe  datos  de  los  programas  clientes,  los  procesa  (si es necesario), y 
los envía a la capa del sistema de información empresarial para su almacenamiento.  
Un  bean  enterprise   también  recupera  datos  desde  el  almacenamiento,  los  procesa  (si  es 
necesario), y los envía de vuelta al programa cliente. 
 
Hay  tres  tipos  de  beans  enterprise:  beans  de  sesión   (con  o  sin  estado),  beans  de  entidad 
(manejados por el bean o por el contenedor) y beans dirigidos a mensaje.  
Un  bean  de  sesión  representa  una   conversación  temporal  con   un cliente. Cuando el cliente 
finaliza su ejecución, el bean de sesión y sus datos desaparecen.  
Por  el  contrario,  un  bean  de   entidad  representa  datos  persistentes  almacenados en una fila 
de  una  tabla/relación  de  una  base  de  datos.  Si  el  cliente   se  termina  o  si  se  apaga  el 
servidor, los servicios subyacentes se aseguran de grabar el bean.  
Un  bean  dirigido­a­mensaje  combina  las  características   de  un  bean  de  sesión  y  de  un 
oyente  de  Java  Message  Service (JMS), permitiendo que un componente de negocio reciba 
asíncronamente mensajes JMS. 
 
Capa Enterprise Information System
Esta  capa  maneja  el software EIS e incluye sistemas de infraestructura de la empresa, tales 
como la planificación de recursos empresariales (ERP), sistemas de bases de datos, etc. 
Por  ejemplo,  los  componentes  de  aplicaciones  Java  EE  pueden  necesitar  acceso  a  los 
sistemas de información de la empresa para la conectividad de la base de datos. 
 
 

Java EE Contenedores
La  arquitectura  Java  EE  está  basada  en  componentes  y es independiente de la plataforma, 
lo  que  hace  que  las  aplicaciones  Java  EE  sean  más  fáciles  de  escribir   porque  la  lógica  de 
negocio está organizada en componentes que son reutilizables.  
Además,  el  servidor  Java  EE  proporciona  servicios  como  un  contenedor  para  cada  tipo   de 
componente.  

Servicios de contenedor
Los  contenedores  son  la  interfaz   entre  un  componente  y  la  funcionalidad  específica  de  la 
plataforma de bajo nivel que soporta el componente.  
Antes  de  que  pueda  ser  ejecutado  un  ejb o un componente de aplicación cliente, deben ser 
empaquetados en un módulo Java EE y desplegados en su contenedor. 
 
El  proceso  de deploy implica especificar valores de contenedor para  cada componente en la 
aplicación Java EE y para la aplicación Java EE en sí.  
Se  pueden  personalizar  valores  de  servicios  tales  como  la  seguridad,  la  gestión   de 
transacciones,  Java  Naming  and  Directory  Interface  API  de  búsquedas  (JNDI),  y 
conectividad remota.  
 
Como  la   arquitectura  Java  EE  proporciona  servicios  configurables,  los  mismos 
componentes  de  una  aplicación Java EE pueden comportarse de forma diferente en función 
de  donde  se   desplieguen.  Por  ejemplo,  un  ejb  puede  tener  la  configuración  de  seguridad 
que  permite  un  cierto  nivel  de  acceso  a  los  datos  de  base  de  datos  en  un  entorno  de 
producción y otro nivel de acceso a la base de datos en otro entorno de producción. 

Tipos de contenedores
El  proceso  de  despliegue  instala  los  componentes  de  aplicaciones  Java  EE  en  los 
contenedores Java EE. 
 
 

 
 
● Servidor Java EE:​  Un servidor Java EE proporciona contenedores EJB y web. 
● Enterprise  JavaBeans  (EJB):  gestiona  la  ejecución  de  los  ejbs  para  las 
aplicaciones Java EE.  
● Contenedor  web:  Gestiona  la  ejecución  de  páginas  web,  servlets,  y  algunos 
componentes EJB para aplicaciones Java EE. 
● Contenedor  de  cliente  de  aplicación:  Gestiona  la  ejecución  de  los  componentes 
de  cliente  de aplicaciones. Los clientes de aplicación  y su contenedor se ejecutan  en 
el cliente. 
● Contenedor  de  applets:   Gestiona  la  ejecución  de applets. Consta de un navegador 
web y Java Plug­in que se ejecuta en el cliente. 
 
Servidores Java EE
 
Los servidores Java EE representan el ambiente en el que ejecutan los componentes. 
Estos  componentes  se  denominan  componentes  server­side  o  componentes  de  aplicación 
JEE. 
Puede tratarse de  
● Componentes web (JSP / Servlets / JSF) 
● Componentes de negocio (EJB) 
Estos componentes ejecutan en un contenedor  
Servidor de aplicaciones Java EE
Un servidor de aplicaciones Java EE es una implementación de la especificación Java EE.  
 
Java EE provee estándares que permiten a un servidor de aplicaciones servir como 
contenedor de los componentes que conforman dichas aplicaciones. Debe servir como 
contenedor web y contenedor ejb. 
 
 ​
Entre los servidores de aplicación Java EE​más conocidos están WebLogic de Oracle, 
WebSphere de IBM, ambos licenciados, y dentro de los libres se encuentran JOnAs, JBoss, 
Geronimo, Glassfish, etc. 
Mucha gente confunde​  ​
Tomcat como un servidor de aplicaciones; sin embargo, es 
solamente un contenedor web. 
 

Java EE y empaquetado de aplicaciones 
Una aplicación Java EE se empaqueta en una o más unidades. Cada unidad contiene 
● Un componente funcional como ejbs, página web, servlets, o un applet 
● Un  descriptor  de  despliegue  opcional  que  describe  su  contenido. Estos  descriptores 
de  despliegue  contienen  información   específica  de  cada  componente  empaquetado 
y  son  un  mecanismo  para   configurar  el  comportamiento  de  la  aplicación  en  el 
momento del ensamble o del despliegue. 
 
Una vez que se empaqueta la aplicación Java EE, está lista para ser desplegada.  
Para  el  despliegue  se  utiliza  la  herramienta  de  despliegue  de la plataforma para especificar 
la  información  específica  de  la  ubicación, la lista de los usuarios que pueden acceder a ella, 
el  nombre  de  la  base  de  datos,  entre  otras  cosas.  Una  vez  desplegado  en  el  servidor,  la 
aplicación está lista para ser utilizada. 
 

Empaquetado 
Una aplicación Java EE se empaqueta en: 
 
● archivo Java Archive (JAR) 
● archivo Archivo Web (WAR)  
● archivo EAR (Enterprise Archive).  
 
Una  aplicación  Java  EE  se  empaqueta  en  un  archivo  ​ enterprise  (​.ear​)  que  contiene  toda  la 
aplicación  junto  con  el  descriptor  de  despliegue   que  proporciona  información  sobre  la 
aplicación y sus componentes. 
 
Un  descriptor  de  despliegue  es  un  documento  XML  donde  describe  la  configuración  de 
despliegue  de  una  aplicación,  un  módulo  o  un  componente.  Como  la  información  de 
descriptor  de  despliegue   es  declarativa  se  puede  cambiar  sin  la  necesidad  de   modificar  el 
código fuente.  
 
Es  en  tiempo  de  ejecución  que  el  servidor  Java  EE  lee  el  descriptor  de  despliegue  y  actúa 
sobre  la  aplicación,  módulo  o   componente  en  consecuencia  sin  necesidad  de  recompilar el 
código fuente. 
 
 
Existen 2 tipos de descriptores de despliegue: 
 
● Descriptores  de  despliegue  JEE  (JEE  deployment  descriptor):  configuran  las 
opciones de despliegue de cualquier componente de Java Empresarial 
● Descriptores  de  despliegue  del  entorno  de  ejecución  (runtime  deployment 
descriptor):  configuran  opciones  del  entorno  de  ejecución  de  nuestra  aplicación 
empresarial, tales como las opciones de caché en el servidor 
 
 
Un  módulo  Java  EE  consta  de  uno  o  más  componentes  de  Java  EE  para  el  mismo  tipo de 
contenedor y, opcionalmente, descriptores de despliegue de ese tipo.  
Un  descriptor  de  despliegue  del  módulo  Enterprise  Bean,  por  ejemplo,  declara  atributos  de 
transacción  y  las  autorizaciones   de  seguridad  para   un bean enterprise. Un módulo Java EE 
puede implementarse como un módulo independiente. 
Los módulos Java EE son de los siguientes tipos: 
● Módulos  EJB:  contiene  los  beans  de  empresa  y,  opcionalmente,   un  descriptor  de  
despliegue  EJB.  Estos   módulos  son   empaquetados   como  archivos  JAR  con 
extensión .jar. 
● Módulos  web:  contienen  las  clases  de  los  servlets, archivos web, archivos utilitarios, 
imágenes   y  HTML,  y,  opcionalmente,  un  descriptor  de  despliegue   de  aplicaciones 
Web.  Estos  módulos  son  empaquetados  como archivos JAR con una extensión .war 
(archivo web). 
● Módulos  cliente:  contienen  las  clases  y,  opcionalmente,  un  descriptor de despliegue 
de  aplicaciones  de  cliente.  Estos  módulos  se  empaquetan  como  archivos  JAR  con 
una extensión .jar. 
● Los  módulos  adaptadores   de  recursos,  contienen  todas  las  interfaces  Java,  clases, 
bibliotecas  nativas,  y,  opcionalmente,  un  descriptor  de   despliegue  del  adaptador  de 
recursos.  Estos  módulos  son  empaquetados  como  archivos  JAR  con  una  extensión 
.rar (archivo adaptador de recursos). 
 

Roles de desarrollo 
El  uso  de  módulos  reutilizables  hacen  posible  dividir  el  desarrollo  de  aplicaciones  y  el 
proceso  de  implementación  en  distintos  roles  para  que  diferentes personas puedan realizar 
diferentes partes del proceso. 
Los  dos  primeros  papeles,  Java  EE  proveedor  de  productos  y  proveedor  de  herramientas, 
implican la compra e instalación del producto y herramientas Java EE.  
Después  que  el  software  es  comprado  e  instalado,  los  componentes  Java  EE  pueden  ser 
desarrollados  por  los  proveedores  de  componentes  de  aplicaciones,  ensamblados  por  los 
ensambladores de aplicaciones, y desplegados por los implantadores de aplicaciones.  
 
En  una  organización  grande,  cada  una  de  estas  funciones   podrían  ser  ejecutados  por 
diferentes  individuos   o  equipos.  Esta  división  del  trabajo  funciona  porque  cada  una  de  las 
funciones  anteriores  genera   un  archivo  portátil  que   es  la  entrada  para  una  función 
subsiguiente.  Por  ejemplo,  en  la  fase  de  desarrollo  componente  de  aplicación,  un 
desarrollador   de  software  bean  enterprise  proporciona  archivos  JAR  EJB.  En   el  papel 
conjunto  de  aplicación,  otro  desarrollador  puede   combinar  estos  archivos  JAR  EJB  en  una 
aplicación  Java  EE  y  guardarlo  en  un   archivo  EAR.  En  el  papel  de  implantación  de 
 
aplicaciones,  un  administrador  de  sistemas  en  el  sitio  del  cliente utiliza el  archivo EAR para 
instalar la aplicación Java EE en el servidor. 
 
Los diferentes roles no siempre son ejecutados por diferentes personas. 

Proveedor del producto Java EE 
El  proveedor  de  productos  de  Java  EE  es  la empresa que diseña y pone a disposición para 
su  compra  las  APIs  de  la  plataforma  Java  EE   y  otras  características  definidas  en  la 
especificación  Java  EE.  Son  típicamente  los  fabricantes  de  servidores  de  aplicaciones  que 
implementan la plataforma Java EE de acuerdo con la especificación Java EE. 

Proveedor de herramientas 
El  proveedor  de  la  herramienta  es  la  empresa  o  persona  que  desarrolla,  monta  y  crea 
herramientas   para  los  paquetes  utilizados  por  los  proveedores  de  componentes, 
ensambladores, y quienes los despliegan. 

Proveedor de componentes de aplicación 
El  proveedor  de  componentes  de  aplicación  es  la  empresa  o  persona  que  crea 
componentes  web,  beans  de  empresa,  applets   u  clientes  de  aplicaciones  para  su  uso  en 
aplicaciones Java EE. 

Bean Enterprise Developer 
Se trata de un desarrollador de bean de empresa que realiza las siguientes tareas: 
● Escribe y compila el código fuente 
● Especifica el descriptor de despliegue (opcional) 
● Empaqueta los archivos .class y descriptor de despliegue en el archivo JAR EJB 

Web Component Developer 
Se trata de un desarrollador de componentes web que realiza las siguientes tareas: 
● Escribe y compila el código fuente del servlet 
● Escribe JavaServer Faces, JSP y archivos HTML 
● Especifica el descriptor de despliegue (opcional) 
● Empaqueta el descriptor .class, .jsp y archivos .html en el archivo WAR 

Desarrollador de aplicaciones de cliente 
Se trata de un desarrollador de aplicaciones cliente que realiza las siguientes tareas: 
● Escribe y compila el código fuente 
● Especifica el descriptor de despliegue para el cliente (opcional) 
● Empaqueta los archivos .class y descriptor de despliegue en el archivo JAR 

Ensamblador de aplicación 
El  ensamblador  de  la  aplicación  es  la   empresa  o  persona  que  recibe  los  módulos  de 
aplicación de los proveedores de componentes y los empaqueta en un archivo EAR.  
 
Realiza las siguientes tareas: 
● Se  ensambla  archivos  JAR  EJB  y  WAR  creados  en  las  fases  anteriores   en  una 
aplicación Java EE archivo (EAR) 
● Especifica el descriptor de despliegue de la aplicación Java EE (opcional) 
 
● Verifica  que  el  contenido  del  archivo  EAR  están  bien  formadas  y  cumplen  con  la 
especificación Java EE 

Administrador de aplicación 
El  programa  de  implementación  de  aplicaciones  y  administrador  sea  la  empresa  o persona 
que  configura  y  despliega  los  clientes  de   aplicaciones,  aplicaciones  web,  componentes 
JavaBeans   Enterprise  y  las  aplicaciones  Java  EE,  administra  la  infraestructura 
computacional   y  de  redes,  donde  los  componentes  y  aplicaciones  Java  EE  corren,  y 
supervisa  el  entorno  de  ejecución.  Las  responsabilidades  incluyen  controles de transacción 
de ajuste y los atributos de seguridad y especificando las conexiones a bases de datos. 
Durante  la   configuración,  el  programa  de  implementación  sigue  las  instrucciones 
suministradas  por  el  proveedor  del  componente  de   aplicación  para  resolver  las 
dependencias  externas,  especifique  la  configuración  de  seguridad,  y  asignar  atributos  de 
transacción.  Durante la instalación, el programa de implementación mueve los componentes 
de la aplicación en el servidor y genera las clases e interfaces específicos del contenedor. 
Un  administrador   del  programa  de  implementación o el sistema realiza las siguientes tareas 
para instalar y configurar una aplicación o componentes Java EE: 
● Configura la aplicación Java EE o componentes para el entorno operativo 
● Verifica que los contenidos de la oreja, JAR, y / o archivos WAR están bien formadas 
y cumplen con la especificación Java EE 
● Despliega (instala) la aplicación Java EE o componentes en el servidor Java EE 
 
 
 
 

Java Persistence API


 

¿Qué es JPA?
 
Java Persistence API (JPA) nos brinda un estándar para poder gestionar datos relacionales 
en aplicaciones java, de tal forma que además simplifica el desarrollo de la persistencia de 
datos. 
 
JPA establece una interface común que es implementada por un proveedor de persistencia, 
tales como Hibernate, EclipseLink u otro. Podemos elegir en cualquier momento el 
proveedor que más se adecue a nuestras necesidades. Así, es el proveedor quién realiza el 
trabajo, pero siempre funcionando bajo la API de JPA. 
 
Para los ejemplos del curso utilizaremos Hibernate, pero si lo prefieren pueden utilizar otro 
en cualquier momento. 
Hibernate es un framework open source de mapeo y persistencia para ser utilizado en Java. 
Sus librerías ya vienen con el servidor de aplicaciones WildFly por lo que no tendremos que 
agregar librerias adicionales. 
 
 
Para entender JPA, tendremos que tener claro el concepto de persistencia. La persistencia 
o el almacenamiento permanente, es una de las necesidades básicas de cualquier sistema 
de información de cualquier tipo. Persistir objetos Java en una base de datos relacional 
implica serializar un árbol de objetos Java en una base de datos de estructura tabular y 
viceversa. Es vital poder mapear objetos Java para optimizar velocidad y eficiencia de la 
base de datos. 

Entidades
 
Una entidad es un objeto de dominio persistencia liviano. Por lo general, una entidad 
representa una tabla en una base de datos relacional, y cada instancia de la entidad 
corresponde a una fila de esa tabla.  
Una entidad tiene campos o propiedades que son persistentes.  

Requisitos de una entidad


 
Una entidad debe cumplir los siguientes requisitos. 
● La clase debe tener la javax.persistence.Entity anotación: @Entity 
● La clase debe tener un constructor sin parámetros public o protected. La clase 
puede tener además otros constructores. 
 
● La clase no debe ser declarada final . No hay métodos o variables de instancia 
persistentes que sean declarados final . 
● Si una instancia de una entidad se pasa por valor como un objeto a través de la 
interfaz de negocio remota de un EJB, la clase debe implementar la interfaz 
Serializable. 
● Las entidades pueden extender clases de cualquier tipo (entidades u otras), y las 
clases que no son entidades pueden extender de clases de entidad. 
● Las variables de instancia pueden ser accedidas sólo por los métodos de la clase 
entidad, en general a través de métodos get o set. 

Ejemplo de entidad 
@Entity  
@Table(name = "PERSONA") 
 
public class Persona {  
    @Id  
    @GeneratedValue  
    private Long id;  
    @Column(nullable=false) 
    private String nombre;  
    @Column(nullable=true) 
    private Date fechaNacimiento; 
    @Transient 
    private int edad; 
   
    // Getters y Setters  

 
La anotación @Table nos permite configurar el nombre de la tabla donde queremos 
almacenar la entidad mediante el atributo name.  

Los campos persistentes y propiedades de la entidad


 
A través de la anotación @Column podemos configurar el nombre de la columna donde se 
almacenará una propiedad, si dicha propiedad puede contener un valor null, etc. 
 
Los tipos de datos válidos como propiedades son 
● Tipos primitivos 
● java.lang.Byte 
● java.lang.Short 
● java.lang.Integer 
● java.lang.Long 
 
● java.math.BigInteger 
● java.lang.Float 
● java.lang.Double 
● java.math.BigDecimal 
● java.lang.Boolean 
● java.lang.Character 
● java.lang.String 
● java.util.Date 
● java.util.Calendar 
● java.sql.Date 
● java.sql.Time 
● java.sql.Timestamp 
Para definir un atributo de una entidad (Entity) que no se desee persistir, debe emplearse la 
anotación @Transient. La anotación @Lob especifica que la propiedad debe ser persistida 
en un Blob o Clob 
 
Las entidades pueden utilizar campos persistentes, propiedades persistentes, o una 
combinación de ambos. Si las anotaciones de mapeo se aplican a las variables de instancia 
de la entidad, la entidad utiliza campos persistentes. Si las anotaciones de mapeo se 
aplican a los métodos getter de la entidad, la entidad utiliza las propiedades persistentes. 

Los campos persistentes


Si la clase de entidad utiliza campos persistentes, el acceso se realiza en tiempo de 
ejecución.  
Todos los campos que NO sean anotados con javax.persistence.Transient o no marcados 
como @Transient se guardarán en el almacén de datos.  

En el ejemplo de la entidad Persona, los campos persistentes son el id, nombre y 
fechaNacimiento. El campo edad no se almacenará en la base de datos ya que está 
anotado como transient. Este campo puede ser calculado a partir de la fecha de nacimiento, 
es por eso que no necesita ser almacenado en la base de datos. 

Propiedades persistentes
Si la entidad utiliza las propiedades persistentes, la entidad debe seguir las convenciones 
JavaBeans: esto implica el uso de métodos get y set.  
En el ejemplo de la entidad Persona, si utiliza las propiedades persistentes y tiene una 
variable de instancia privada denominada nombre, la clase define un getNombre y 
setNombre. 
 

Tipos de acceso
 
JPA permite definir dos tipos de acceso: 
   
● Acceso a variable  
 
● Acceso a propiedad  
   
El tipo de acceso que usará una entidad está definido por el lugar donde situemos sus 
anotaciones de mapeo. Si las anotaciones están en las variables estaremos indicando a 
JPA que debe realizar ​acceso a variable.​  Si, por el contrario situamos las anotaciones de 
mapeo en los métodos getter, estaremos indicando un ​ acceso a propiedad.​   
A efectos prácticos, no existe diferencia alguna entre ambas opciones.  
 

Lectura temprana y lectura demorada


 
Cuando leemos una entidad desde la base de datos, ciertas propiedades pueden no ser 
necesarias en el momento de la creación del objeto. 
JPA nos permite leer una propiedad desde la base de datos recién cuando el cliente 
necesita leer su valor (lectura demorada), en lugar de leerla cuando la entidad que la 
contiene se crea (lectura temprana).  
Es entonces que si la propiedad nunca es accedida, nos evitamos el costo de crearla. Esto 
puede ser útil si la propiedad contiene un objeto de gran tamaño: 
   
@Basic(fetch = FetchType.LAZY) 
private Archivo adjunto; 
   
La propiedad adjunto es un objeto que representa un archivo adjunto (un objeto que puede 
ser de gran tamaño). Como el costo de crear este objeto al leer la entidad que lo contiene 
es muy alto, lo marcamos como una propiedad de lectura demorada con la anotación 
@Basic(fetch = FetchType.LAZY).  
El comportamiento por defecto de la mayoría de tipos Java es el contrario (lectura 
temprana). Este comportamiento, a pesar de ser implícito, puede ser declarado 
explícitamente de la siguiente manera: 
   
@Basic(fetch = FetchType.EAGER) 
private Archivo adjunto; 
   
Hay que tener ciertos cuidados cuando configuramos atributos con lectura demorada. Si, 
por ejemplo, marcamos todas las propiedades de tipo int, String o Date de una entidad con 
lectura demorada, cada vez que accedemos por primera vez a cada una de ellas el 
proveedor de persistencia tendrá que hacer una llamada a la base de datos para leerla. 
Esto va a hacer que se realicen muchas llamadas a la base de datos cuando con solo una 
(al crear la entidad en memoria) podrían haberse leído todas con muy bajo costo. Por este 
motivo hay que tener mucho cuidado al configurar este tipo de atributos porque puede 
afectar considerablemente el rendimiento de nuestra aplicación. 
   
La anotación @Basic solo puede ser aplicada a tipos primitivos, sus correspondientes 
clases wrapper, BigDecimal, BigInteger, Date, arrays, algunos tipos del paquete java.sql, 
enums, y cualquier tipo que implemente la interface Serializable.  
 
Además del atributo fetch, la anotación @Basic admite otro atributo, optional, el cual permite 
definir si la propiedad sobre la que se está aplicando la anotación puede contener el valor 
null. 
 

Tipos enumerados
 
JPA puede mapear los ​ tipos enumerados ​ (enum) mediante la anotación Enumerated: 
   
@Enumerated 
private Sexo sexo; 
 
   
La configuración por defecto de JPA mapeará cada valor ordinal de un tipo enumerado a 
una columna de tipo numérico en la base de datos.  
   
public enum Sexo {  
    FEMENINO,  
    MASCULINO  
}  
   
Si la propiedad sexo tiene el valor Sexo.FEMENINO, en la columna correspondiente de la 
base de datos de insertará el valor 0.  
Si quiero forzar a la base de datos a utilizar una columna de texto en lugar de una columna 
numérica: de esta manera, el valor almacenado será el nombre del valor enum, y no su 
valor ordinal: 
   
@Enumerated(EnumType.STRING) 
private Sexo sexo; 
 

Transient
 
Ciertas propiedades de una entidad pueden no representar su estado. Por ejemplo, 
imaginemos que tenemos una entidad que representa a una persona: 
   
@Entity  
public class Persona {  
    @Id  
    @GeneratedValue  
    private Long id;  
    private String nombre;  
    private String apellidos  
    private Date fechaNacimiento;  
 
    private int edad;  
   
    // getters y setters  
}  
   
Podemos considerar que la propiedad edad no representa el estado de Persona, ya que si 
no es actualizada cada cumpleaños, terminará conteniendo un valor erróneo. Como su valor 
puede calcularse a partir de la fecha de nacimiento, no vamos a guardarlo en la base de 
datos. Para indicar al proveedor de persistencia que ignore una propiedad cuando realice el 
mapeo, usamos la anotación @Transient: 
   
@Transient 
private int edad; 
 
Ahora, para obtener el valor de edad utilizamos su método getter: 
   
public int getEdad() {  
    // calcular la edad y devolverla  

 

Colecciones
 
Una entidad puede tener propiedades de tipo java.util.Collection y/o java.util.Map que 
contengan tipos básicos. Los elementos de estas colecciones serán almacenados en una 
tabla diferente a la que contiene la entidad donde están declarados. El tipo de colección 
tiene que ser concreto (como ArrayList o HashMap) y nunca una interface. 
   
private ArrayList<String> nombres; 
 
Podemos customizar la configuración de la siguiente manera 
   
@ElementCollection(fetch = FetchType.LAZY) 
@CollectionTable(name = "NOMBRES") 
private ArrayList<String> nombres;  
   
@ElementCollection permite definir el tipo de lectura (temprana o demorada). 
@CollectionTable nos permite definir el nombre de la tabla donde queremos almacenar los 
elementos de la colección. Si nuestra colección es de tipo Map, podemos añadir la 
anotación @MapKeyColumn(name = "NOMBRE_COLUMNA"), la cual nos permite definir el 
nombre de la columna donde se almacenarán las claves del Map. 
 

Tipos embeddable
 
 
Los tipos embeddable son objetos que no tienen identidad: esto significa que para ser 
persistidos deben ser primero insertados dentro de una entidad. Cada propiedad del tipo 
embeddable será mapeada a la tabla de la entidad que lo contenga, como si fuera una 
propiedad declarada en la propia entidad. Definimos un tipo insertable con la anotación 
@Embeddable: 
   
@Embeddable  
public class Direccion {  
    private String calle;  
    private int codigoPostal;  
   
    // ...  
}   
   
Y lo ​ insertamos​  en una entidad con la anotación @Embedded 
   
@Entity  
public class Persona {  
    // ...  
   
    @Embedded  
    private Direccion direccion;  
}   
   
Ahora, la tabla que contenga las entidades de tipo Persona contendrá sus propias 
columnas, más las definidas en el tipo embeddable Direccion. 
 

Las claves
 
Cada entidad tiene un identificador de objeto único. Una entidad de un cliente, por ejemplo, 
puede ser identificado por un número de cliente. El identificador único, o una clave principal, 
permite localizar una instancia de entidad en particular.  
Cada entidad debe tener una clave principal. Una entidad puede tener una clave simple o 
compuesta. 
Las claves primarias simples utilizan el javax.persistence.Id anotación para indicar la 
propiedad de clave primaria en el campo. 
 
Las claves primarias compuestas se utilizan cuando una clave principal se compone de más 
de un atributo, que corresponde a un conjunto de propiedades persistentes individuales o 
campos. Las claves primarias compuestas deben ser definidas en una clase aparte de clave 
primaria. Las claves primarias compuestas se denotan usando las anotaciones 
javax.persistence.EmbeddedId y javax.persistence.IdClass. 
 
 
Las Entidades poseen una identidad que las diferencie del resto 
● Propiedad marcada con la anotación @Id 
● Debe admitir valores null, p.e.: Integer en lugar de int 
● La identidad de una entidad va a ser gestionada por el proveedor de persistencia 
● Propiedad de identidad anotada: @GeneratedValue 
 
La anotación @GeneratedValue permitirá la generación de forma totalmente automática y 
transparente de una clave primaria cada vez que sea necesario insertar un nuevo 
objeto/registro. Para esta generación JPA define cuatro estrategias: 
 

Claves simples

@GeneratedValue(strategy=GenerationType.IDENTITY)
MySQL y SQLServer tienen un tipo de columna autonumérica (AUTO_INCREMENT e 
IDENTITY respectivamente) ideal para ser usadas como clave primaria. Asimismo, 
PostgreSQL cuenta con el tipo SERIAL que simula esta funcionalidad creando secuencias. 
Podemos usar esta característica mediante este tipo de generador: 
@Id 
@GeneratedValue(strategy=GenerationType.IDENTITY) 
private Long id; 
En el caso de Oracle, al no tener esta funcionalidad obtendremos el correspondiente error: 
Oracle10gDialect does not support identity key generation 

@GeneratedValue(strategy=GenerationType.SEQUENCE)
Una  secuencia  es  un  objeto  o  tipo de datos  que genera valores numéricos únicos dentro de 
esa  secuencia.  Ese  valor  se  define  dentro  de  un  rango,  y  se  va  incrementando  según  un 
valor  de  incremento  a  medida  que  se  vayan  solicitando  nuevos  valores  (por  ejemplo  en 
Oracle con la sentencia NOMBRE_SEQ.nextval). 
@Id 
@GeneratedValue(strategy=GenerationType.SEQUENCE) 
private Long id; 
 
Se  pueden  definir  secuencias  específicas  para  cada  clave  (o  una  común  a  varias  de  ellas) 
con  la  anotación  @SequenceGenerator.   Esta  anotación  tiene  como  parámetros  opcionales 
allocationSize​,   que  indica  el  incremento  numérico  del  avance  de  la  secuencia  y  cuyo  valor 
por  omisión  es  50  (por   lo  que  probablemente  queramos  definirlo  a  un  valor que nos resulte 
más  conveniente  como  por  ejemplo  1)  y  ​ initialValue  cuyo  valor  por  defecto  es  1  tal  y como 
cabría esperar. 
@Entity 
public class EntityA{   
    @Id 
    @SequenceGenerator(name="entA", sequenceName="entityA_seq", allocationSize = 
 

1) 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="entA") 
    private Long id; 
  
.... 
  
@Entity 
public class EntityB{ 
  
    @Id 
    @SequenceGenerator(name="entB", sequenceName="entityB_seq", allocationSize = 
1) 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="entB") 
    private Long id; 

@GeneratedValue(strategy=GenerationType.AUTO)
Delega en el proveedor la elección de la estrategia que considere oportuna en función de la 
BD subyacente. 
@Id 
@GeneratedValue(strategy=GenerationType.AUTO) 
private Long id; 
Es la estrategia más cómoda, pero debemos conocer qué hace nuestro framework ya que el 
estándar le da vía libre y es posible que el resultado no sea el deseado. 

@GeneratedValue(strategy=GenerationType.TABLE)
Por  último,  veremos  la  estrategia  más  portable  de  todas  ya  que  se  puede  emplear de igual 
manera  en  cualquier  BD.  Se  basa  en  utilizar  una  tabla  con  dos columnas, una de tipo texto 
con  el  nombre  que  identifica  al  generador  de  claves  primarias  (tendremos  uno  por  cada 
tabla)  y  otra de  tipo numérico con el último valor que fue asignado como  PK para un registro 
de esa tabla. 
@Id 
@GeneratedValue(strategy=GenerationType.TABLE) 
private Long id; 

Claves múltiples
Con  la  anotación  @Id  indicamos  un  atributo  que  puede  ser  de  cierto  tipo  como  clave  
primaria, pero ¿qué pasaría si nuestra clave primaria es múltiple?  
Frente  a  esta  situación,  lo  que haremos es crear una clase  que contenga todos los atributos 
de  nuestra clave múltiple, y la marcaremos con la anotación @Embeddable que permite que 
una  clase  pueda  ser  incluída  en  una  entidad  y  sus  atributos  formen parte  de su mapeo a la 
BD.Por ejemplo: 
 
@Embeddable 
 
public class EntityPK implements Serializable{ 
    private Long idRef1;   
    private Long idRef2; 
 //getters y setters 
 
Ahora nuestra clave primaria estará compuesta por los dos atributos de esta clase y la 
usaremos con la anotación @EmbeddedId: 
@Entity 
public class EntityA{ 
    @EmbeddedId 
    EntityPK entityPK; 
 

La multiplicidad de relaciones de entidades


Las multiplicidades son de los siguientes tipos. 
● One to one: Cada instancia de la entidad está relacionada con una sola instancia de 
otra entidad. Por ejemplo, para modelar un empleado que tiene una única dirección 
asociada. Se utiliza la anotación: javax.persistence.OneToOne en la propiedad o 
campo persistente correspondiente. 
● One to many: Una instancia de la entidad puede estar relacionada con varias 
instancias de las otras entidades. Por ejemplo, una biblioteca que puede tener 
muchos libros. Se utiliza la anotación javax.persistence.OneToMany en la propiedad 
o campo persistente correspondiente. 
● Many to one: Múltiples instancias de una entidad pueden estar relacionados con una 
sola instancia de la otra entidad. Esta multiplicidad es lo contrario de una relación 
uno­a­muchos. Por ejemplo: un libro que pertenece a una biblioteca, y la misma 
puede tener muchos libros. Se utiliza la anotación javax.persistence.ManyToOne en 
la propiedad o campo persistente correspondiente. 
● Many to many: En este caso varias instancias de una entidad pueden relacionarse 
con múltiples instancias de otras entidades. Por ejemplo, cada curso de la 
universidad tiene muchos estudiantes, y cada estudiante puede tomar varios cursos. 
Se utiliza la anotación javax.persistence.ManyToMany en la propiedad o campo 
persistente correspondiente. 

Dirección en relaciones de entidades


La dirección de una relación puede ser bidireccional o unidireccional. Una relación 
bidireccional tiene tanto un lado propietario y un lado inverso. Una relación unidireccional 
sólo tiene un lado propietario. El lado propietario de una relación determina en tiempo de 
ejecución como se realizan los cambios a la relación en la base de datos. 

Las relaciones bidireccionales


En una relación bidireccional, cada entidad tiene un campo de relación o propiedad que se 
refiere a la otra entidad. A través del campo de relación o de propiedad, el código de una 
clase de entidad puede tener acceso a su objeto relacionado. Si una entidad tiene un campo 
 
relacionado, se dice que la entidad a "conoce" su objeto relacionado. Por ejemplo, si 
CustomerOrder conoce que LineItem tiene y si LineItem conoce al CustomerOrder que 
pertenece, se dice que tienen una relación bidireccional. 
Las relaciones bidireccionales deben seguir estas reglas. 
● El lado inverso de una relación bidireccional debe referirse a su lado propietario 
mediante el uso de la mappedBy de la relación @OneToOne , @OneToMany , o 
@ManyToMany. El mappedBy designa la propiedad o campo en la entidad que es el 
dueño de la relación. 
● El lado Many de relaciones Many to one bidireccionales no debe definir el elemento 
mappedBy. El lado Many es siempre el lado propietario de la relación. 
● Para relaciones one to one bidireccionales, el lado propietario corresponde a la parte 
que contiene la clave externa correspondiente. 
● Para relaciones Many to many bidireccionales, cada lado puede ser la parte 
propietaria. 

Las relaciones unidireccionales


En una relación unidireccional, sólo una entidad tiene un campo de relación o propiedad que 
se refiere a la otra. Por ejemplo, LineItem tendría un campo de relación que identifica 
Product, pero Product no tendría un campo de relación o propiedad para LineItem . En otras 
palabras, LineItem conoce a Product, pero Product no conoce que LineItems se refieren a 
ella. 

Las consultas y Dirección de Relación


Java Persistence consultas lenguaje de consulta y los criterios del API menudo navegar a 
través de las relaciones. La dirección de una relación determina si una consulta puede 
navegar desde una entidad a otra. Por ejemplo, una consulta puede navegar desde 
LineItem al Product, pero no puede navegar en la dirección opuesta. Para CustomerOrder y 
LineItem, una consulta podría realizarse en ambas direcciones debido a que estas dos 
entidades tienen una relación bidireccional. 

Operaciones en cascada
Las entidades que utilizan relaciones a menudo tienen dependencias en la existencia de la 
otra entidad en la relación.  
Por ejemplo, un elemento de línea es parte de un pedido; si se elimina la orden, el elemento 
de línea también debería eliminarse. Esto se llama una eliminación en cascada. 
El tipo enumerado javax.persistence.CascadeType define las operaciones en cascada que 
pueden aplicarse. 
 
Operación en 
cascada  Descripción 

ALL  Todas las operaciones en cascada se aplicarán a la entidad 
relacionada. All es equivalente a especificar cascade={DETACH, 
MERGE, PERSIST, REFRESH, REMOVE} 
 

DETACH  Si la entidad matriz se separa del contexto de persistencia, también 
puede separar la entidad relacionada. 

MERGE  Cuando una entidad es actualizada (se va a grabar), su entidad 
relacionada debe ser actualizada también. 

PERSIST  Cuando una entidad es persistida (se crea), su entidad relacionada 
debe ser persistida también.   

REFRESH  Cuando una entidad es refrescada /se refresca con los datos de la base 
de datos), su entidad relacionada debe ser refrescada también. 

REMOVE  Cuando una entidad es removida (se borra), su entidad relacionada 
debe ser removida también. 
 
 

Algunos ejemplos

@OneToOne
 
@Entity 
public class Departamento implements Serializable { 
… 

 
@Entity 
public class Empleado implements Serializable { 

@OneToOne(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.RE
MOVE},optional=false) 
private Direccion direccion; 
… 

 
Configuramos la opción ​ fetch​ a LAZY, de forma que cuando recuperemos un objeto de la 
entidad Empleado no recupere la instancia de Dirección asociada. Luego pusimos ​ cascade 
a PERSIST y REMOVE, de forma que cuando persistamos un empleado que tenga 
asociada una nueva Direccion, éste también se persistirá, y como no tiene sentido que 
exista una dirección sin un empleado asociado, si eliminamos la instancia del Empleado 
también eliminará la instancia de Direccion asociada. También hemos establecido la opción 
optional​ a false, de forma que no permitimos que se persista una instancia de Empleado si 
no está asociada con una instancia de Direccion. Por último, con la opción ​orphanRemoval 
a  true indicamos que cualquier instancia de Direccion que no esté asociada a una instancia 
de Empleado será eliminada de la base de datos. 
 
 
Ahora vamos a convertir la relación one­to­one unidireccional en bidireccional. Bastaría con 
añadir a la entidad Direccion un atributo haciendo referencia a la entidad Empleado y anotar 
el atributo con @OneToOne. 
 
@OneToOne(fetch=FetchType.LAZY,mappedBy="direccion”) 
private Empleado empleado; 
 
Agregamos la opción ​ mappedBy ​ con la que indicamos el atributo de la entidad propietaria 
de la relación (Empleado en nuestro caso). De esta forma a través de una instancia de la 
entidad Direccion podemos recuperar la instancia de la entidad Empleado asociada. 

@OneToMany
 
@Entity 
public class Libro implements Serializable { 
… 

 
@Entity 
public class Biblioteca implements Serializable { 
@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.ALL}) 
private List<Libro> libros; 
… 

 
La opción ​fetch​
 está en LAZY, de forma que cuando recuperemos un objeto de la entidad 
cascade ​
Biblioteca no recupere las instancias de Libro asociadas. Luego pusimos ​ a todo, de 
forma que cuando persistamos, borremos o modifiquemos una Biblioteca sus libros también 
se actualizarán 
 

@ManyToOne
@Entity 
public class Biblioteca implements Serializable { 
 @Id 
 @GeneratedValue 
  private Long id; 
… 

 
@Entity 
public class Libro implements Serializable { 
@ManyToOne(fetch=FetchType.LAZY,optional=false) 
@JoinColumn(name="id") 
 
private Biblioteca biblioteca; 
… 

 
La anotación @JoinColumn o @JoinColumns se usa para especificar cual es el campo de la 
tabla que actúa de clave foránea o clave foránea compuesta, respectivamente. 

@ManyToMany
@Entity 
public class Clase{ 
   @Id 
   @GeneratedValue( strategy = GenerationType.AUTO ) 
   private int id; 
   private String name; 
 
   @ManyToMany 
   private List<Profesor> profesores; 
…. 
 
@Entity 
public class Profesor{ 
   @Id 
   @GeneratedValue( strategy = GenerationType.AUTO ) 
   private int id; 
   private String name; 
 
   @ManyToMany(mappedBy="profesores") 
   private List<Clase> clases; 
…. 
 

Herencia
 
La herencia es el concepto de la base de cualquier lenguaje orientado a objetos, por lo 
tanto, podemos utilizar las relaciones de herencia o estrategias entre las entidades. JPA 
admiten tres tipos de estrategias de herencia: SINGLE_TABLE, JOINED_TABLE y 
TABLE_PER_CONCRETE_CLASS. 
 
SINGLE_TABLE: Una sola tabla para guardar toda la jerarquía de clases. Tiene la ventaja 
de ser la opción que mejor rendimiento da, ya que sólo es necesario acceder a una tabla 
(está totalmente desnormalizada). Tiene como inconveniente que todos los campos de las 
clases hijas tienen que admitir nulos, ya que cuando guardemos un tipo, los campos 
correspondientes a los otros tipos de la jerarquía no tendrán valor. 
 
 
JOINED_TABLE: Una tabla para el padre de la jerarquía, con las cosas comunes, y otra 
tabla para cada clase hija con las cosas concretas. Es la opción más normalizada, y por lo 
tanto la más flexible (puede ser interesante si tenemos un modelo de clases muy 
cambiante), ya que para añadir nuevos tipos basta con añadir nuevas tablas y si queremos 
añadir nuevos atributos sólo hay que modificar la tabla correspondiente al tipo donde se 
está añadiendo el atributo. Tiene la desventaja de que para recuperar la información de una 
clase, hay que ir haciendo join con las tablas de las clases padre. 
 
TABLE_PER_CONCRETE_CLASS: Una tabla independiente para cada tipo. En este caso 
cada tabla es independiente, pero los atributos del padre (atributos comunes en los hijos), 
tienen que estar repetidos en cada tabla. En principio puede tener serios problemas de 
rendimiento, si estamos trabajando con polimorfismo, por los SQL UNIONS que se tienen 
que hacer para recuperar la información. Sería la opción menos aconsejable. Tanto es así 
que en la versión 3.0 de EJBs, aunque está recogida en la especificación, no es obligatoria 
su implementación. 
 
Ejemplo 

 
 
Aquí tenemos un ejemplo clásico de herencia donde tenemos una Persona que puede ser 
un Alumno o un Profesor.  
 
Vamos a ver ahora como implemento esta realidad con la estrategia SINGLE_TABLE 
 
@Entity 
@Inheritance( strategy = InheritanceType.SINGLE_TABLE ) 
@DiscriminatorColumn( name="tipo" ) 
public abstract class Persona { 
 
@Id 
 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Integer id; 
  
private String apellido; 
private String nombre; 
  
// SETTERS AND GETTERS 

 
 
@Entity 
@DiscriminatorValue( value="ALUMNO" ) 
public class Alumno extends Persona implements Serializable { 
  
private int generacion; 
  
// GETTERS AND SETTERS 
  

 
@Entity 
@DiscriminatorValue( value="PROFESOR" ) 
public class Profesor extends Persona implements Serializable { 
  
private String gradoDocente; 
  
// GETTERS AND SETTERS 
  

 
La tabla física que se genera es la siguiente: 
 
Id  Tipo  Nombre  Apellido  Generacion  GradoDocente 

1  ALUMNO  Juan  Perez  2005  <null> 

2  PROFESOR  Maria  Gonzalez  <null>  grado 3 


 
Ahora veamos este mismo ejemplo pero utilizando la estrategia JOINED 
@Entity 
@Inheritance( strategy = InheritanceType.JOINED ) 
public abstract class Persona { 
 
@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
 
private Integer id; 
  
private String apellido; 
private String nombre; 
  
// SETTERS AND GETTERS 

 
 
@Entity 
@PrimaryKeyJoinColumn(referencedColumnName="id") 
public class Alumno extends Persona implements Serializable { 
  
private int generacion; 
  
// GETTERS AND SETTERS 
  

 
@Entity 
@PrimaryKeyJoinColumn(referencedColumnName="id") 
public class Profesor extends Persona implements Serializable { 
  
private String gradoDocente; 
  
// GETTERS AND SETTERS 
  

 
Esto genera 3 tablas: 
Persona 
 
Id  Nombre  Apellido 

1  Juan  Perez 

2  Maria  Gonzalez 
 
Alumno 
 
Id  Generacion 

1  2005 
 
 
Profesor 
 
Id  GradoDocente 

2  grado 3 
 

Unidades de persistencia
 
La agrupación de entidades en una aplicación se llama ​ unidad de persistencia.​
 La unidad de 
persistence.xml​
persistencia de la aplicación se define en un archivo llamado ​ . Este 
archivo debe existir dentro del directorio META­INF de la aplicación. 
 
El archivo persistence.xml tiene muchas funciones, pero la más importante es la de listar 
todas las entidades, nombrar la unidad de persistencia y brindar los datos necesarios para 
almacenar los datos en la base de datos elegida. 
Un ejemplo de archivo de persistencia es: 
 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.1"> 
    <persistence­unit name="ejemploJPA"> 
        <provider>org.hibernate.ejb.HibernatePersistence</provider> 
        <jta­data­source>java:/XAOracleDS</jta­data­source> 
        <class>com.ejemplo.Curso</class> 
        <class>com.ejemplo.Materia</class> 
        <properties> 
   <property name="hibernate.dialect" 
value="org.hibernate.dialect.Oracle10gDialect"/> 
   <property name="hibernate.hbm2ddl.auto" value="create­drop"/> 
   <property name="hibernate.show_sql" value="true"/> 
  </properties> 
    </persistence­unit> 
 </persistence> 
 
 
 
 
 
 

Java Persistence Query Language


 

Qué es
 
JPQL es un lenguaje de consulta orientado a objetos definido en la especificación de Java 
Persistence API (JPA). 
JPQL es usado para hacer consultas contra las entidades almacenadas en una base de 
datos relacional. Su sintaxis es muy similar a la de SQL, pero mientras SQL trabaja 
directamente con bases de datos relacionales, registros y campos; JPQL lo hace con clases 
Java e instancias. 
Además de recuperar objetos a través de las consultas SELECT, JPQL también soporta 
consultas de actualización y borrado como lo son el UPDATE y DELETE. 
 
 

Sintaxis
 
Veamos primero la sintaxis de este tipo de consultas empezando con un ejemplo. 
 
SELECT m FROM Materia m 
   
Esta query lo que hace es obtener todas las instancias de la clase Materia de la base de 
datos. El SELECT se utiliza para seleccionar cierta información desde el FROM.  
El “FROM Materia m” indica que m es un alias para la clase Materia, mientras que el 
“SELECT m” indica que la expresión m se utiliza para acceder a la clase Materia a la que 
refiere el alias o a sus propiedades. 
 
Si quisiera obtener el nombre de las materias:  
   
SELECT m.nombre FROM Materia m  
 
También puede querer obtener los ids y nombres de todas las materias: 
   
SELECT m.id, m.nombre FROM Materia m 
 
Puedo querer eliminar los resultados duplicados usando la clausula DISTINCT: 
   
SELECT DISTINCT p.nombre FROM Materia m 
 
   
 
También puedo utilizar funciones agregadas como el COUNT, SUM, MAX, MIN, AVG, etc. 
Si quisiera saber la cantidad de materias que tengo: 
   
SELECT COUNT(m) FROM Materia m  
 
El WHERE permite restringir los resultados devueltos por una consulta, en base a ciertos 
criterios lógicos. 
   
SELECT m FROM Materia m 
WHERE m.capacidad < 50  
   
En esta sentencia estoy obteniendo todas las instancias de Materia que  tengan una 
capacidad de menos de 50 estudiantes. También puedo agregar más condiciones: 
   
SELECT m FROM Materia m 
WHERE m.capacidad < 50 AND m.tipo = ‘CIENCIAS’  
 
En este caso se obtienen las materias con capacidad menor a 50 estudiantes y que sean de 
tipo CIENCIAS.    
Puedo utilizar los operadores lógicos AND, OR y NOT.  
   
SELECT m FROM Materia m 
WHERE m.capacidad < 50 AND NOT (m.tipo = ‘CIENCIAS’) 
 
Ahora estoy obteniendo las materias con capacidad menor a 50 estudiantes y que NO sean 
de tipo CIENCIAS.  
   
También puedo utilizar el BETWEEN para comparar entre rangos: 
   
SELECT m FROM Materia m 
WHERE m.capacidad BETWEEN 20 AND 50 
   
Otro operador de comparación muy útil es [NOT] LIKE (NOT es opcional), el cual nos 
permite comparar una cadena de texto completa o solo una parte de ella: 
   
SELECT m FROM Materia m 
WHERE m.nombre LIKE 'A%' 
 
En esta consulta se obtienen todas las instancias de Materia cuyo nombre comience con A. 
 
 

Parámetros
 
Podemos agregar parámetros en forma dinámica a nuestras sentencias JPQL de dos 
maneras: por posición y por nombre.  
 
Por posición:    
SELECT m FROM Materia m 
WHERE m.nombre = ?1 
 
Por nombre:    
SELECT m FROM Materia m 
WHERE m.nombre = :nombre 
   
Cuando quiera ejecutar la consulta tendré que pasar el o los valores que sustituyan a los 
parámetros definidos. 
 
Para poder ordenar los resultados de nuestras consultas, podemos utilizar la cláusula 
ORDER BY que admite ordenamiento ascendente  (ASC que es el por default) o 
descendente (DESC): 
   
SELECT m FROM Materia m 
ORDER BY m.capacidad DESC 
   
Aquí se retornan las materias ordenadas por capacidad de mayor a menor. 
   
SELECT m FROM Materia m 
WHERE m.tipo = ‘CIENCIAS’ 
ORDER BY m.capacidad DESC, m.nombre ASC 
 
Ahora estoy obteniendo todas las materias de tipo CIENCIAS ordenadas por capacidad de 
mayor a menor y el forma alfabética. 
 
Resumiendo: 
Una sentencia select puede tener 6 cláusulas:  
SELECT, FROM, WHERE, GROUP BY, HAVING, and ORDER BY.  
El SELECT y FROM son obligatorias, pero el WHERE, GROUP BY, HAVING, y ORDER BY 
son opcionales.  
 
La sintaxis de alto nivel sería: 
QL_statement ::= select_clause from_clause  
  [where_clause][groupby_clause][having_clause][orderby_clause] 
Donde 
● El SELECT define los tipos de objetos o valores que retorna la query. 
 
● El FROM define el alcance de la query definiendo una o más variables de 
identificación que podrán ser referenciadas en el SELECT y WHERE. Una variable 
de identificación representa uno de los siguientes elementos: 
○ El nombre del esquema abstracto de una entidad 
○ Un elemento colección de una relación 
○ Un elemento de un solo valor de una relación 
○ Un miembro de una colección que es el lado múltiple de una relación one to 
many. 
● El WHERE es una expresión condicional que restringe los objetos o valores que 
retorna la query. 
● El GROUP BY agrupa resultado de acuerdo a un conjunto de propiedades. 
● El HAVING es usado junto con el GROUP BY para restringir los resultados de 
acuerdo a la expresión. 
● El ORDER BY ordena los objetos o valores retornados por la query. 
 

Actualización de datos y borrado


 
La sentencia UPDATE nos permite realizar operaciones de actualización en la base de 
datos: 
   
UPDATE Materia m 
SET m.capacidad = 20 
WHERE m.tipo = ‘CIENCIAS’ 
 
   
En la sentencia anterior se actualizan las instancias de Materia donde el tipo es CIENCIAS, 
poniéndoles capacidad de 20 estudiantes. 
 
También puedo hacer lo siguiente:    
DELETE FROM Materia m 
WHERE m.capacidad = 0 
 
De esta manera borro las materias que no tengan capacidad para estudiantes. 
 
Resumiendo… 
La sintaxis es: 
update_statement :: = update_clause [where_clause]  
delete_statement :: = delete_clause [where_clause] 
 
El update y delete determinan el tipo de entidades que serán actualizadas o borradas. El 
WHERE es opcional y se usa para restringir el alcance de los datos actualizados o 
borrados. 
 

Ejecutando sentencias JPQL


 
Los métodos EntityManager.createQuery y EntityManager.createNamedQuery se utilizan 
para realizar búsquedas en la base de datos utilizando consultas JPQL. 
El método createQuery se utiliza para crear las consultas dinámicas, que son consultas 
definidas directamente dentro de la lógica de negocio de una aplicación: 
 
public List obtenerMateriasPorTipo(String tipoMateria) { 
return em.createQuery( 
    "SELECT m FROM Materia m WHERE m.tipo LIKE :tipo") 
    .setParameter("tipo", tipoMateria) 
    .setMaxResults(10) // indica cantidad máxima de resultados 
    .getResultList(); 

 
El método createNamedQuery se utiliza para crear consultas estáticas o consultas que se 
definen en los metadatos mediante el uso de la anotación javax.persistence.NamedQuery. 
El elemento name de @NamedQuery especifica el nombre de la consulta que se utilizará 
con el método createNamedQuery.  
Por ejemplo: 
En el entity de Materia puedo definir: 
@NamedQuery ( 
    name = "Materia.obtenerPorTipo", 
    query = "SELECT m FROM Materia m WHERE m.tipo LIKE :tipo" 
 ) 
 
Y para usar el método createNamedQuery, que utiliza la @NamedQuery : 
@PersistenceContext 
public EntityManager em; 
... 
materias = em.createNamedQuery("Materia.obtenerPorTipo") 
    .setParameter("tipo", "CIENCIAS") 
    .getResultList(); 
 

Los named parameters son los parámetros de consulta con el prefijo dos puntos ( : ). Estos 
parámetros se setean utilizando el método javax.persistence.Query.setParameter (String 
nombre, Object valor) 

Los named parameters son case sensitive y pueden ser utilizados por ambas consultas 
dinámicas y estáticas. 

En el método obtenerMateriaPorTipo, el named parameter es “tipo”. 
 

En vez de los named parameters pueden utilizarse parámetros posicionales en las 
consultas. Los parámetros posicionales van precedidos de un signo de interrogación ( ? ), 
seguido de la posición numérica del parámetro de la consulta. El método 
Query.setParameter(integer position, Object value) se utiliza para establecer los valores de 
los parámetros. 

Reescribiendo el método de obtenerMateriasPorTipo con parámetros posicionales sería: 
public List obtenerMateriasPorTipo(String tipoMateria) { 
return em.createQuery( 
    "SELECT m FROM Materia m WHERE m.tipo LIKE ?1") 
    .setParameter(1, tipoMateria) 
    .setMaxResults(10) 
    .getResultList(); 

 

Query versus query tipada


 
Para obtener todas las materias, por ejemplo, tengo 2 formas de hacerlo: 
 
Query query = em.createQuery("SELECT m FROM Materia m"); 
List resultados = query.getResultList(); 
 

 
TypedQuery<Materia> query = em.createQuery("SELECT m FROM Materia m", 
Materia.class); 
List<Materia> resultados = query.getResultList(); 
 
El objeto Query y el TypedQuery definen ambos un método getResultList, pero la versión de 
Query retorna una lista de un tipo de dato no genérico, en vez de uno parametrizado 
(genérico). 
 
Las queries tipadas también puedo utilizarlas de forma análoga con las named queries: 
TypedQuery<Materia> query = em.createNamedQuery("Materia.obtenerTodas", 
Materia.class); 
List<Materia> resultados = query.getResultList(); 
 
Es una buena práctica utilizar Queries tipadas, de esa manera ya le indicamos de antemano 
que tipo de dato nos debe retornar.  
 
 
 

Consultas nativas SQL

Por último puedo querer ejecutar sentencias SQL nativas en vez de una sentencia JPQL: 

String sql = "SELECT * FROM MATERIA"; 
Query query = em.createNativeQuery(sql); 
// ...    

Estas consultas SQL nativas también pueden ser definidas de manera estática: 

@Entity  
@NamedNativeQuery(name=”Materia.obtenerTodas”, query="SELECT * FROM MATERIA")  
public class Materia {  
    // ...  
}    

 
 
 
 
 

Manejo de Entidades
 

Entity Manager
 
Las entidades son gestionadas por el gestor de entidades, que está representado por el 
javax.persistence.EntityManager. Cada instancia del EntityManager, se asocia con un 
contexto de persistencia: un conjunto de instancias de entidades manejadas que existen en 
cierto almacén de datos.  
Un contexto de persistencia define el alcance bajo el cual instancias de entidades son 
creadas, persistidas y removidas. La interfaz EntityManager define los métodos que se 
utilizan para interactuar con el contexto de persistencia. 

La interfaz EntityManager
La API EntityManager crea y elimina instancias de entidad persistentes, encuentra las 
entidades por la clave primaria de la entidad, y permite ejecutar consultas en las entidades. 

Entity Managers manejados por contenedor


Con un gestor de entidades manejados por contenedor, una instancia del EntityManager del 
contexto de persistencia se propaga automáticamente por el contenedor a todos los 
componentes de las aplicaciones que utilizan la instancia del EntityManager dentro de una 
transacción única JTA (API Java Transaction). 
Las transacciones JTA por lo general implican llamadas a través de componentes de la 
aplicación. Para completar una transacción JTA, estos componentes por lo general 
necesitan tener acceso a un único contexto de persistencia. Esto ocurre cuando un 
EntityManager se inyecta en los componentes de la aplicación por medio de la anotación 
javax.persistence.PersistenceContext.  
El contexto de persistencia se propaga automáticamente con la transacción JTA actual, y 
las referencias de EntityManager que se asignan a la misma unidad de persistencia 
proporcionan acceso al contexto de persistencia dentro de esa transacción. Al propagar 
automáticamente el contexto de persistencia, los componentes de aplicaciones no necesitan 
pasar referencias a las instancias de EntityManager entre sí con el fin de realizar cambios 
dentro de una única transacción. El contenedor Java EE gestiona el ciclo de vida de los 
gestores de entidad manejados por el contenedor. 
 
Para obtener una instancia del EntityManager, basta con inyectar el manejador de la entidad 
en el componente de aplicación: 
 
 
@PersistenceContext 
 EntityManager em; 
 

La gestión del ciclo de vida de una entidad


 
Se pueden administrar instancias de entidad a través de la invocación de operaciones 
utilizando una instancia del EntityManager. Una instancia de una entidad puede estar en 
uno de estos cuatro estados: new, managed, detached, o removed. 
● New: no tienen identidad persistente y aún no están asociados con un contexto de 
persistencia. 
● Managed: tienen una identidad persistente y están asociados con un contexto de 
persistencia. 
● Detached: tienen una identidad persistente y en la actualidad no están asociados 
con un contexto de persistencia. 
● Removed: tienen una identidad persistente, están asociados con un contexto 
persistente, y están programadas para ser removidas del almacén de datos. 
 
Supongamos el siguiente ejemplo de entidad: 
 
@Entity  
public class Curso{  
    @Id  
    @GeneratedValue  
    private Long id;  
    private String nombre;  
    @OneToMany (Cascade = ALL) 
    private List<Materia> materias = new ArrayList<Materia>();   
    // Getters y Setters  

 
Para que JPA pueda persistir esta entidad, necesita un archivo de configuración XML 
llamado ​ persistence.xml​ META­INF​
, el cual debe estar ubicado en el directorio ​  de nuestra 
aplicación.  
Para este ejemplo sería: 
   
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> 
    <persistence­unit name="ejemploJPA" transaction­type="RESOURCE_LOCAL"> 
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
        <class>com.ejemplo.Curso</class> 
        <class>com.ejemplo.Materia</class> 
        <properties> 
 
            <property name="eclipselink.jdbc.driver" 
value="oracle.jdbc.OracleDriver"></property> 
            <property name="eclipselink.jdbc.url" 
value="oracle:thin:@myhost:l521:MYSID"></property> 
            <property name="eclipselink.jdbc.user" value="APP"> </property> 
            <property name="eclipselink.jdbc.password" value="APP"> </property> 
            <property name="eclipselink.ddl­generation" value="create­tables"> </property> 
        </properties> 
    </persistence­unit> 
 </persistence> 
   
persistence.xml​
El archivo ​  tiene toda la información necesaria para almacenar los datos en 
la base de datos elegida, como el nombre de la unidad de persistencia, el tipo de 
transacciones que vamos a utilizar, las clases que deseamos que sean manejadas por el 
proveedor de persistencia, y los parámetros para conectar con nuestra base de datos. 
 
El concepto de transacción representa un contexto de ejecución dentro del cual podemos 
realizar varias operaciones como si fuera una sola, de manera que o todas ellas son 
ejecutadas, o el proceso entero falla.  
JPA nos permite configurar en cada unidad de persistencia el tipo de transacción que 
queremos usar, que puede ser:     
● Manejada por la aplicación (RESOURCE_LOCAL) 
● Manejada por el contenedor (JTA) 
 
Para JPA, una entidad puede estar en uno de los dos estados siguientes:  
● Managed (gestionada) 
● Detached (separada) 
   
Cuando persistimos una entidad automáticamente se convierte en una entidad ​ gestionada.​ 
Todos los cambios que efectuemos sobre ella dentro del contexto de una transacción se 
verán reflejados también en la base de datos, de forma transparente para la aplicación. 
   
El segundo estado en el que puede estar una entidad es ​ separado,​ en el cual los cambios 
realizados en la entidad no están sincronizados con la base de datos. Una entidad se 
encuentra en estado separado antes de ser persistida por primera vez, y cuando tras haber 
estado gestionada es separada de su contexto de persistencia. 
   

Persistiendo una entidad


Las instancias de entidad nuevas, se convierten en administradas y persistentes de dos 
maneras posibles: mediante la invocación del método ​persist​ o por una operación cascada 
 
persist invocada por entidades relacionadas que tienen la propiedad cascade=PERSIST o 
cascade=ALL.  
Esto significa que los datos de la entidad se almacenan en la base de datos cuando la 
transacción asociada al persist se completa.  
 
El siguiente método realiza una persist operación: 
 
@PersistenceContext 
 EntityManager em; 
 ... 
 public void crearMateria (Materia materia) { 
    em.persist (materia); 
 } 
 
Cuando llamamos a em.persist(materia) la entidad es persistida en nuestra base de datos, 
la entidad Materia queda gestionada por el proveedor de persistencia mientras dure la 
transacción. Por ello, cualquier cambio en su estado será sincronizado automáticamente y 
de forma transparente para la aplicación:     
 
em.persist(materia); 
materia.setNombre("otro nombre"); 
 
Modificamos el nombre de la entidad materia después de haber sido persistida, pero como 
estoy dentro de la misma transacción que realizó la persistencia los datos se sincronizarán 
con la base de datos. Es importante tener presente que esta sincronización puede no ocurrir 
hasta que se complete la transacción e internamente se realice el commit en la base de 
datos (el momento en que la sincronización se lleve a cabo depende enteramente de la 
implementación concreta del proveedor de persistencia que usemos). Lo que podemos 
hacer en este caso es forzar a que cualquier cambio pendiente se guarde en la base de 
datos en el momento que querramos invocando el método flush() de EntityManager: 
 
em.persist(materia); 
materia.setNombre("otro nombre"); 
em.flush(); 
 
También podemos realizar la sincronización en sentido inverso, actualizando una entidad 
con los datos que se encuentran en la base de datos. Esto es útil cuando persistimos una 
entidad, y tras haber cambiado su estado deseamos recuperar el estado persistido y 
deshacer los últimos cambios realizados sobre la entidad. Esto lo realizamos con el método 
refresh() del EntityManager: 
  
em.persist(materia); 
materia.setNombre("otro nombre"); 
em.refresh(materia); 
   
 
La llamada al em.refresh() deshace los cambios realizados en materia en la línea anterior.  
 
Otro método del EntityManager es el contains(): 
   
boolean gestionada = em.contains(materia); 
   
El método contains() devuelve true si el objeto Java que le pasamos como parámetro se 
encuentra en estado gestionado por el proveedor de persistencia, y false en caso contrario. 
 
 
La operación persist se propaga a todas las entidades relacionadas con la entidad llamante 
que tienen la propiedad cascade ALL o PERSIST en la anotación relación: 
 
public Materia crearMateria(Curso curso, String nombre, int capacidad) { 
    Materia materia = new Materia(nombre, capacidad); 
    curso.getMaterias().add(materia); 
    em.persist(materia); 
    return materia; 

 

Buscando una entidad


 
Para obtener una entidad previamente persistida en la base de datos tengo 2 maneras de 
hacerlo:     
● Obteniendo un objeto real 
● Obteniendo una referencia a los datos persistidos 
   
Obteniendo un objeto real: puedo realizarlo a través del método find. Este método del 
EntityManager se utiliza para buscar entidades a partir de la clave primaria de la entidad: 
   
Materia materia = em.find(Materia.class, id); 
   
Obteniendo una referencia a los datos persistidos: nos permite obtener una referencia a los 
datos almacenados en la base de datos, de manera que el estado de la entidad será leído 
de forma demorada. Se lee en el primer acceso a cada propiedad y no en el momento de la 
creación de la entidad: 
   
Materia materia = em.getReference(Materia.class, id); 
 
En ambos casos, el valor de id es la clave primaria de la entidad. 
 

Actualizando una entidad


 
 
Primero veamos como puedo separar una entidad gestionada por el contexto de 
persistencia. Esto puedo realizarlo con los métodos detach (separa un entidad) y clear 
(separa todas las entidades).  
Una vez que una entidad se encuentra separada, esta deja de estar gestionada, y por tanto 
los cambios en su estado dejan de ser sincronizados con la base de datos. 
Para volver a tener nuestra entidad gestionada y sincronizada es que utilizaremos el método 
merge() de EntityManager: 
 
em.persist(materia); 
em.detach(materia); 
// otras operaciones 
em.merge(materia); 
 
Separa la materia del contexto de persistencia llamando al método detach(). La última línea, 
sin embargo, indica al proveedor de persistencia que vuelva a gestionar la entidad, y que 
sincronice los cambios en la base de datos. 
 

Eliminando una entidad


 
Cuando invocamos al método remove del EntityManager la entidad es eliminada de la base 
de datos y separada del contexto de persistencia. Sin embargo, la entidad seguirá 
existiendo como objeto Java en nuestro código hasta que el ámbito de la variable termine: 
   
em.remove(materia); 
materia.setNombre("ya no soy una entidad, soy solo un objeto Java"); 
 
Si el remove método se invoca en una entidad nueva, la operación del remove se ignora. Si 
el remove se invoca en una entidad detached, el remove lanzará una 
IllegalArgumentException o la confirmación de transacción fallará.  
Si se invoca en una entidad que ya se haya removido, el remove será ignorado. Los datos 
de la entidad se eliminarán de la memoria de datos cuando se termina la transacción, o 
como resultado de la operación flush. 
 
En el siguiente ejemplo, todas las Materias asociadas al curso se removerán, esto es 
porque la lista de materias tiene cascade=ALL: 
 
public void removeCurso(Integer cursoId) { 
    try { 
        Curso curso = em.find(Curso.class, cursoId); 
        em.remove(curso); 
    }... 
 
 

Sincronización de datos de la entidad a la base de datos


 
Cuando llamamos a persist(), merge (), o remove(), estos cambios no se sincronizan con la 
base de datos hasta que el EntityManager decida confirmarlos. Podemos forzar la 
sincronización en cualquier momento llamando a flush() en el EntityManager, de modo que 
los cambios realizados ya pasen a la BD. Por defecto, se invoca a flush antes que se 
ejecute una query relacionada con los cambios y al momento de realizar commit en una 
transacción. 
 

Métodos callback
 
Los métodos ​ callback​
 son métodos que se ejecutan cuando se producen ciertos eventos 
relacionados con el ciclo de vida de una entidad. Estos eventos se clasifican en cuatro 
categorías: 
   
● Eventos de persistencia (métodos callback asociados anotados con @PrePersists y 
@PostPersist: antes y después de persistir) 
● Eventos de actualización (métodos callback asociados anotados con @PreUpdate y 
@PostUpdate: antes y después de actualizar) 
● Eventos de borrado (métodos callback asociados anotados con @PreRemove y 
@PostRemove: antes y después de remover) 
● Eventos de carga (método callback asociado anotado con @PostLoad: luego de 
cargar) 
   
@Entity  
public class Materia{  
    ...  
    @PrePersist  
    @PreUpdate  
    private void validar() {  
        // validación de parámetros antes de persistir/actualizar la entidad  
    }  
}   
El método validar() se ejecutará ante 2 eventos: el momento antes de realizarse la 
persistencia (@PrePersist), y el momento previo a la actualización (@PreUpdate).  
Al escribir métodos callback, debemos seguir algunas reglas para que nuestro código sea 
válido:    
● Un método callback no puede ser declarado static ni final 
● Cada anotación de ciclo de vida puede aparecer una y solo una vez en cada entidad 
● Un método callback solo puede tirar excepciones de tipo unchecked (de runtime) 
● Un método callback no puede invocar métodos de las clases EntityManager y/o 
Query 
   
 

Clases listener
 
Cuando necesitamos aplicar un mismo método callback a varias entidades, es preferible 
extraer de la entidad este método y ponerlo en una clase externa, la cual podrá ser aplicada 
a varias entidades. Estas son las clases listener: 
   
public class ValidadorListener {  
    @PrePersist  
    @PreUpdate  
    public void validar(Materia materia) {  
        // validar parametros antes de persistir/actualizar la entidad  
    }  
}  
   
Ahora debemos aplicar el listener a las entidades que querramos: 
   
@Entity 
@EntityListeners(ValidadorListener.class) 
public class Materia { ... } 
   
En tiempo de ejecución, cuando se produzca un evento que se encuentre definido en la 
clase listener, el proveedor de JPA pasará a su método validar() una referencia de la 
entidad Materia.  
   
También existe la anotación @EntityListeners puede hacer referencia a varias clases 
listener usando un array de objetos .class. Cuando una entidad es asociada con varias 
clases listener, los métodos callback de dichas clases que hagan referencia a un mismo 
evento serán invocados en el orden en que fueron declarados dentro del array.  
Así mismo, los métodos callback de las clases listener serán invocados de manera previa a 
los métodos callback que hagan referencia al mismo tipo de evento y que estén declarados 
dentro de la entidad: 
   
@Entity  
@EntityListeners({  
        ValidadorListener.class,  
        OtroListener.class})  
public class Materia {  
    // ...  
   
    @PrePersist  
    @PreUpdate  
    private void validar() {  
        // validar parámetros antes de persistir y actualizar la entidad  
    }  
 
}  
 
En este ejemplo, los métodos @PrePersist y @PreUpdate se ejecutarán en este orden: 
ValidatorListener, OtroListener, Materia. 
 
JPA
Java Persistence API
¿Que es JPA?

Estándar para gestionar datos relacionales en aplicaciones Java

JPA establece una interface común para distintos proveedores de persistencia


(Hibernate, EclipseLink, OpenJPA, DataNucleus ...)

Cada proveedor de persistencia dá una interface común para distintos


proveedores de bases de datos (MySQL, Oracle, PostgreSQL …)
¿Como funciona? Arquitectura

Gestor
BD

Fuente: OpenJPA (Apache JPA)


http://openjpa.apache.org/builds/2.4.1/apache-openjpa/docs/manual.html#jpa_overview_arch
¿Cómo funciona? Clases
● Persistence: La clase javax.persistence.Persistence contiene métodos estáticos para obtener instancias de
EntityManagerFactory.
● EntityManagerFactory: Esta clase es una factory para EntityManager.
● EntityManager : javax.persistence.EntityManager es la entrada primaria a JPA usada por las aplicaciones. Cada EntityManager
maneja un conjunto de objetos a persistir, y tiene APIs para insertar y borrar objetos. Cuando se usa fuera del contenedor, hay una
relación uno a uno entre un EntityManager y un EntityTransaction. EntityManagers también actúan como factory para instancias de
Query.
● Entity : Estos son objetos persistentes que representan registros de la BD.
● EntityTransaction: Cada EntityManager tiene una relación uno a uno con un único javax.persistence.EntityTransaction. Esta
clase permite que las operaciones en datos almacenados sean agrupados en unidades de trabajo que completan exitosamente o
fallan totalmente, dejando la BD en su estado original. Estas operaciones “todo o nada” son importantes para mantener la integridad
de datos.
● Query : javax.persistence.Query es una interface implementada por cada proveedor JPA para encontrar objetos persistidos que
cumplen un cierto criterio. JPA estandariza el soporte para queries usando tanto Java Persistence Query Language (JPQL) y
Structured Query Language (SQL). Se obtienen instancias de Query de un EntityManager.
Fuente: OpenJPA (Apache JPA)
http://openjpa.apache.org/builds/2.4.1/apache-openjpa/docs/manual.html#jpa_overview_arch
¿Cómo funciona? Annotations en la aplicación
@Entity @Entity(name=<String>)
@Table(name = "PERSONA") @Table(<propiedades tabla…>)
public class Persona {
@Id @Id
@GeneratedValue @GeneratedValue(<propiedades generación clave…>)
private Long id;
@Column(nullable=false) @Column(<propiedades columna...>)
private String nombre; @Basic(fetch=<fetchType>,optional=<boolean>)
@Column(nullable=true) @Transient
private Date fechaNacimiento;
@Transient private int edad;
// Getters y Setters
}
Ejemplo guiado
 
 
 

Tipos de EJBs
 
 Un EJB suele estar compuesto por una clase de implementación y cero o mas interfaces de 
negocio. La clase de implementación contiene las implementaciones de los métodos de 
negocio. Debe estar anotada con: @Stateless, @Stateful o @Singleton 
Las interfaces de negocio contienen las declaraciones de los métodos de negocio visibles al 
cliente y son implementadas por el bean. 

Sin estado
Un EJB Stateless es una clase java sin estado, es decir, no debería tener atributos, sólo 
métodos a los que se pueda llamar de forma independiente. Este tipo de EJB no mantienen 
estado conversacional ni presentan problemas de concurrencia. 
 
Para que el contenedor de aplicaciones lo maneje, sólo hay que ponerle la anotación 
@Stateless 
 
import javax.ejb.LocalBean; 
import javax.ejb.Stateless; 
 
@Stateless 
@LocalBean 
public class SinEstadoBean  { 
   public void holaMundo(String texto){ 
      System.out.println(“Hola mundo: ”+texto); 
   } 

 
Es una clase con un método al que se le pasa un texto y muestra en consola “Hola mundo” 
seguido del texto pasado.  
La anotación @Stateless es la que lo convierte en un EJB y le indica al contenedor de 
aplicaciones que debe encargarse de manejarlo.  
La anotación @LocalBean indica que a esta clase no se va a acceder de forma remota 
(desde fuera de nuestra aplicación). Esta anotación es opcional, ya que por defecto se 
asume que el bean no va a ser accedido de forma remota. 
 
Para los EJB sin estado, el contenedor de aplicaciones va a crear varias instancias de estas 
clase y le pasará estas instancias a quien las necesite. Como son clases sin estado, el 
contenedor dará cualquiera de las instancias que tiene al que la necesite y no se 
preocupará de entregar siempre la misma al mismo cliente.  
 
 

Con estado
Un EJB con estado es una clase en la que sí hay atributos y cuyo valor es importante y 
debe conservarse entre llamadas a métodos.  
El contenedor de aplicaciones instanciará, al igual que con los EJB sin estado, un número 
determinado de ellos, asegurandose de dar siempre al mismo cliente/usuario la misma 
instancia. De esta manera, el cliente puede guardar en él datos que sean propios de él y 
que necesiten conservarse mientras está trabajando con la aplicación.  
Un ejemplo típico es el carrito de la compra de una web. Los productos que el usuario va 
añadiendo al carrito se guardarían en un EJB con estado. 
 
import javax.ejb.EJB; 
import javax.ejb.LocalBean; 
import javax.ejb.Remove; 
import javax.ejb.Stateful; 
 
@Stateful 
@LocalBean 
public class ConEstadoBean { 
   @EJB 
   SinEstadoBean sinEstadoBean; 
   
   // Estado 
   private String estado; 
   
   public void setEstado(String estado){ 
      this.estado = estado; 
   } 
   
   @Remove 
   public void mostrarEstado(){ 
      sinEstadoBean.holaMundo(estado); 
   } 

 
Esta clase utiliza la anotación @Stateful para indicar que es un EJB con estado. La 
anotación @LocalBean, al igual que antes, es opcional e indica que este bean no se va a 
utilizar de forma remota. 
Esta clase tiene un atributo de tipo String llamado estado y un método setEstado que le da 
un valor. Como se trata de un EJB con estado, este estadose conservará para la llamada a 
mostrarEstado().  
 
La anotación @Remove en el método mostrarEstado() se usa para indicar al contenedor 
que ya hemos terminado de usar este EJB con estado. Cuando encuentra esta llamada el 
contenedor sabe que puede darle este EJB a otro que lo necesite pues ya fue usado. 
 
Tenemos también el atributo @EJB SinEstadoBean sinEstadoBean que utilizaremos para 
realizar la llamada a nuestro holaMundo de modo de mostrar en consola el estado. Como 
SinEstadoBean es un EJB controlado por el contenedor de aplicaciones, no hacemos 
nosotros el new de esta clase, la anotamos con @EJB y es el contenedor quien se 
encargará de pasarnos una de las instancias que tiene de SinEstadoBean y podremos 
usarla. 

Singleton
Un EJB Singleton es una clase Java que el contenedor de aplicaciones instanciará una 
única vez y será compartida en la aplicación por los clientes. Está pensada para guardar los 
datos que son comunes a todos los usuarios o clientes de nuestra aplicación. 
import javax.annotation.PostConstruct; 
import javax.annotation.PreDestroy; 
import javax.ejb.Singleton; 
import javax.ejb.Startup; 
 
@Singleton 
@Startup 
public class SingletonBean { 
   @PostConstruct 
   public void init() { 
      System.out.println("SingletonBean arranca"); 
   } 
   
   @PreDestroy 
   public void destroy() { 
      System.out.println("SingletonBean termina"); 
   } 

 
La anotación @Singleton convierte a esta clase Java en un Singleton.  
La anotación @Startup nos sirve para indicarle al contenedor de aplicaciones que debe 
arrancar este EJB al inicio. Si no ponemos la anotación, el bean no arranca hasta que 
alguien lo necesite.  
En general la anotación @Startup no se utiliza, salvo que este bean realice algo que 
necesite ser hecho en el momento de arrancar el contenedor de aplicaciones/nuestra 
aplicación. 
Cuando este EJB arranque se ejecutará lo que esté dentro del método con @PostConstruct. 
Si no hay ningún método con esta anotación, no se hará nada en el arranque, pero si hay 
algún método anotado de esta manera, se ejecutará después de cargar el bean, pero antes 
de que empiece a usarse. Es un método de inicialización de la clase. 
Si queremos realizar alguna acción cuando el bean se vaya a destruir (al finalizar nuestra 
aplicación), debemos anotar el método que queramos que se ejecute con @PreDestroy. 
 
Apuntes de Aplicaciones Enterprise

Contenido

Implementar herencia con estrategia SIMPLE 2

Implementar herencia tipo JOINED 8

Implementar una relación N a N 17

Página 1
Implementar herencia con estrategia SIMPLE
Característica: una tabla para toda la jerarquía.

Se implementó el siguiente diagrama de clases:

Se persistió una instancia de Profesor y otra de Alumno, y se obtuvo una tabla en la base de
datos con la siguiente estructura y contenido:

Página 2
Se implementó de la siguiente manera en el servidor:

Persona.java

package com.entidades;

import java.io.Serializable;
import javax.persistence.*;

@Entity
@Table
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="tipo")
public class Persona implements java.io.Serializable {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;

@Column(length=20)
private String nombre;

@Column(length=20)
private String apellido;

public Persona() {
super();
}
// getters y setters
}
}

Página 3
Alumno.java

package com.entidades;

import java.io.Serializable;
import javax.persistence.*;

@Entity
@DiscriminatorValue(value="ALUMNO")
public class Alumno extends Persona implements Serializable {

private int generacion;

public Alumno() {
super();
}
//getters y setters
}

Profesor.java

package com.entidades;

import java.io.Serializable;
import javax.persistence.*;

@Entity
@DiscriminatorValue(value="PROFESOR")
public class Profesor extends Persona implements Serializable {

private String gradoDocente;

public Profesor() {
super();
}
//getters y setters
}

Página 4
PersonasBeanRemote.java

package com.servicios;

import java.util.List;
import javax.ejb.Remote;
import com.entidades.*;

@Remote
public interface PersonasBeanRemote {

public void crear(Profesor profesor);


public void crear(Alumno alumno);
public List<Persona> obtenerTodos();
public Profesor buscarProfesor(Long id);
public Alumno buscarAlumno(Long id);

PersonasBean.java

package com.servicios;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.*;
import com.entidades.*;

@Stateless
public class PersonasBean implements PersonasBeanRemote {

@PersistenceContext
private EntityManager em;

public PersonasBean() {
}

@Override
public void crear(Profesor profesor) {
em.persist(profesor);
em.flush();
}

@Override
public void crear(Alumno alumno) {

Página 5
em.persist(alumno);
em.flush();
}

@Override
public List<Persona> obtenerTodos() {
TypedQuery<Persona> query = em.createQuery("SELECT p FROM Persona
p ",Persona.class);
return query.getResultList();

@Override
public Profesor buscarProfesor(Long id) {
Profesor p = em.find(Profesor.class, id);
return p;
}

@Override
public Alumno buscarAlumno(Long id) {
Alumno a = em.find(Alumno.class, id);
return a;
}

Archivos de configuración en el servidor:

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>


<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="Herencia_1_EJB">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/HerenciaDS</jta-data-source>
<mapping-file>META-INF/orm.xml</mapping-file>
<class>com.entidades.Persona</class>
<class>com.entidades.Alumno</class>
<class>com.entidades.Profesor</class>
<validation-mode>AUTO</validation-mode>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />

Página 6
<property name="hibernate.show_sql" value="true" />
<property
name="javax.persistence.schema-generation.create-database-schemas" value="true"/>
</properties>
</persistence-unit>
</persistence>

orm.xml

<?xml version="1.0" encoding="UTF-8"?>


<entity-mappings version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd">
<persistence-unit-metadata>
<persistence-unit-defaults>
<access>FIELD</access>
</persistence-unit-defaults>
</persistence-unit-metadata>
<entity class="com.entidades.Persona" access="FIELD">
<table name="PERSONAS">
</table>
</entity>
</entity-mappings>

Página 7
En el cliente se implementó la siguiente clase para realizar la prueba:

package com.cliente;

import java.util.List;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.entidades.*;
import com.servicios.PersonasBeanRemote;

public class Cliente_H1 {

public static void main(String[] args)throws NamingException {

PersonasBeanRemote person = (PersonasBeanRemote)


InitialContext.doLookup("Herencia_1_EJB/PersonasBean!com.servicios.PersonasBeanRem
ote");

altasPersonas(person);

List<Persona> per = person.obtenerTodos();


Alumno aux;
Profesor prof;

for (Persona pe : per) {

if (pe instanceof Profesor) {


System.out.println("Es un profesor");
Long id=pe.getId();
prof=person.buscarProfesor(id);
System.out.print(prof.getNombre()+" --- ");
System.out.print(prof.getApellido()+ "-- grado : ");
System.out.println(prof.getGradoDocente());

} else if(pe instanceof Alumno) {


System.out.println("Es un Alumno");
Long id=pe.getId();
aux=person.buscarAlumno(id);
System.out.print(aux.getNombre()+" --- ");
System.out.print(aux.getApellido()+ "-- generacion : ");
System.out.println(aux.getGeneracion());

Página 8
}

// Metodo que da de altas Profesores y Alumnos


public static void altasPersonas(PersonasBeanRemote per) {

per.crear(new Profesor("Jose","Granada","grado4"));
per.crear(new Alumno("Ana","Marquez",2019));
per.crear(new Profesor("Marta","Dinardi","grado2"));
per.crear(new Alumno("Daniel","Ventos",2020));
per.crear(new Alumno("Luis","Fontes",2020));
per.crear(new Alumno("Antonio","Rios",2020));
per.crear(new Alumno("Joaquin","Beal",2020));
per.crear(new Alumno("Emiliano","Silva",2019));
per.crear(new Profesor("Sergio","Trias","grado 2"));

Resultado de la salida por la consola del listado total de Personas :

Es un profesor
Jose --- Granada-- grado : grado4
Es un Alumno
Ana --- Marquez-- generacion : 2019
Es un profesor
Marta --- Dinardi-- grado : grado2
Es un Alumno
Daniel --- Ventos-- generacion : 2020
Es un Alumno
Luis --- Fontes-- generacion : 2020
Es un Alumno
Antonio --- Rios-- generacion : 2020
Es un Alumno
Joaquin --- Beal-- generacion : 2020

Página 9
Es un Alumno
Emiliano --- Silva-- generacion : 2019
Es un profesor
Sergio --- Trias-- grado : grado 2

Implementar herencia tipo JOINED


Característica: una tabla para cada entidad.

Se implementó el siguiente diagrama de clases:

Página 10
Se persistió una instancia de Profesor y otra de Alumno, y se obtuvo las siguientes tablas en
la base de datos con la siguiente estructura y contenido:

Una tabla PERSONAS con los dos registros (un profesor y un alumno) y su ID
correspondiente:

Una tabla PROFESORES sólo con el registro del profesor, con el ID que le corresponde y
con el atributo propio del profesor (gradoDocente).

Una tabla ALUMNOS sólo con el registro del alumno, con el ID que le corresponde y con el
atributo propio del alumno (generacion).

Página 11
Se implementó de la siguiente manera en el servidor:

Persona.java

package com.entidades;

import javax.persistence.*;

@Entity
@Table(name="PERSONAS")
@Inheritance(strategy=InheritanceType.JOINED)
public class Persona implements java.io.Serializable{

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_PER"
)
@SequenceGenerator(name = "SEQ_PER", initialValue = 1, allocationSize = 1)

private Long id;


private String nombre;
private String apellido;

public Persona() {
super();
}

public Persona(Long id, String nombre, String apellido) {


this.id = id;
this.nombre = nombre;
this.apellido = apellido;
}

// getters y setters
}

Página 12
Alumno.java

package com.entidades;

import java.io.Serializable;
import javax.persistence.*;

@Entity
@Table(name="ALUMNOS")
@PrimaryKeyJoinColumn(referencedColumnName="id")
public class Alumno extends Persona implements Serializable {

private int generacion=0;

public Alumno() {
super();
}

// getters y setters
}

Profesor.java

package com.entidades;

import java.io.Serializable;
import javax.persistence.*;

@Entity
@Table(name="PROFESORES")
@PrimaryKeyJoinColumn(referencedColumnName="id")
public class Profesor extends Persona {

private String gradoDocente;

public Profesor() {
super();
}

// getters y setters
}

Página 13
PersonasBeanRemote.java

package com.servicios;

import java.util.List;
import javax.ejb.Remote;
import com.entidades.*;

@Remote
public interface PersonasBeanRemote {

public void crear(Profesor profesor);


public void crear(Alumno alumno);
}

PersonasBean.java

package com.servicios;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.*;
import com.entidades.*;

@Stateless
public class PersonasBean implements PersonasBeanRemote {

@PersistenceContext
private EntityManager em;

public PersonasBean() {
}

@Override
public void crear(Profesor profesor) {
em.persist(profesor);
em.flush();
}

@Override
public void crear(Alumno alumno) {
em.persist(alumno);
em.flush();
}
}

Página 14
Archivos de configuración en el servidor:

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>


<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="Herencia_2_EJB">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/HerenciaDS</jta-data-source>
<mapping-file>META-INF/orm.xml</mapping-file>
<validation-mode>AUTO</validation-mode>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true" />
<property
name="javax.persistence.schema-generation.create-database-schemas" value="true"/>
</properties>
</persistence-unit>
</persistence>

orm.xml

<?xml version="1.0" encoding="UTF-8"?>


<entity-mappings version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd">
<persistence-unit-metadata>
<persistence-unit-defaults>
<access>FIELD</access>
</persistence-unit-defaults>
</persistence-unit-metadata>
<entity class="com.entidades.Persona" access="FIELD">
<table name="PERSONAS"></table>
<inheritance strategy="JOINED"/></entity>
<entity class="com.entidades.Profesor" access="FIELD">
<table name="PROFESORES">
</table></entity>
<entity class="com.entidades.Alumno" access="FIELD">
<table name="ALUMNOS">
</table></entity></entity-mappings>

Página 15
En el cliente se implementó la siguiente clase para realizar la prueba:

import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.entidades.*;
import com.servicios.PersonasBeanRemote;

public class Cliente {

public static void main(String[] args)throws NamingException {

String
ruta="ejb:/Herencia_2_EJB/PersonasBean!com.servicios.PersonasBeanRemote";
PersonasBeanRemote person = (PersonasBeanRemote)
InitialContext.doLookup(ruta);

Profesor p = new Profesor();


p.setNombre("Jose");
p.setApellido("Granada");
p.setGradoDocente("grado 4");
try {
person.crear(p);
} catch(Exception e) {
System.out.println("Error al crear Profesor");
System.out.println(e.getMessage());
}

Alumno a = new Alumno();


a.setNombre("Ana");
a.setApellido("Marquez");
a.setGeneracion(2019);

try{
person.crear(a);
} catch(Exception e) {
System.out.println("Error al crear Alumno");
System.out.println(e.getMessage());
}
}
}

Para hacer el listado total, se hace de la misma forma que con una sola tabla. Fijarse el
ejemplo anterior.

Página 16
Implementar una caso de ManyToMany

Dado una entidad Libro, que puede tener muchos Autores, y que un Autor puede estar en
muchos Libros, tenemos una relación de N a N.

Vamos a verlo en un Ejemplo.

Entidades

Entidad Libro:

package com.entidades;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.*;

@Entity
@Table(name="LIBROS")
public class Libro implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@SequenceGenerator(name = "SEQ_LIB", initialValue = 1, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_LIB")

private Long id;

Página 17
private String nombre;

// Estas anotaciones hacen crear una tabla(auxiliar) en SQL con las dos id de cada
// entidad que tiene la relación N a N
@JoinTable(
name = "LIBROS_AUTORES",
joinColumns = @JoinColumn(name = "FK_LIBRO", nullable = false),
inverseJoinColumns = @JoinColumn(name="FK_AUTOR", nullable = false)
)
@ManyToMany(cascade=CascadeType.ALL ,fetch = FetchType.EAGER)

private Set<Autor> autores;

public void addAutor(Autor autor) {


if(this.autores == null){
this.autores = new HashSet<>();
}

this.autores.add(autor);
}

public Libro() {
super();
}

// Getters y Setters

public Long getId() {


return id;
}

public void setId(Long id) {


this.id = id;
}

public String getNombre() {


return nombre;
}

public void setNombre(String nombre) {


this.nombre = nombre;
}

Página 18
public Set<Autor> getAutores() {
return autores;
}

public void setAutores(Set<Autor> autores) {


this.autores = autores;
}

Entidad Autor

package com.entidades;

import java.io.Serializable;
import java.util.List;
import java.util.Set;

import javax.persistence.*;

@Entity
@Table(name="AUTORES")
public class Autor implements Serializable {

private static final long serialVersionUID = 1L;


@Id
@SequenceGenerator(name = "SEQ_AUT", initialValue = 1, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_AUT")

private Long id;

@Column
private String nombre;

// en esta relacion N a N lo que se mapea con mappedBy es el nombre de la


// lista en la entidad Libro

@ManyToMany( mappedBy="autores")
private Set <Libro> lib;

Página 19
public Autor() {
super();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public Set<Libro> getLib() {
return lib;
}
public void setLib(Set<Libro> lib) {
this.lib = lib;
}

Servicios Bean

LibroBeanRemote

package com.servicios;

import javax.ejb.Remote;

import com.entidades.Libro;

@Remote
public interface LibroBeanRemote {

public void crearLibro(Libro libro);

Página 20
LibroBean

package com.servicios;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import com.entidades.Libro;

@Stateless
public class LibroBean implements LibroBeanRemote {

@PersistenceContext
private EntityManager em;

public LibroBean() {
}

@Override
public void crearLibro(Libro libro) {

// Importante
// El uso de merge en lugar de persist
// Nos sirve para dar de alta los autores
// Ya que los que ya estan creados
// no los da de alta nuevamente

em.merge(libro);
em.flush();
}

AutoresBeanRemote

package com.servicios;

import javax.ejb.Remote;

import com.entidades.Autor;

@Remote

Página 21
public interface AutoresBeanRemote {

public void crearAutor(Autor autor);


public Autor ObtenerAutor(Long id);
public Autor ObtenerAutor(String nombre);

AutoresBean

package com.servicios;

import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import com.entidades.Autor;

/**
* Session Bean implementation class AutoresBean
*/
@Stateless
public class AutoresBean implements AutoresBeanRemote {

@PersistenceContext
private EntityManager em;

public AutoresBean() {

@Override
public void crearAutor(Autor autor) {
em.persist(autor);
em.flush();

@Override
public Autor ObtenerAutor(Long id) {
Autor autor=em.find(Autor.class, id);
return autor;
}

Página 22
@Override
public Autor ObtenerAutor(String nombre) {
TypedQuery<Autor> query ;
query = em.createQuery("SELECT a FROM Autor a WHERE a.nombre LIKE
:nombre", Autor.class).setParameter("nombre", nombre);

return query.getSingleResult();
}

Archivo ORM.xml

<?xml version="1.0" encoding="UTF-8"?>


<entity-mappings version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd">
<persistence-unit-metadata>
<persistence-unit-defaults>
<access>FIELD</access>
</persistence-unit-defaults>
</persistence-unit-metadata>
<entity class="com.entidades.Libro" access="FIELD">
<table name="LIBROS">
</table>
</entity>
<entity class="com.entidades.Autor" access="FIELD">
<table name="AUTORES">
</table>
</entity>
</entity-mappings>

Cliente que utiliza al servidor :

Cliente_MTM_1.java

package com.cliente;

import java.util.HashSet;

Página 23
import java.util.Set;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.entidades.Autor;
import com.entidades.Libro;
import com.servicios.AutoresBeanRemote;
import com.servicios.LibroBeanRemote;

public class Cliente_MTM_1 {


public static void main(String[] args)throws NamingException {

String ruta="MTM_EJB//LibroBean!com.servicios.LibroBeanRemote";
String ruta2="MTM_EJB//AutoresBean!com.servicios.AutoresBeanRemote";

LibroBeanRemote vari = (LibroBeanRemote) InitialContext.doLookup(ruta);


AutoresBeanRemote vari2 = (AutoresBeanRemote) InitialContext.doLookup(ruta2);

// Nuevos Autores
Autor autor1 = new Autor();
autor1.setNombre("Maria Barrios");

Autor autor2 = new Autor();


autor2.setNombre("Julio Blanco");

Autor autor3 = new Autor();


autor3.setNombre("Marcos Martinez");

Autor autor4 = new Autor();


autor4.setNombre("Ana Paladino");

Autor autor5 = new Autor();


autor5.setNombre("Karen Lopez");

// Nuevos Libros
Libro libro1 = new Libro();
libro1.setNombre("El hombre y las computadoras");
libro1.addAutor(autor1);
libro1.addAutor(autor4);

vari.crearLibro(libro1);

Página 24
System.out.println("Se creo el primer Libro");

// Como voy a poner en el siguiente libro un autor que ya di de alta


// hago el control antes buscando para ver si existe.
// si existe que cargado en la variable correspondiente, con el id
// Al hacer merge si ya tiene id, no lo da de alta.

autor4=vari2.ObtenerAutor("Ana Paladino");
System.out.println(autor4.getNombre()+" "+autor4.getId());

Libro libro2 = new Libro();


libro2.setNombre("Encontrando la solucion de Java EE");
libro2.addAutor(autor4);

vari.crearLibro(libro2);

System.out.println("Se creo el segundo Libro");

Libro libro3 = new Libro();


libro3.setNombre("El hombre que sabia usar el merge");
libro3.addAutor(autor5);
libro3.addAutor(autor3);

// Como autor1 ya lo di de alta en el libro1 lo busco antes para que le cargue


// la id, asi el merge no lo da de alta.

autor1=vari2.ObtenerAutor("Maria Barrios");
System.out.println(autor1.getNombre()+" "+autor1.getId());

libro3.addAutor(autor1);

vari.crearLibro(libro3);

System.out.println("Se creo el tercer Libro");

System.out.println("FIN DEL PROGRAMA");


}
}

Como quedaron las tablas en sql.


Autores, Libros y Libros_Autores

Página 25
Página 26
APLICACIONES
ENTERPRISE
Semestre 2

Licenciatura en Tecnologías de la Información

Tutor: Juan Antonaccio


ÍNDICE
INTRODUCCIÓN A APLICACIONES ENTERPRISE ......................................................................................................................... 4
APLICACIONES EMPRESARIALES .................................................................................................................................................................................4
MODELO JAVA EE ..........................................................................................................................................................................................................4
APLICACIONES DISTRIBUÍDAS......................................................................................................................................................................................5
SEGURIDAD .....................................................................................................................................................................................................................5
ARQUITECTURA ..............................................................................................................................................................................................................6
Componente Java EE ...........................................................................................................................................................................................6
LOS CLIENTES DE JAVA EE ...........................................................................................................................................................................................7
Clientes Web ...........................................................................................................................................................................................................7
Aplicación de escritorio .....................................................................................................................................................................................7
Applets ......................................................................................................................................................................................................................7
JAVABEANS .....................................................................................................................................................................................................................7
JAVA COMMUNICATIONS SERVER EE..........................................................................................................................................................................8
COMPONENTES WEB .....................................................................................................................................................................................................8
COMPONENTES DE NEGOCIO ........................................................................................................................................................................................9
JAVA EE CONTENEDORES .......................................................................................................................................................................................... 10
Servicios de Contenedor ................................................................................................................................................................................. 10
Tipos de contenedores ..................................................................................................................................................................................... 10
SERVIDORES JAVA EE................................................................................................................................................................................................. 11
SERVIDOR DE APLICACIONES JAVA EE..................................................................................................................................................................... 11
JAVA EE Y EMPAQUETADO DE APLICACIONES......................................................................................................................................................... 11
EMPAQUETADO ........................................................................................................................................................................................................... 12
ROLES DE DESARROLLO ............................................................................................................................................................................................. 13
Proveedor del producto Java EE.................................................................................................................................................................. 13
Proveedor de herramientas .......................................................................................................................................................................... 13
Proveedor de componentes de aplicación ............................................................................................................................................... 13
Bean Enterprise Developer ................................................................................................................................................................................................. 13
Web Component Developer ................................................................................................................................................................................................ 14
Desarrollador de aplicaciones de cliente...................................................................................................................................................................... 14
Ensamblador de aplicación ........................................................................................................................................................................... 14
Administrador de aplicación ........................................................................................................................................................................ 14
DOCUMENTACIÓN JAVA EE ORACLE (DOCUMENTO) ........................................................................................................................................... 14
ENTERPRISE JAVA BEANS .................................................................................................................................................................15
¿QUÉ ES UN ENTERPRISE JAVA BEAN? .................................................................................................................................................................... 15
Ventajas del uso de EJBs ................................................................................................................................................................................. 15
Cuándo conviene utilizar EJBs ..................................................................................................................................................................... 15
Tipos de EJBs ....................................................................................................................................................................................................... 15
BEAN DE SESIÓN ......................................................................................................................................................................................................... 16
Beans de sesión con estado............................................................................................................................................................................ 16
Beans de sesión sin estado ............................................................................................................................................................................. 16
Beans de sesión Singleton .............................................................................................................................................................................. 16
MESSAGE DRIVEN BEAN (MDB) ............................................................................................................................................................................. 16
ACCESO A BEANS DE SESIÓN ..................................................................................................................................................................................... 17
Usando EJBs en Clientes .................................................................................................................................................................................. 18
Sintaxis JNDI ............................................................................................................................................................................................................................... 18
La decisión sobre acceso remoto o local .................................................................................................................................................. 18
Los clientes locales ............................................................................................................................................................................................ 19
Accediendo EJBs locales utilizando la vista sin interfaz........................................................................................................................................ 20
Accediendo EJBs locales que implementan interfaces ........................................................................................................................................... 20
Los clientes remotos ......................................................................................................................................................................................... 20
EL CONTENIDO DE UN BEAN ENTERPRISE .............................................................................................................................................................. 21

Página 1 de 77
MÉTODOS ASÍNCRONOS ............................................................................................................................................................................................. 21
TIPOS DE EJBS .......................................................................................................................................................................................23
SIN ESTADO .................................................................................................................................................................................................................. 23
CON ESTADO ................................................................................................................................................................................................................ 24
SINGLETON................................................................................................................................................................................................................... 25
WILDFLY EN ECLIPSE .........................................................................................................................................................................26
CAMBIAR EL PUERTO DEL WILDFLY ........................................................................................................................................................................ 26
CÓMO INICIAR EL WILDFLY ...................................................................................................................................................................................... 27
CÓMO DETENER EL WILDFLY ................................................................................................................................................................................... 28
CÓMO HACER DEPLOY DE UN PROYECTO ................................................................................................................................................................. 29
COMO HACER UNDEPLOY DE UN PROYECTO ............................................................................................................................................................ 30
DEPLOY EN CALIENTE O HOT DEPLOY ...................................................................................................................................................................... 30
Como configurar el hot deploy..................................................................................................................................................................... 30
JAVA PERSISTENCE API .....................................................................................................................................................................32
¿QUÉ ES JPA? .............................................................................................................................................................................................................. 32
ENTIDADES .................................................................................................................................................................................................................. 32
Requisitos de una entidad .............................................................................................................................................................................. 32
Los campos persistentes y propiedades de la entidad ........................................................................................................................ 33
Campos persistentes .............................................................................................................................................................................................................. 34
Propiedades persistentes ..................................................................................................................................................................................................... 34
Tipos de acceso................................................................................................................................................................................................... 34
Lectura temprana y lectura demorada .................................................................................................................................................... 34
Tipos enumerados ............................................................................................................................................................................................. 35
Transient .............................................................................................................................................................................................................. 35
Colecciones........................................................................................................................................................................................................... 36
Tipos Embeddable............................................................................................................................................................................................. 36
Las claves.............................................................................................................................................................................................................. 37
Claves simples ........................................................................................................................................................................................................................... 37
@GeneratedValue(strategy = GenerationType.IDENTITY) ........................................................................................................................... 37
@GeneratedValue(strategy = GenerationType.SEQUENCE) ........................................................................................................................ 38
@GeneratedValue(strategy = GenerationType.AUTO) .................................................................................................................................... 38
@GeneratedValue(strategy = GenerationType.TABLE).................................................................................................................................. 38
Claves múltiples ........................................................................................................................................................................................................................ 39
LA MULTIPLICIDAD DE RELACIONES DE ENTIDADES.............................................................................................................................................. 39
Dirección en Relaciones de Entidades ....................................................................................................................................................... 39
Las relaciones Bidireccionales........................................................................................................................................................................................... 40
Las relaciones Unidireccionales........................................................................................................................................................................................ 40
Las Consultas y Dirección de Relación........................................................................................................................................................................... 40
Operaciones en cascada ................................................................................................................................................................................. 40
Algunos Ejemplos .............................................................................................................................................................................................. 41
@OneToOne ................................................................................................................................................................................................................................ 41
@OneToMany ............................................................................................................................................................................................................................ 42
@ManyToOne ............................................................................................................................................................................................................................ 42
@ManyToMany ......................................................................................................................................................................................................................... 42
HERENCIA .................................................................................................................................................................................................................... 43
SINGLE_TABLE ................................................................................................................................................................................................... 43
JOINED_TABLE ................................................................................................................................................................................................... 43
TABLE_PER_CONCRETE_CLASS .................................................................................................................................................................. 43
Ejemplo ................................................................................................................................................................................................................. 44
UNIDADES DE PERSISTENCIA .................................................................................................................................................................................... 46
MANEJO DE ENTIDADES ....................................................................................................................................................................47
ENTITY MANAGER ...................................................................................................................................................................................................... 47
La interfaz EntityManager ............................................................................................................................................................................ 47
Página 2 de 77
Entity Managers manejados por contenedor ......................................................................................................................................... 47
La gestión del ciclo de vida de una entidad ............................................................................................................................................ 47
Persistiendo una entidad ............................................................................................................................................................................... 49
Buscando una entidad..................................................................................................................................................................................... 50
Actualizando una entidad ............................................................................................................................................................................. 50
Eliminando una entidad ................................................................................................................................................................................. 51
Sincronización de datos de la entidad a la base de datos ................................................................................................................. 51
MÉTODOS CALLBACK ................................................................................................................................................................................................. 51
CLASES LISTENER ........................................................................................................................................................................................................ 52
JAVA PERSISTENCE QUERY LANGUAGE .......................................................................................................................................54
QUÉ ES .......................................................................................................................................................................................................................... 54
SINTAXIS ....................................................................................................................................................................................................................... 54
Parámetros .......................................................................................................................................................................................................... 55
Resumiendo ......................................................................................................................................................................................................... 56
ACTUALIZACIÓN DE DATOS Y BORRADO .................................................................................................................................................................. 56
Resumiendo ......................................................................................................................................................................................................... 57
EJECUTANDO SENTENCIAS JPQL .............................................................................................................................................................................. 57
QUERY VS QUERY TIPADA ........................................................................................................................................................................................ 58
CONSULTAS NATIVAS SQL ........................................................................................................................................................................................ 58
IMPLEMENTACIÓN DE HERENCIAS Y RELACIONES .................................................................................................................59
IMPLEMENTAR HERENCIA CON ESTRATEGIA SIMPLE ......................................................................................................................................... 59
Servidor ................................................................................................................................................................................................................. 59
Persona.java................................................................................................................................................................................................................................ 60
Alumno.java ................................................................................................................................................................................................................................ 60
PersonasBeanRemote.java .................................................................................................................................................................................................. 61
PersonasBean.java ................................................................................................................................................................................................................... 61
Archivos de configuración en el servidor ................................................................................................................................................. 62
persistence.xml ......................................................................................................................................................................................................................... 62
orm.xml ......................................................................................................................................................................................................................................... 62
Cliente .................................................................................................................................................................................................................... 63
IMPLEMENTAR HERENCIA TIPO JOINED ................................................................................................................................................................ 64
Servidor ................................................................................................................................................................................................................. 65
Persona.java................................................................................................................................................................................................................................ 65
Alumno.java ................................................................................................................................................................................................................................ 66
Profesor.java............................................................................................................................................................................................................................... 66
PersonasBeanRemote.java .................................................................................................................................................................................................. 67
PersonasBean.java ................................................................................................................................................................................................................... 67
Archivos de configuración en el servidor ................................................................................................................................................. 68
persistence.xml ......................................................................................................................................................................................................................... 68
orm.xml ......................................................................................................................................................................................................................................... 68
Cliente .................................................................................................................................................................................................................... 69
IMPLEMENTAR UNA CASO DE MANYTOMANY ....................................................................................................................................................... 70
Entidades .............................................................................................................................................................................................................. 70
Entidad Libro ............................................................................................................................................................................................................................. 70
Entidad Autor............................................................................................................................................................................................................................. 71
Servidor ................................................................................................................................................................................................................. 72
LibroBeanRemote .................................................................................................................................................................................................................... 72
LibroBean .................................................................................................................................................................................................................................... 73
AutoresBeanRemote............................................................................................................................................................................................................... 73
AutoresBean ............................................................................................................................................................................................................................... 73
Archivos de configuración en el servidor ................................................................................................................................................. 74
orm.xml ......................................................................................................................................................................................................................................... 74
Cliente .................................................................................................................................................................................................................... 75
Cliente_MTM_1.java ................................................................................................................................................................................................................ 75
Tablas en SQL ..................................................................................................................................................................................................... 76

Página 3 de 77
INTRODUCCIÓN A APLICACIONES ENTERPRISE

APLICACIONES EMPRESARIALES

En la actualidad cada vez más se necesita el desarrollo de aplicaciones empresariales.


¿Qué son las aplicaciones empresariales? Son sistemas que integran distintas partes del negocio, por
ejemplo, recursos humanos, contabilidad, manejo de recursos, etc.
Gracias a este tipo de aplicaciones, las empresas pueden aumentar su rendimiento a un bajo costo, teniendo
todo integrado en un mismo sistema.

MODELO JAVA EE

El modelo Java EE tiene como protagonistas el lenguaje de programación Java y la máquina virtual de Java.
Las características fundamentales de este tipo de aplicaciones son la productividad, portabilidad y
seguridad.
Java EE es un conjunto de especificaciones Java que brindan la funcionalidad necesaria para el desarrollo
de aplicaciones empresariales. Este tipo de aplicaciones pueden ser muy complejas, ya que pueden acceder
datos de una gran variedad de fuentes y que requieran que la aplicación sea distribuida a una gran cantidad
de clientes.
Java EE incluye muchos componentes de Java Standard Edition, llamada Java SE. JavaSE es un kit de
desarrollo de software que se utiliza para escribir applets y aplicaciones con el lenguaje de programación
Java. Este kit es el que han utilizado hasta el momento para las materiales Java que ya tuvieron. Java EE no
es un reemplazo de Java SE: Java SE proporciona el soporte de lenguaje básico sobre el que Java EE ejecuta.

El modelo Java EE define una arquitectura para la implementación de servicios como aplicaciones de varios
niveles que ofrecen a escalabilidad, accesibilidad y capacidad de gestión necesaria para aplicaciones
empresariales.
Si pensamos en una aplicación empresarial estándar, necesitaremos 3 capas:
• Capa de presentación: Encargada de desplegar y obtener información para el usuario.
• Capa de negocios: Encargada de los procesos y reglas de negocio.
• Capa de acceso a datos: Toda aplicación requiere alguna forma de persistencia (leer / almacenar
datos).
Página 4 de 77
Las aplicaciones Java EE se suelen distribuir en tres lugares diferentes:
• La máquina cliente.
• La máquina servidor (Servidor Java EE).
• Base de datos o sistemas legados (Sistema legado: se trata de un sistema informático que ha quedado
obsoleto pero continúa siendo utilizado por el usuario y no se quiere o no se puede reemplazar o
actualizar de forma sencilla).

Java EE divide el trabajo necesario para implementar esta arquitectura en las siguientes partes:
• La lógica de negocio y presentación, implementados por el desarrollador.
• Los servicios del sistema estándar, proporcionados por la plataforma Java EE.

Java EE promueve la construcción de sistemas independientes de la plataforma.


Posee una especificación es abierta, por lo que puede ser implementada por cualquier proveedor. Para esto,
el proveedor deberá de seguir el estándar, cumpliendo con los procesos de certificación existentes. Debe
cumplir lo que dice el estándar, pero eso no significa que sólo deba contemplar lo que el estándar establece.
Un servidor de aplicaciones que sea Java EE certificado, deberá proveer los servicios que define la
especificación. Con esto se logra que una aplicación que se ejecuta en un servidor de aplicaciones A, pueda
ejecutarse en un servidor de aplicación B.

APLICACIONES DISTRIBUÍDAS

Java EE usa un modelo de varios niveles donde se distribuyen las aplicaciones de la empresa.
En ésta un objeto está asociado con un nombre, donde los nombres los proporciona un servicio de nombres,
notificando a distintos componentes y resolviendo las referencias de clientes para estos componentes de
servicio.
La lógica de la aplicación se divide en componentes de acuerdo a su función, y los componentes de una
aplicación Java EE pueden estar instalados en distintas máquinas, dependiendo de la capa a la que
pertenece el componente de aplicación.
Las aplicaciones de multicapa Java EE son generalmente consideradas como aplicaciones de tres capas,
porque están distribuidas en tres lugares: máquina cliente, la máquina del servidor Java EE, y la base de
datos.

SEGURIDAD

Aunque otros modelos de aplicaciones empresariales requieren medidas de seguridad específicas para
cada aplicación, el entorno de seguridad de Java EE permite que las medidas de seguridad se definan
durante el despliegue (deploy) o momento de instalación de la aplicación.
Estas medidas protegen a los desarrolladores de aplicaciones de la complejidad de la implementación de
elementos de seguridad.
La plataforma Java EE proporciona reglas de control de acceso estándar declarativas que están definidas
por el desarrollador e interpretadas cuando se realiza el deploy o despliegue de la aplicación.

Página 5 de 77
ARQUITECTURA

Java EE define un estándar para el desarrollo de aplicaciones empresariales multicapa basadas en


componentes.
La lógica de la aplicación se divide en componentes de acuerdo a su función, y cada componente puede ser
instalado en una máquina diferente dependiendo de la capa a la que pertenezca Las aplicaciones se
dividen en capas dependiendo de su funcionalidad como pueden ser:
• Componentes de la capa de cliente corriendo en la máquina cliente.
• Componentes de la capa web corriendo en el servidor Java EE.
• Componentes de la capa de negocio corriendo en el servidor Java EE.
• Software de la capa EIS (Enterprise Information System) corriendo en un servidor EIS, con bases de
datos.

COMPONENTE JAVA EE
Un componente es una unidad de software “autosuficiente” y funcional que se ensambla dentro de una
aplicación Java EE y se comunica con otros componentes.
Para que un componente pueda ser ejecutado, debe de ser previamente desplegado (deploy) en el
contenedor correspondiente de un servidor Java EE.
La especificación Java EE define los siguientes componentes Java EE:
• Los clientes de aplicaciones y applets son componentes que se ejecutan en el cliente.
• Servlet Java, Java Server Faces, y Java Server Pages (JSP) son componentes web que se ejecutan en el
servidor.
• Enterprise JavaBeans (EJBs) son componentes de negocio que se ejecutan en el servidor.
Los componentes Java EE están escritos en Java y se compilan de la misma forma que cualquier otro
programa en el lenguaje. Las diferencias entre los componentes Java EE y las clases de Java "estándar" son
que los componentes Java EE se ensamblan en una aplicación Java EE, que se verifican de estar bien
formados y de acuerdo con la especificación Java EE, y que se implementan en la producción, en la que
están gestionados por el servidor Java EE.
Página 6 de 77
LOS CLIENTES DE JAVA EE

Un cliente Java EE es un cliente web, una aplicación de escritorio o un applet.

CLIENTES WEB
Un cliente web se compone de dos partes:
• Páginas web dinámicas que contienen varios tipos de lenguaje de marcado (HTML, XML, etc.), que son
generados por los componentes Web que se ejecutan en la capa web.
• Un navegador web, lo que hace que las páginas sean mostradas.

Un cliente web a veces se llama un cliente ligero. Los clientes ligeros no suelen consultar bases de datos,
ejecutar reglas de negocio complejas, ni conectarse con otras aplicaciones. Cuando se utiliza un cliente
ligero, las operaciones “pesadas” las realizan los bean enterprises que se ejecutan en el servidor Java EE,
en el que pueden aprovechar la seguridad, velocidad, servicios, y la fiabilidad de las tecnologías del lado del
servidor Java EE.

APLICACIÓN DE ESCRITORIO
Una aplicación de escritorio se ejecuta en una máquina cliente y brinda una forma más amigable para que
los usuarios manejen las tareas que requieren una interfaz de usuario más rica y más customizada que la
de un lenguaje de marcas (HTML).
Normalmente tiene una interfaz gráfica de usuario basada en Swing o AWT, pero también podría ser tan
simple como una interfaz de línea de comandos.
Las aplicaciones de escritorio acceden directamente a los beans enterprise que se ejecutan en la capa de
negocio.

APPLETS
Un applet es una pequeña aplicación cliente que se ejecuta en la máquina virtual Java embebida en el
navegador web. En las máquinas cliente necesitará el plugin de Java y, posiblemente un certificado de
seguridad para que el applet pueda ejecutarse con éxito en el navegador web.

JAVABEANS

Las capas servidor y cliente pueden incluir componentes JavaBeans para comunicar estas dos capas que
servirán de puente entre ambas.
Los componentes JavaBeans son clases Java que tienen propiedades y métodos get y set para acceder a las
mismas. Los componentes JavaBeans utilizados de esta manera suelen ser simples en su diseño e
implementación, pero deben ajustarse a las convenciones de nombres y de diseño descritos en la
arquitectura de componentes JavaBeans.
Los componentes JavaBeans no son considerados componentes Java EE por parte de la especificación Java
EE.

Página 7 de 77
JAVA COMMUNICATIONS SERVER EE

El cliente se comunica con la capa de negocio que se ejecuta en el servidor Java EE ya sea directamente o,
como en el caso de un cliente que se ejecuta en un navegador, pasando a través de páginas web o servlets
que se ejecutan en la capa web.

COMPONENTES WEB

Los componentes Web Java EE son servlets o páginas web creadas usando la tecnología JavaServer Faces
y/o la tecnología JSP (páginas JSP).
Los servlets son clases Java que procesan en forma dinámica peticiones y construyen respuestas.
Las páginas JSP son documentos basados en texto que se ejecutan como servlets pero permiten un enfoque
más natural para la creación de contenido estático.
JavaServer Faces se basa en servlets y JSP y proporciona un marco de componentes de interfaz de usuario
para las aplicaciones web.
Las páginas HTML estáticas y los applets se incluyen con los componentes web, pero no se consideran
componentes web según la especificación Java EE.
Las clases de utilidades del lado del servidor también pueden ser incluidas con los componentes web y, al
igual que las páginas HTML, no se consideran componentes web.

Página 8 de 77
COMPONENTES DE NEGOCIO

Es la lógica que resuelve las necesidades del negocio. Es manejado por los JavaBeans, ya sea en la capa de
negocio o de la capa web.

Un bean enterprise recibe datos de los programas clientes, los procesa (si es necesario), y los envía a la
capa del sistema de información empresarial para su almacenamiento.
Un bean enterprise también recupera datos desde el almacenamiento, los procesa (si es necesario), y los
envía de vuelta al programa cliente.
Hay tres tipos de beans enterprise: beans de sesión (con o sin estado), beans de entidad (manejados por el
bean o por el contenedor) y beans dirigidos a mensaje.
Un bean de sesión representa una conversación temporal con un cliente. Cuando el cliente finaliza su
ejecución, el bean de sesión y sus datos desaparecen.
Por el contrario, un bean de entidad representa datos persistentes almacenados en una fila de una
tabla/relación de una base de datos. Si el cliente se termina o si se apaga el servidor, los servicios
subyacentes se aseguran de grabar el bean.
Un bean dirigido-a-mensaje combina las características de un bean de sesión y de un oyente de Java
Message Service (JMS), permitiendo que un componente de negocio reciba asíncronamente mensajes JMS.

Página 9 de 77
JAVA EE CONTENEDORES

La arquitectura Java EE está basada en componentes y es independiente de la plataforma, lo que hace que
las aplicaciones Java EE sean más fáciles de escribir porque la lógica de negocio está organizada en
componentes que son reutilizables.
Además, el servidor Java EE proporciona servicios como un contenedor para cada tipo de componente.

SERVICIOS DE CONTENEDOR
Los contenedores son la interfaz entre un componente y la funcionalidad específica de la plataforma de
bajo nivel que soporta el componente.
Antes de que pueda ser ejecutado un ejb o un componente de aplicación cliente, deben ser empaquetados
en un módulo Java EE y desplegados en su contenedor.
El proceso de deploy implica especificar valores de contenedor para cada componente en la aplicación Java
EE y para la aplicación Java EE en sí.
Se pueden personalizar valores de servicios tales como la seguridad, la gestión de transacciones, Java
Naming and Directory Interface API de búsquedas (JNDI), y conectividad remota.
Como la arquitectura Java EE proporciona servicios configurables, los mismos componentes de una
aplicación Java EE pueden comportarse de forma diferente en función de donde se desplieguen. Por
ejemplo, un ejb puede tener la configuración de seguridad que permite un cierto nivel de acceso a los datos
de base de datos en un entorno de producción y otro nivel de acceso a la base de datos en otro entorno de
producción.

TIPOS DE CONTENEDORES
El proceso de despliegue instala los componentes de aplicaciones Java EE en los contenedores Java EE.

Página 10 de 77
• Servidor Java EE: Un servidor Java EE proporciona contenedores EJB y web.
• Enterprise JavaBeans (EJB): Gestiona la ejecución de los EJBs para las aplicaciones Java EE.
• Contenedor web: Gestiona la ejecución de páginas web, servlets, y algunos componentes EJB para
aplicaciones Java EE.
• Contenedor de cliente de aplicación: Gestiona la ejecución de los componentes de cliente de
aplicaciones. Los clientes de aplicación y su contenedor se ejecutan en el cliente.
• Contenedor de applets: Gestiona la ejecución de applets. Consta de un navegador web y Java Plugin
que se ejecuta en el cliente.

SERVIDORES JAVA EE

Los servidores Java EE representan el ambiente en el que ejecutan los componentes. Estos componentes se
denominan componentes serverside o componentes de aplicación JEE.
Puede tratarse de:
• Componentes web (JSP / Servlets / JSF).
• Componentes de negocio (EJB)

Estos componentes ejecutan en un contenedor.

SERVIDOR DE APLICACIONES JAVA EE

Un servidor de aplicaciones Java EE es una implementación de la especificación Java EE.


Java EE provee estándares que permiten a un servidor de aplicaciones servir como contenedor de los
componentes que conforman dichas aplicaciones. Debe servir como contenedor web y contenedor ejb.
Entre los servidores de aplicación Java EE más conocidos están WebLogic de Oracle, WebSphere de IBM,
ambos licenciados, y dentro de los libres se encuentran JOnAs, JBoss, Geronimo, Glassfish, etc.
Mucha gente confunde Tomcat como un servidor de aplicaciones; sin embargo, es solamente un contenedor
web.

JAVA EE Y EMPAQUETADO DE APLICACIONES

Una aplicación Java EE se empaqueta en una o más unidades. Cada unidad contiene:
• Un componente funcional como ejbs, página web, servlets, o un applet.
• Un descriptor de despliegue opcional que describe su contenido. Estos descriptores de despliegue
contienen información específica de cada componente empaquetado y son un mecanismo para
configurar el comportamiento de la aplicación en el momento del ensamble o del despliegue.

Una vez que se empaqueta la aplicación Java EE, está lista para ser desplegada.
Para el despliegue se utiliza la herramienta de despliegue de la plataforma para especificar la información
específica de la ubicación, la lista de los usuarios que pueden acceder a ella, el nombre de la base de datos,
entre otras cosas. Una vez desplegado en el servidor, la aplicación está lista para ser utilizada.

Página 11 de 77
EMPAQUETADO

Una aplicación Java EE se empaqueta en:


• Archivo Java Archive (JAR).
• Archivo Archivo Web (WAR).
• Archivo EAR (Enterprise Archive).

Una aplicación Java EE se empaqueta en un archivo enterprise (.ear) que contiene toda la aplicación junto
con el descriptor de despliegue que proporciona información sobre la aplicación y sus componentes.
Un descriptor de despliegue es un documento XML donde describe la configuración de despliegue de una
aplicación, un módulo o un componente. Como la información de descriptor de despliegue es declarativa
se puede cambiar sin la necesidad de modificar el código fuente.
Es en tiempo de ejecución que el servidor Java EE lee el descriptor de despliegue y actúa sobre la aplicación,
módulo o componente en consecuencia sin necesidad de recompilar el código fuente.

Existen 2 tipos de descriptores de despliegue:


• Descriptores de despliegue JEE (JEE Deployment Descriptor): Configuran las opciones de despliegue
de cualquier componente de Java Empresarial.
• Descriptores de despliegue del entorno de ejecución (Runtime Deployment Descriptor): Configuran
opciones del entorno de ejecución de nuestra aplicación empresarial, tales como las opciones de caché
en el servidor.

Un módulo Java EE consta de uno o más componentes de Java EE para el mismo tipo de contenedor y,
opcionalmente, descriptores de despliegue de ese tipo.
Un descriptor de despliegue del módulo Enterprise Bean, por ejemplo, declara atributos de transacción y
las autorizaciones de seguridad para un bean enterprise. Un módulo Java EE puede implementarse como
un módulo independiente.

Los módulos Java EE son de los siguientes tipos:


• Módulos EJB: Contiene los beans de empresa y, opcionalmente, un descriptor de despliegue EJB. Estos
módulos son empaquetados como archivos JAR con extensión .jar.
• Módulos web: Contienen las clases de los servlets, archivos web, archivos utilitarios, imágenes y
HTML, y, opcionalmente, un descriptor de despliegue de aplicaciones Web. Estos módulos son
empaquetados como archivos JAR con una extensión .war (archivo web).
• Módulos cliente: Contienen las clases y, opcionalmente, un descriptor de despliegue de aplicaciones
de cliente. Estos módulos se empaquetan como archivos JAR con una extensión .jar.
• Módulos adaptadores de recursos: Contienen todas las interfaces Java, clases, bibliotecas nativas, y,
opcionalmente, un descriptor de despliegue del adaptador de recursos. Estos módulos son
empaquetados como archivos JAR con una extensión .rar (archivo adaptador de recursos).

Página 12 de 77
ROLES DE DESARROLLO

El uso de módulos reutilizables hacen posible dividir el desarrollo de aplicaciones y el proceso de


implementación en distintos roles para que diferentes personas puedan realizar diferentes partes del
proceso.
Los dos primeros papeles, Java EE proveedor de productos y proveedor de herramientas, implican la
compra e instalación del producto y herramientas Java EE.
Después que el software es comprado e instalado, los componentes Java EE pueden ser desarrollados por
los proveedores de componentes de aplicaciones, ensamblados por los ensambladores de aplicaciones, y
desplegados por los implantadores de aplicaciones.
En una organización grande, cada una de estas funciones podrían ser ejecutados por diferentes individuos
o equipos. Esta división del trabajo funciona porque cada una de las funciones anteriores genera un archivo
portátil que es la entrada para una función subsiguiente. Por ejemplo, en la fase de desarrollo componente
de aplicación, un desarrollador de software bean enterprise proporciona archivos JAR EJB. En el papel
conjunto de aplicación, otro desarrollador puede combinar estos archivos JAR EJB en una aplicación Java
EE y guardarlo en un archivo EAR. En el papel de implantación de aplicaciones, un administrador de
sistemas en el sitio del cliente utiliza el archivo EAR para instalar la aplicación Java EE en el servidor.
Los diferentes roles no siempre son ejecutados por diferentes personas.

PROVEEDOR DEL PRODUCTO JAVA EE


El proveedor de productos de Java EE es la empresa que diseña y pone a disposición para su compra las
APIs de la plataforma Java EE y otras características definidas en la especificación Java EE. Son típicamente
los fabricantes de servidores de aplicaciones que implementan la plataforma Java EE de acuerdo con la
especificación Java EE.

PROVEEDOR DE HERRAMIENTAS
El proveedor de la herramienta es la empresa o persona que desarrolla, monta y crea herramientas para
los paquetes utilizados por los proveedores de componentes, ensambladores, y quienes los despliegan.

PROVEEDOR DE COMPONENTES DE APLICACIÓN


El proveedor de componentes de aplicación es la empresa o persona que crea componentes web, beans de
empresa, applets u clientes de aplicaciones para su uso en aplicaciones Java EE.

BEAN ENTERPRISE DEVELOPER


Se trata de un desarrollador de bean de empresa que realiza las siguientes tareas:
• Escribe y compila el código fuente.
• Especifica el descriptor de despliegue (opcional).
• Empaqueta los archivos .class y descriptor de despliegue en el archivo JAR EJB.

Página 13 de 77
WEB COMPONENT DEVELOPER
Se trata de un desarrollador de componentes web que realiza las siguientes tareas:
• Escribe y compila el código fuente del servlet.
• Escribe JavaServer Faces, JSP y archivos HTML.
• Especifica el descriptor de despliegue (opcional).
• Empaqueta el descriptor .class, .jsp y archivos .html en el archivo WAR.

DESARROLLADOR DE APLICACIONES DE CLIENTE


Se trata de un desarrollador de aplicaciones cliente que realiza las siguientes tareas:
• Escribe y compila el código fuente.
• Especifica el descriptor de despliegue para el cliente (opcional).
• Empaqueta los archivos .class y descriptor de despliegue en el archivo JAR.

ENSAMBLADOR DE APLICACIÓN
El ensamblador de la aplicación es la empresa o persona que recibe los módulos de aplicación de los
proveedores de componentes y los empaqueta en un archivo EAR.
Realiza las siguientes tareas:
• Se ensambla archivos JAR EJB y WAR creados en las fases anteriores en una aplicación Java EE archivo
(EAR).
• Especifica el descriptor de despliegue de la aplicación Java EE (opcional).
• Verifica que el contenido del archivo EAR están bien formadas y cumplen con la especificación Java EE.

ADMINISTRADOR DE APLICACIÓN
El programa de implementación de aplicaciones y administrador sea la empresa o persona que configura y
despliega los clientes de aplicaciones, aplicaciones web, componentes JavaBeans Enterprise y las
aplicaciones Java EE, administra la infraestructura computacional y de redes, donde los componentes y
aplicaciones Java EE corren, y supervisa el entorno de ejecución. Las responsabilidades incluyen controles
de transacción de ajuste y los atributos de seguridad y especificando las conexiones a bases de datos.
Durante la configuración, el programa de implementación sigue las instrucciones suministradas por el
proveedor del componente de aplicación para resolver las dependencias externas, especifique la
configuración de seguridad, y asignar atributos de transacción. Durante la instalación, el programa de
implementación mueve los componentes de la aplicación en el servidor y genera las clases e interfaces
específicos del contenedor.
Un administrador del programa de implementación o el sistema realiza las siguientes tareas para instalar
y configurar una aplicación o componentes Java EE:
• Configura la aplicación Java EE o componentes para el entorno operativo.
• Verifica que los contenidos de la oreja, JAR, y / o archivos WAR están bien formadas y cumplen con la
especificación Java EE.
• Despliega (instala) la aplicación Java EE o componentes en el servidor Java EE.

DOCUMENTACIÓN JAVA EE ORACLE (DOCUMENTO)


Página 14 de 77
ENTERPRISE JAVA BEANS

¿QUÉ ES UN ENTERPRISE JAVA BEAN?

Un enterprise java bean (EJB) es un componente del lado del servidor que encapsula la lógica de negocio
de una aplicación.
La lógica de negocio es el código que contiene las reglas de negocio y de proceso de una aplicación. En una
aplicación de stock de productos, por ejemplo, los EJBs pueden implementar su lógica de negocio en los
métodos “agregarProducto” o “chequearStockProducto”. Al invocar estos métodos, se puede acceder a los
servicios de stock de productos que proporciona la aplicación.

VENTAJAS DEL USO DE EJBS


Se podría decir que la mayor ventaja del uso de EJBs es simplificar el desarrollo de aplicaciones
distribuidas.
Esto es debido a que el contenedor EJB brinda servicios a nivel de sistema de modo que el desarrollador
puede concentrarse en resolver los problemas de negocio. El contenedor EJB es responsable de los servicios
como la gestión de transacciones y seguridad.
Además como los beans contienen la lógica de negocio de la aplicación, el desarrollador del cliente puede
centrarse en la presentación. El desarrollador no tendrá que programar las rutinas que implementan reglas
de negocio o bases de datos de acceso; de manera que los clientes serán más ligeros.
También como los enterprise beans son componentes portables, el ensamblador de aplicaciones podrá
crear nuevas aplicaciones con los beans existentes. Siempre que utilicen las API estándar, estas aplicaciones
se pueden ejecutar en cualquier servidor compatible con Java EE.

CUÁNDO CONVIENE UTILIZAR EJBS


• Cuando la aplicación debe escalar: Si la aplicación puede tener un número de usuarios en aumento,
es posible que necesite distribuir los componentes de la aplicación en varias máquinas. Los EJBs podrán
ser distribuidos en varias máquinas siendo esto transparente para la aplicación.
• Cuando se quiere garantizar la integridad de los datos: Los EJBs permiten el uso de transacciones
y los mecanismos que gestionan el acceso concurrente de objetos compartidos.
• Cuando la aplicación tiene clientes variados: Un EJB puede interactuar con una gran gama de
clientes.

TIPOS DE EJBS
• Bean de sesión: Representa un proceso o una acción de negocio. En general, cualquier llamada a un
servicio debería comenzar con una llamada a un bean de sesión. Conceptualmente se asocian los beans
de sesión con los verbos: agregarProducto, chequearStockProducto, etc.
• Beans dirigidos por mensajes (MDBs): Pueden escuchar mensajes de un servicio de mensajes JMS
(Java Message Service). Los clientes de estos beans nunca los llaman directamente, sino que es
necesario enviar un mensaje JMS para comunicarse con ellos. Un ejemplo de bean dirigido por mensajes
podría ser un bean ListenerNuevoProducto que se activa cada vez que se envía un mensaje
comunicando que se ha dado de alta a un nuevo producto.

Página 15 de 77
BEAN DE SESIÓN

Los beans de sesión representan sesiones interactivas con uno o más clientes. Los bean de sesión pueden
mantener un estado, pero sólo durante el tiempo que el cliente interactúa con el bean. Esto significa que
los beans de sesión no almacenan sus datos en una base de datos después de que el cliente termine el
proceso. Por ello se suele decir que los beans de sesión no son persistentes.
Existe una correspondencia uno a uno entre beans de sesión y clientes. Por esto, el contenedor EJB no
necesita implementar mecanismos de manejo de concurrencia en el acceso a estos beans.
Los beans de sesión pueden ser de tres tipos: con estado, sin estado, y singleton.

BEANS DE SESIÓN CON ESTADO


El estado de un objeto consiste en los valores de sus variables de instancia.
En un bean de sesión con estado, las variables de instancia representan el estado de una sesión de cliente
/ bean único. Debido a que el cliente interactúa ( "habla"), con su bean, este estado se llama a menudo
“estado de conversación”.
El estado se mantiene durante la duración de la sesión del cliente / bean.
Un ejemplo típico de bean de sesión con estado es un carrito de compra, en donde el cliente va guardando
uno a uno los ítem que va comprando.

BEANS DE SESIÓN SIN ESTADO


Un bean de sesión sin estado no mantiene un estado de conversación con el cliente. Cuando un cliente
invoca los métodos de un bean sin estado, las variables de instancia del bean pueden contener un estado
específico para ese cliente, pero sólo durante la duración de la invocación. Cuando se termina el
procedimiento, el estado específico del cliente no se mantiene.
Esta propiedad permite que el contenedor EJB pueda crear una reserva (pool) de instancias, todas del
mismo bean de sesión sin estado y asignar cualquier instancia a cualquier cliente. Incluso un único bean
puede estar asignado a múltiples clientes, ya que la asignación sólo dura el tiempo de invocación del
método solicitado por el cliente.
Como este tipo de beans pueden dar soporte a múltiples clientes, ofrecen una mejor escalabilidad para
aplicaciones que requieren un gran número de clientes. Por lo general, una aplicación requiere un menor
número de beans de sesión sin estado que beans de sesión con estado para atender el mismo número de
clientes.

BEANS DE SESIÓN SINGLETON


Un bean de sesión Singleton se instancia una vez por aplicación y existe para el ciclo de vida de la aplicación.
Este tipo de beans están diseñados para circunstancias en las que una sola instancia de un bean enterprise
se comparte por los clientes en forma concurrente durante toda la aplicación.
Son similares a los beans de sesión sin estado pero se diferencian de ellos en que sólo hay un único bean de
sesión por aplicación, en lugar de un conjunto de beans de sesión sin estado, cualquiera de los cuales
pueden responder a una petición de cliente.

MESSAGE DRIVEN BEAN (MDB)

Un MDB es un EJB que permite a las aplicaciones Java EE procesar mensajes de forma asíncrona. Este tipo
de bean en general actúa como un receptor de mensajes JMS, que es similar a un detector de eventos.
Página 16 de 77
Los mensajes se pueden enviar por cualquiera de los componentes de Java EE (un cliente de aplicación, un
EJB, o un componente web) o por una aplicación JMS o un sistema que no utiliza la tecnología Java EE. Los
MDBs pueden procesar mensajes JMS u otros tipos de mensajes.
En muchos aspectos, un MDB es parecido a un bean de sesión sin estado.
• Las instancias de un MDB no almacenan ningún estado conversacional ni datos de clientes.
• Todas las instancias de los MDBs son equivalentes, lo que permite al contenedor EJB asignar un mensaje
a cualquier instancia. El contenedor puede almacenar estas instancias para permitir que los streams de
mensajes sean procesados de forma concurrente.
• Un único MDB puede procesar mensajes de múltiples clientes.
Las variables de instancia de estos beans pueden contener algún estado referido al manejo de los mensajes
de los clientes. Pueden contener una conexión JMS, una conexión de base de datos o una referencia a un
EJB.
Cuando llega un mensaje, el contenedor EJB llama al método “onMessage” del bean. El método onMessage
suele realizar un casteo del mensaje a uno de los cinco tipos de mensajes de JMS y manejarlo de forma
acorde con la lógica de negocio de la aplicación.
Un mensaje puede enviarse a un MDB dentro de un contexto de transacción, por lo que todas las
operaciones dentro del método onMessage son parten de un única transacción.

ACCESO A BEANS DE SESIÓN

Los clientes van a acceder a los EJBs de dos maneras posibles: a través de una vista sin interfaz o a través
de una interfaz de negocio (local o remota).
Todos los métodos públicos del bean (incluyendo aquellos definidos en superclases) están disponibles en
la vista sin interfaz.
Los clientes que utilizan la vista sin interfaz de un EJB pueden invocar cualquier método público de la clase
de implementación del EJB o cualquier superclase de la implementación.
Una interfaz de negocio es una interfaz estándar de lenguaje de programación Java que contiene los
métodos de negocio del EJB.
Un cliente puede acceder a un bean de sesión sólo a través de los métodos definidos en la interfaz de
negocio del bean o por medio de los métodos públicos de un EJB con una vista sin interfaz.
Es importante tener un modelo de interfaces bien diseñado ya que esto simplifica el desarrollo y
mantenimiento de la aplicación Java EE.
No sólo las interfaces limpias y las vistas sin interfaz protegen a los clientes de cualquier complejidad en el
nivel de EJB, sino que también permiten a los EJBs cambiar internamente sin afectar a los clientes. Por
ejemplo, si cambia la implementación de un método de negocio de bean de sesión, no se tendrá que
modificar el código del cliente. Pero si tuviera que cambiar las definiciones de métodos de las interfaces, es
posible que tenga que modificar el código del cliente también. Por lo tanto, es importante que el diseño de
las interfaces y los accesos de vista sin interfaz estén pensados cuidadosamente para evitar que los clientes
deban realizar cambios al acceder a los EJBs.
Los beans de sesión pueden tener más de una interfaz de negocio. Los beans de sesión deben, pero no están
obligados a, implementar una interfaz o interfaces de negocio.
Si el bean no expone ninguna interfaz remota o local, entonces el contenedor tiene que dejar disponible una
vista sin interfaz. En cambio, si el bean expone al menos una interfaz remota o una local, entonces el
contenedor no provee una vista sin interfaz (a menos que se pida explícitamente usando la anotación
LocalBean.
Página 17 de 77
USANDO EJBS EN CLIENTES
El cliente de un EJB obtiene una referencia a una instancia de un bean enterprise, ya sea a través de la
inyección de dependencia, mediante anotaciones de lenguaje de programación Java, o búsqueda JNDI,
utilizando la sintaxis de Java Naming and Directory Interface para encontrar la instancia del EJB.
La inyección de dependencia es la forma más sencilla de obtener una referencia a un EJB. La inyección de
dependencia es una técnica popular en el desarrollo de aplicaciones empresariales java, en donde un
componente especifica los recursos de los que depende.
Un inyector, típicamente un contenedor, proporciona los recursos al componente. Aunque la inyección de
dependencia puede ser implementado de varias maneras, en general se realiza con anotaciones.
Los clientes que ejecutan en un entorno gestionado por el servidor Java EE, JavaServer Faces aplicaciones
web, servicios web JAXRS, otros EJBs, o clientes de aplicaciones Java EE soportan la inyección de
dependencias utilizando anotaciones java.
Una anotación java una es una forma de añadir metadatos al código fuente Java que están disponibles para
la aplicación en tiempo de ejecución.
Las aplicaciones que se ejecutan fuera de un entorno gestionado por el servidor Java EE, tales como
aplicaciones Java SE, deben realizar una búsqueda explícita. JNDI soporta una sintaxis global para la
identificación de los componentes de Java EE para simplificar las operaciones de búsqueda este explícita.

SINTAXIS JNDI
Existen tres espacios de nombres JNDI que se utilizan para las búsquedas: java:global , java:module , y
java:app .
• java:global es la manera portable de encontrar EJBs remotos mediante búsquedas JNDI. Las direcciones
JNDI son de la siguiente forma:
java:global[/application name]/module name/enterprise bean name[/interface name]

• java:module se utiliza para buscar EJBs locales dentro del mismo módulo. Las direcciones JNDI son de
la siguiente forma:
java:module/enterprise bean name/[interface name]

• La java:app se utiliza para buscar EJBs locales envasados dentro de la misma aplicación. Es decir, el EJB
se empaqueta en un archivo EAR que contiene múltiples módulos Java EE. Las direcciones JNDI son de
la siguiente forma:
java:app[/module name]/enterprise bean name[/interface name]

Por ejemplo: supongamos que tengo un EJB llamado MiPrimerEJB, que se empaqueta dentro del archivo
web miPrimerApp.war y el nombre del módulo es miPrimerApp. El nombre JNDI portable es
java:module/MiPrimerEJB. Un nombre JNDI equivalente utilizando el java:global es
java:global/miPrimerApp/MiPrimerEJB.

LA DECISIÓN SOBRE ACCESO REMOTO O LOCAL


Cuando se diseña una aplicación Java EE, una de las primeras decisiones que hay que tomar es el tipo de
acceso que le voy a permitir al cliente para acceder a los EJBs: remoto, local o usando web services.

Página 18 de 77
Ya sea para permitir el acceso local o remoto depende de los siguientes factores.
• Alto acoplamiento: Por ejemplo, si un bean de sesión que procesa los pedidos de cliente llama a otro
bean de sesión que envía correo electrónico con la confirmación al cliente, estos EJBs están
estrechamente unidos. Estos son buenos candidatos para el acceso local. Encajan entre sí como una
unidad lógica, que normalmente se llaman entre sí a menudo y se beneficiarían del aumento de
rendimiento que es posible con el acceso local.
• Tipo de cliente: Si un EJB se accede por clientes de la aplicación, se debe permitir el acceso remoto. En
un entorno de producción, estos clientes casi siempre se ejecutan en máquinas distintas de aquellas en
las que se ejecuta el servidor JavaEE. Si los clientes que acceden al EJB son componentes web u otros
EJBs, el tipo de acceso depende de cómo desea distribuir sus componentes: si van en el mismo servidor
o en otros.
• La distribución de componentes: Las aplicaciones Java EE son escalables porque sus componentes
pueden ser distribuidos a través de múltiples máquinas. En una aplicación distribuida, por ejemplo, el
servidor en el que los componentes web corren puede no ser el mismo en el que los EJBs están
desplegados. En este escenario distribuido, los EJBs deben permitir el acceso remoto.
• Rendimiento: Debido a factores tales como la latencia de la red, las llamadas remotas puede ser más
lentas que las llamadas locales. Por otro lado, si distribuye componentes entre los diferentes servidores,
es posible mejorar el rendimiento general de la aplicación.

Si no se está seguro de qué tipo de acceso debe tener un EJB, debería elegir el acceso remoto ya que da más
flexibilidad. Esto permitirá distribuir sus componentes para escalar la aplicación.
También es posible que un EJB permita el acceso remoto y local. Si este es el caso, se necesitará una interfaz
remota y otra local. La misma interfaz de negocio no puede ser a la vez una interfaz local y remota.

LOS CLIENTES LOCALES


Un cliente local:
• Debe correr en la misma aplicación a la que accede el EJB.
• Puede ser un componente Web u otro EJB.

La vista sin interfaz de un EJB es una vista local. Los métodos públicos de la clase de implementación de un
EJB están expuestos a los clientes locales que acceden a la vista sin interfaz del EJB. Los EJBs que utilizan la
vista sin interfaz no implementan una interfaz de negocio.
La interfaz de negocio local define los métodos y el ciclo de vida del bean.
Si interfaz de negocio del bean no está anotada con @Local o @Remote , y si la clase de bean no especifica
la interfaz mediante @Local o @Remote, la interfaz de negocio es por defecto una interfaz local.
Para construir un EJB que permite sólo el acceso local, se puede seguir uno de los siguientes pasos:
• Crear una clase de implementación de EJB que no implementa una interfaz de negocio, lo que significa
que el bean expone una vista sin interfaz a los clientes. Por ejemplo:
@LocalBean
public class myBean {...}

• Anotar la interfaz de negocio como @Local. Por ejemplo:


@Local
public interface InterfaceName { ... }

Página 19 de 77
• Especificar la interfaz mediante la anotación @Local y el nombre de la interfaz. Por ejemplo:
@Local(InterfaceName.class)
public class BeanName implements InterfaceName { ... }

ACCEDIENDO EJBS LOCALES UTILIZANDO LA VISTA SIN INTERFAZ


Para acceder a un EJB con estas características se puede utilizar: inyección de dependencia o de búsqueda
JNDI.
• Para obtener una referencia a la vista sin interfaz de un EJB utilizando la inyección de dependencias:
@EJB
MiPrimerBean miPrimerBean;

Siendo MiPrimerBean el nombre de la clase del EJB.


• Para obtener una referencia a la vista sin interfaz de un EJB utilizando la búsqueda JNDI:
MiPrimerBean miPrimerBean = (MiPrimerBean)
InitialContext.lookup ("java:module/MiPrimerBean");

Los clientes no utilizan el operador new para obtener una nueva instancia de un EJB que utiliza una vista
sin interfaz

ACCEDIENDO EJBS LOCALES QUE IMPLEMENTAN INTERFACES


El acceso se lleva a cabo a través de inyección de dependencia o de búsqueda JNDI.
• Para obtener una referencia a la interfaz de negocio local de un EJB utilizando la inyección de
dependencias, se debe utilizar la anotación javax.ejb.EJB y especificar el nombre de interfaz de negocio
local:
@EJB
Ejemplo ejemplo;

• Para obtener una referencia a una interfaz de negocio local de un EJB utilizando la búsqueda JNDI, se
debe utilizar el método lookup de javax.naming.InitialContext:
EjemploLocal ejemploLocal = (EjemploLocal)
InitialContext.lookup ("java:module/EjemploLocal");

LOS CLIENTES REMOTOS


Un cliente remoto de un EJB tiene las siguientes características.
• Se puede ejecutar en una máquina diferente y una JVM diferente de la que está el EJB. (No es necesario
para ejecutar en una JVM diferente).
• Puede ser un componente web, un cliente de aplicación, u otro EJB.
• Para un cliente remoto, la ubicación del EJB es transparente.
• El EJB debe implementar una interfaz de negocio. Es decir, los clientes remotos no pueden acceder a un
EJB a través de una vista sin interfaz.

Página 20 de 77
Para crear un EJB que permita el acceso remoto, o bien debe:
• Anotar la interfaz de negocio del EJB con @Remote:
@Remote
public interface InterfaceName { ... }

• O anotar con @Remote la clase del EJB y especificando la interfaz o interfaces de negocio:
@Remote(InterfaceName.class)
public class BeanName implements InterfaceName { ... }

La interfaz remota define los métodos de negocio y el ciclo de vida que son específicos para el EJB. Por
ejemplo, la interfaz remota de un bean llamado StockProductosBean podría tener los métodos de negocio
agregarProducto y quitarProducto.
El acceso de un cliente a un EJB que implementa una interfaz de negocio remota se lleva a cabo a través de
inyección de dependencia o de búsqueda JNDI.
• Para obtener una referencia a la interfaz de negocio remota de un EJB a través de la inyección de
dependencias, se debe utilizar la anotación javax.ejb.EJB y especificar el nombre de interfaz de negocio
remota:
@EJB
Ejemplo ejemplo;

• Para obtener una referencia a una interfaz de negocios remota de un EJB a través de la búsqueda JNDI,
se debe utilizar el método lookup del javax.naming.InitialContext:
ExampleRemote example = (ExampleRemote)
InitialContext.lookup("java:global/myApp/ExampleRemote");

EL CONTENIDO DE UN BEAN ENTERPRISE

Para desarrollar un EJB se deben generar los siguientes archivos:


• Clase EJB: Implementa los métodos de negocio del EJB.
• Interfaces: Define los métodos de negocio implementados por la clase EJB. No se requiere una interfaz
de negocio si el EJB expone una vista local sin interfaz.
• Clases de ayuda: Otras clases que necesita la clase EJB, tales como excepciones y servicios públicos.

Los archivos anteriores se empaquetan ya sea en un archivo JAR EJB (un módulo independiente que se
almacena el EJB) o dentro de un módulo de archivo de la aplicación Web (WAR).

MÉTODOS ASÍNCRONOS

Los EJBs pueden implementar métodos asincrónicos: son métodos donde se devuelve el control al cliente
a través del contenedor antes de invocar el método en la instancia de bean de sesión. El resultado del
método se devuelve al contenedor y no al cliente, por lo que el cliente no percibe demoras y puede seguir
trabajando.
Este tipo de métodos se utilizan normalmente para operaciones de larga duración, para las tareas de uso
intensivo del procesador, para tareas en segundo plano, para aumentar el rendimiento de aplicaciones, o
para mejorar el tiempo de respuesta de la aplicación.

Página 21 de 77
Ejemplo:
@Asynchronous
public void enviarMail(String texto) {
...
}

Página 22 de 77
TIPOS DE EJBS
Un EJB suele estar compuesto por una clase de implementación y cero o más interfaces de negocio. La clase
de implementación contiene las implementaciones de los métodos de negocio. Debe estar anotada con:
@Stateless, @Stateful o @Singleton
Las interfaces de negocio contienen las declaraciones de los métodos de negocio visibles al cliente y son
implementadas por el bean.

SIN ESTADO

Un EJB Stateless es una clase java sin estado, es decir, no debería tener atributos, sólo métodos a los que se
pueda llamar de forma independiente. Este tipo de EJB no mantienen estado conversacional ni presentan
problemas de concurrencia.
Para que el contenedor de aplicaciones lo maneje, sólo hay que ponerle la anotación @Stateless
import javax.ejb.LocalBean;
import javax.ejb.Stateless;

@Stateless
@LocalBean
public class SinEstadoBean {

public void holaMundo(String texto){


System.out.println(“Hola mundo: ”+texto);
}

Es una clase con un método al que se le pasa un texto y muestra en consola “Hola mundo” seguido del texto
pasado.
La anotación @Stateless es la que lo convierte en un EJB y le indica al contenedor de aplicaciones que debe
encargarse de manejarlo.
La anotación @LocalBean indica que a esta clase no se va a acceder de forma remota (desde fuera de
nuestra aplicación). Esta anotación es opcional, ya que por defecto se asume que el bean no va a ser
accedido de forma remota.
Para los EJB sin estado, el contenedor de aplicaciones va a crear varias instancias de estas clase y le pasará
estas instancias a quien las necesite. Como son clases sin estado, el contenedor dará cualquiera de las
instancias que tiene al que la necesite y no se preocupará de entregar siempre la misma al mismo cliente.

Página 23 de 77
CON ESTADO

Un EJB con estado es una clase en la que sí hay atributos y cuyo valor es importante y debe conservarse
entre llamadas a métodos.
El contenedor de aplicaciones instanciará, al igual que con los EJB sin estado, un número determinado de
ellos, asegurandose de dar siempre al mismo cliente/usuario la misma instancia. De esta manera, el cliente
puede guardar en él datos que sean propios de él y que necesiten conservarse mientras está trabajando con
la aplicación.
Un ejemplo típico es el carrito de la compra de una web. Los productos que el usuario va añadiendo al
carrito se guardarían en un EJB con estado.
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Remove;
import javax.ejb.Stateful;

@Stateful
@LocalBean
public class ConEstadoBean {

@EJB
SinEstadoBean sinEstadoBean;

// Estado
private String estado;

public void setEstado(String estado){


this.estado = estado;
}

@Remove
public void mostrarEstado(){
sinEstadoBean.holaMundo(estado);
}

Esta clase utiliza la anotación @Stateful para indicar que es un EJB con estado. La anotación @LocalBean,
al igual que antes, es opcional e indica que este bean no se va a utilizar de forma remota.
Esta clase tiene un atributo de tipo String llamado estado y un método setEstado que le da un valor. Como
se trata de un EJB con estado, este estado se conservará para la llamada a mostrarEstado().
La anotación @Remove en el método mostrarEstado() se usa para indicar al contenedor que ya hemos
terminado de usar este EJB con estado. Cuando encuentra esta llamada el contenedor sabe que puede darle
este EJB a otro que lo necesite pues ya fue usado.
Tenemos también el atributo @EJB SinEstadoBean sinEstadoBean que utilizaremos para realizar la
llamada a nuestro holaMundo de modo de mostrar en consola el estado. Como SinEstadoBean es un EJB
controlado por el contenedor de aplicaciones, no hacemos nosotros el new de esta clase, la anotamos con
@EJB y es el contenedor quien se encargará de pasarnos una de las instancias que tiene de SinEstadoBean
y podremos usarla.

Página 24 de 77
SINGLETON

Un EJB Singleton es una clase Java que el contenedor de aplicaciones instanciará una única vez y será
compartida en la aplicación por los clientes. Está pensada para guardar los datos que son comunes a todos
los usuarios o clientes de nuestra aplicación.
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;

@Singleton
@Startup
public class SingletonBean {

@PostConstruct
public void init() {
System.out.println("SingletonBean arranca");
}

@PreDestroy
public void destroy() {
System.out.println("SingletonBean termina");
}

La anotación @Singleton convierte a esta clase Java en un Singleton.


La anotación @Startup nos sirve para indicarle al contenedor de aplicaciones que debe arrancar este EJB
al inicio. Si no ponemos la anotación, el bean no arranca hasta que alguien lo necesite.
En general la anotación @Startup no se utiliza, salvo que este bean realice algo que necesite ser hecho en
el momento de arrancar el contenedor de aplicaciones/nuestra aplicación.
Cuando este EJB arranque se ejecutará lo que esté dentro del método con @PostConstruct. Si no hay ningún
método con esta anotación, no se hará nada en el arranque, pero si hay algún método anotado de esta
manera, se ejecutará después de cargar el bean, pero antes de que empiece a usarse. Es un método de
inicialización de la clase.
Si queremos realizar alguna acción cuando el bean se vaya a destruir (al finalizar nuestra aplicación),
debemos anotar el método que queramos que se ejecute con @PreDestroy.

Página 25 de 77
WILDFLY EN ECLIPSE

CAMBIAR EL PUERTO DEL WILDFLY

Por default cuando instalamos el WildFly, el mismo correr en el puerto 8080. Hay veces que tenemos otras
aplicaciones corriendo en ese puerto, por lo que debemos cambiarlo.
Existen varias formas de hacerlo. Veamos como hacerlo desde el Eclipse.
En la solapa Servers, ir dentro del WildFly a “XML Configuration” Ports y allí JBoss Web.

Botón derecho sobre JBoss Web y click en Change Value. Ahí modificamos el número de puerto por el
deseado y enter.
Ahora ya podrán iniciar el WildFly donde verán que se levanta en este nuevo puerto.

Página 26 de 77
CÓMO INICIAR EL WILDFLY

En la solapa Servers WildFly, botón derecho Start.

Una vez iniciado aparece WildFly 10.0 [Started, Synchronized].


Si miramos la consola, (solapa Console) veremos en el log algo del estilo:

Esa última línea indica que se inició el WildFly en forma correcta.


Otra forma de verificarlo es abriendo un navegador web y escribiendo la url: http://localhost:8080 con el
puerto configurado.

Página 27 de 77
CÓMO DETENER EL WILDFLY

En la solapa Servers en el WildFly, botón derecho Stop.

Una vez detenido aparece WildFly 10.0 [Stopped, Synchronized]

Página 28 de 77
CÓMO HACER DEPLOY DE UN PROYECTO

Hay varias formas de hacerlo. Puede ser con botón derecho sobre el proyecto Run us Run on server.
O dentro de la solapa Servers WildFly Add and Remove.

Cuando se realiza un deploy verificar que el proyecto quede en estado [Started, Synchronized].

Página 29 de 77
COMO HACER UNDEPLOY DE UN PROYECTO

Hay varias maneras de hacerlo también.


En la solapa servers, click botón derecho sobre el proyecto y hacer Remove.
Otra opción, es botón derecho sobre WildFly click en Add and Remove.
Cuando se realiza un undeploy verificar que el proyecto quede en estado [Stopped, Synchronized].

DEPLOY EN CALIENTE O HOT DEPLOY

Cuando se realiza un deploy de un proyecto que tiene EJBs, en la consola deberíamos ver algo así:

Para verificar que el proyecto que contiene EJBs haya quedado bien en el WildFly, aparte de verificar que
el estado del proyecto sea Started, revisar en la consola que aparezcan las rutas JNDI del / de los ejbs en
cuestión. De esta manera sabremos que los EJBs quedaron deployados de forma correcta.

COMO CONFIGURAR EL HOT DEPLOY


El hot swap significa que una vez que modifico algo del proyecto, en vez de yo tener que hacer manualmente
un undeploy y luego un deploy de la aplicación, se hará en forma automática. Esto facilita mucho el
desarrollo de las aplicaciones. Hay que tener cuidado en que NO SIEMPRE se puede hacer un deploy en
caliente. Si por ejemplo cambio la firma de un método EJB o agrego o quito EJBs o entidades, tendré que
hacerle manualmente el undeploy y el deploy. Si en cambio modifico el cuerpo de un método, el hot deploy
será muy util, pues al grabar el archivo y compilarse se hará una republicación del proyecto.
Para configurar esto, vamos a la solapa Servers y hacemos doble click sobre WildFly. En la segunda
columna, bajo el título Application Reload Behaviour tienen una opción que dice Customize application
reload…. Desmarcar la opción default y escribir: \.jar$|\.class$ tal como muestra la siguiente figura:

Página 30 de 77
Página 31 de 77
JAVA PERSISTENCE API

¿QUÉ ES JPA?

Java Persistence API (JPA) nos brinda un estándar para poder gestionar datos relacionales en aplicaciones
java, de tal forma que además simplifica el desarrollo de la persistencia de datos.
JPA establece una interface común que es implementada por un proveedor de persistencia, tales como
Hibernate, EclipseLink u otro. Podemos elegir en cualquier momento el proveedor que más se adecue a
nuestras necesidades. Así, es el proveedor quién realiza el trabajo, pero siempre funcionando bajo la API
de JPA.
Para los ejemplos del curso utilizaremos Hibernate, pero si lo prefieren pueden utilizar otro en cualquier
momento.
Hibernate es un framework open source de mapeo y persistencia para ser utilizado en Java. Sus librerías
ya vienen con el servidor de aplicaciones WildFly por lo que no tendremos que agregar librerías
adicionales.
Para entender JPA, tendremos que tener claro el concepto de persistencia. La persistencia o el
almacenamiento permanente, es una de las necesidades básicas de cualquier sistema de información de
cualquier tipo. Persistir objetos Java en una base de datos relacional implica serializar un árbol de objetos
Java en una base de datos de estructura tabular y viceversa. Es vital poder mapear objetos Java para
optimizar velocidad y eficiencia de la base de datos.

ENTIDADES

Una entidad es un objeto de dominio persistencia liviano. Por lo general, una entidad representa una tabla
en una base de datos relacional, y cada instancia de la entidad corresponde a una fila de esa tabla.
Una entidad tiene campos o propiedades que son persistentes.

REQUISITOS DE UNA ENTIDAD


Una entidad debe cumplir los siguientes requisitos:
• La clase debe tener la javax.persistence.Entity anotación: @Entity
• La clase debe tener un constructor sin parámetros public o protected. La clase puede tener además
otros constructores.
• La clase no debe ser declarada final. No hay métodos o variables de instancia persistentes que sean
declarados final.
• Si una instancia de una entidad se pasa por valor como un objeto a través de la interfaz de negocio
remota de un EJB, la clase debe implementar la interfaz Serializable.
• Las entidades pueden extender clases de cualquier tipo (entidades u otras), y las clases que no son
entidades pueden extender de clases de entidad.
• Las variables de instancia pueden ser accedidas sólo por los métodos de la clase entidad, en general a
través de métodos get o set.

Página 32 de 77
Ejemplo de entidad
@Entity
@Table(name = "PERSONA")

public class Persona {

@Id
@GeneratedValue
private Long id;

@Column(nullable=false)
private String nombre;

@Column(nullable=true)
private Date fechaNacimiento;

@Transient
private int edad;

// Getters y Setters
}

La anotación @Table nos permite configurar el nombre de la tabla donde queremos almacenar la entidad
mediante el atributo name.

LOS CAMPOS PERSISTENTES Y PROPIEDADES DE LA ENTIDAD


A través de la anotación @Column podemos configurar el nombre de la columna donde se almacenará una
propiedad, si dicha propiedad puede contener un valor null, etc.
Los tipos de datos válidos como propiedades son:
• Tipos primitivos.
• java.lang.Byte
• java.lang.Short
• java.lang.Integer
• java.lang.Long
• java.math.BigInteger
• java.lang.Float
• java.lang.Double
• java.math.BigDecimal
• java.lang.Boolean
• java.lang.Character
• java.lang.String
• java.util.Date
• java.util.Calendar
• java.sql.Date
• java.sql.Time
• java.sql.Timestamp

Para definir un atributo de una entidad (Entity) que no se desee persistir, debe emplearse la anotación
@Transient. La anotación @Lob especifica que la propiedad debe ser persistida en un Blob o Clob.

Página 33 de 77
Las entidades pueden utilizar campos persistentes, propiedades persistentes, o una combinación de ambos.
Si las anotaciones de mapeo se aplican a las variables de instancia de la entidad, la entidad utiliza campos
persistentes. Si las anotaciones de mapeo se aplican a los métodos getter de la entidad, la entidad utiliza las
propiedades persistentes.

CAMPOS PERSISTENTES
Si la clase de entidad utiliza campos persistentes, el acceso se realiza en tiempo de ejecución.
Todos los campos que NO sean anotados con javax.persistence.Transient o no marcados como
@Transient se guardarán en el almacén de datos.

En el ejemplo de la entidad Persona, los campos persistentes son el id, nombre y fechaNacimiento. El campo
edad no se almacenará en la base de datos ya que está anotado como transient. Este campo puede ser
calculado a partir de la fecha de nacimiento, es por eso que no necesita ser almacenado en la base de datos.

PROPIEDADES PERSISTENTES
Si la entidad utiliza las propiedades persistentes, la entidad debe seguir las convenciones JavaBeans: esto
implica el uso de métodos get y set.
En el ejemplo de la entidad Persona, si utiliza las propiedades persistentes y tiene una variable de instancia
privada denominada nombre, la clase define un getNombre y setNombre.

TIPOS DE ACCESO
JPA permite definir dos tipos de acceso:
• Acceso a variable.
• Acceso a propiedad.

El tipo de acceso que usará una entidad está definido por el lugar donde situemos sus anotaciones de
mapeo. Si las anotaciones están en las variables estaremos indicando a JPA que debe realizar acceso a
variable. Si, por el contrario situamos las anotaciones de mapeo en los métodos getter, estaremos
indicando un acceso a propiedad. A efectos prácticos, no existe diferencia alguna entre ambas opciones.

LECTURA TEMPRANA Y LECTURA DEMORADA


Cuando leemos una entidad desde la base de datos, ciertas propiedades pueden no ser necesarias en el
momento de la creación del objeto.
JPA nos permite leer una propiedad desde la base de datos recién cuando el cliente necesita leer su valor
(lectura demorada), en lugar de leerla cuando la entidad que la contiene se crea (lectura temprana).
Es entonces que si la propiedad nunca es accedida, nos evitamos el costo de crearla. Esto puede ser útil si
la propiedad contiene un objeto de gran tamaño:
@Basic(fetch = FetchType.LAZY)
private Archivo adjunto;

La propiedad adjunto es un objeto que representa un archivo adjunto (un objeto que puede ser de gran
tamaño). Como el costo de crear este objeto al leer la entidad que lo contiene es muy alto, lo marcamos
como una propiedad de lectura demorada con la anotación @Basic(fetch = FetchType.LAZY) .
El comportamiento por defecto de la mayoría de tipos Java es el contrario (lectura temprana). Este
comportamiento, a pesar de ser implícito, puede ser declarado explícitamente de la siguiente manera:

Página 34 de 77
@Basic(fetch = FetchType.EAGER)
private Archivo adjunto;

Hay que tener ciertos cuidados cuando configuramos atributos con lectura demorada. Si, por ejemplo,
marcamos todas las propiedades de tipo int, String o Date de una entidad con lectura demorada, cada vez
que accedemos por primera vez a cada una de ellas el proveedor de persistencia tendrá que hacer una
llamada a la base de datos para leerla.
Esto va a hacer que se realicen muchas llamadas a la base de datos cuando con solo una (al crear la entidad
en memoria) podrían haberse leído todas con muy bajo costo. Por este motivo hay que tener mucho cuidado
al configurar este tipo de atributos porque puede afectar considerablemente el rendimiento de nuestra
aplicación.
La anotación @Basic solo puede ser aplicada a tipos primitivos, sus correspondientes clases wrapper,
BigDecimal, BigInteger, Date, arrays, algunos tipos del paquete java.sql, enums, y cualquier tipo que
implemente la interface Serializable.
Además del atributo fetch, la anotación @Basic admite otro atributo, optional, el cual permite definir si la
propiedad sobre la que se está aplicando la anotación puede contener el valor null.

TIPOS ENUMERADOS
JPA puede mapear los tipos enumerados (enum) mediante la anotación Enumerated:
@Enumerated
private Sexo sexo;

La configuración por defecto de JPA mapeará cada valor ordinal de un tipo enumerado a una columna de
tipo numérico en la base de datos.
public enum Sexo {
FEMENINO,
MASCULINO
}

Si la propiedad sexo tiene el valor Sexo.FEMENINO, en la columna correspondiente de la base de datos de


insertará el valor 0.
Si quiero forzar a la base de datos a utilizar una columna de texto en lugar de una columna numérica: de
esta manera, el valor almacenado será el nombre del valor enum, y no su valor ordinal:
@Enumerated(EnumType.STRING)
private Sexo sexo;

TRANSIENT
Ciertas propiedades de una entidad pueden no representar su estado. Por ejemplo, imaginemos que
tenemos una entidad que representa a una persona:
@Entity
public class Persona {

@Id
@GeneratedValue
private Long id;

private String nombre;


private String apellidos;
private Date fechaNacimiento;
private int edad;
Página 35 de 77
// getters y setters
}

Podemos considerar que la propiedad edad no representa el estado de Persona, ya que si no es actualizada
cada cumpleaños, terminará conteniendo un valor erróneo. Como su valor puede calcularse a partir de la
fecha de nacimiento, no vamos a guardarlo en la base de datos. Para indicar al proveedor de persistencia
que ignore una propiedad cuando realice el mapeo, usamos la anotación @Transient:
@Transient
private int edad;

Ahora, para obtener el valor de edad utilizamos su método getter:


public int getEdad() {
// Calcular la edad y devolverla
}

COLECCIONES
Una entidad puede tener propiedades de tipo java.util.Collection y/o java.util.Map que contengan tipos
básicos. Los elementos de estas colecciones serán almacenados en una tabla diferente a la que contiene la
entidad donde están declarados. El tipo de colección tiene que ser concreto (como ArrayList o HashMap) y
nunca una interface.
private ArrayList nombres;

Podemos customizar la configuración de la siguiente manera:


@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(name = "NOMBRES")
private ArrayList nombres;

@ElementCollection permite definir el tipo de lectura (temprana o demorada).

@CollectionTable nos permite definir el nombre de la tabla donde queremos almacenar los elementos de
la colección. Si nuestra colección es de tipo Map, podemos añadir la anotación @MapKeyColumn(name =
"NOMBRE_COLUMNA"), la cual nos permite definir el nombre de la columna donde se almacenarán las claves
del Map.

TIPOS EMBEDDABLE
Los tipos embeddable son objetos que no tienen identidad: esto significa que para ser persistidos deben
ser primero insertados dentro de una entidad. Cada propiedad del tipo embeddable será mapeada a la tabla
de la entidad que lo contenga, como si fuera una propiedad declarada en la propia entidad. Definimos un
tipo insertable con la anotación @Embeddable:
@Embeddable
public class Direccion {
private String calle;
private int codigoPostal;

// ...
}

Y lo insertamos en una entidad con la anotación @Embedded:

Página 36 de 77
@Entity
public class Persona {
// ...

@Embedded
private Direccion direccion;
}

Ahora, la tabla que contenga las entidades de tipo Persona contendrá sus propias columnas, más las
definidas en el tipo embeddable Direccion.

LAS CLAVES
Cada entidad tiene un identificador de objeto único. Una entidad de un cliente, por ejemplo, puede ser
identificado por un número de cliente. El identificador único, o una clave principal, permite localizar una
instancia de entidad en particular.
Cada entidad debe tener una clave principal. Una entidad puede tener una clave simple o compuesta.
Las claves primarias simples utilizan el javax.persistence.Id anotación para indicar la propiedad de
clave primaria en el campo.
Las claves primarias compuestas se utilizan cuando una clave principal se compone de más de un atributo,
que corresponde a un conjunto de propiedades persistentes individuales o campos. Las claves primarias
compuestas deben ser definidas en una clase aparte de clave primaria. Las claves primarias compuestas se
denotan usando las anotaciones javax.persistence.EmbeddedId y javax.persistence.IdClass.
Las Entidades poseen una identidad que las diferencie del resto:
• Propiedad marcada con la anotación @Id
• Debe admitir valores null, p.e.: Integer en lugar de int
• La identidad de una entidad va a ser gestionada por el proveedor de persistencia.
• Propiedad de identidad anotada: @GeneratedValue

La anotación @GeneratedValue permitirá la generación de forma totalmente automática y transparente de


una clave primaria cada vez que sea necesario insertar un nuevo objeto/registro. Para esta generación JPA
define cuatro estrategias:

CLAVES SIMPLES

@GeneratedValue(strategy = GenerationType.IDENTITY)
MySQL y SQLServer tienen un tipo de columna autonumérica (AUTO_INCREMENT e IDENTITY
respectivamente) ideal para ser usadas como clave primaria. Asimismo, PostgreSQL cuenta con el tipo
SERIAL que simula esta funcionalidad creando secuencias. Podemos usar esta característica mediante este
tipo de generador:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

En el caso de Oracle, al no tener esta funcionalidad obtendremos el correspondiente error:


Oracle10gDialect does not support identity key generation.

Página 37 de 77
@GeneratedValue(strategy = GenerationType.SEQUENCE)
Una secuencia es un objeto o tipo de datos que genera valores numéricos únicos dentro de esa secuencia.
Ese valor se define dentro de un rango, y se va incrementando según un valor de incremento a medida que
se vayan solicitando nuevos valores (por ejemplo en Oracle con la sentencia NOMBRE_SEQ.nextval).
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;

Se pueden definir secuencias específicas para cada clave (o una común a varias de ellas) con la anotación
@SequenceGenerator. Esta anotación tiene como parámetros opcionales allocationSize, que indica el
incremento numérico del avance de la secuencia y cuyo valor por omisión es 50 (por lo que probablemente
queramos definirlo a un valor que nos resulte más conveniente como por ejemplo 1) y initialValue cuyo
valor por defecto es 1 tal y como cabría esperar.
@Entity
public class EntityA{
@Id
@SequenceGenerator(name="entA", sequenceName="entityA_seq", allocationSize = 1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="entA")
private Long id;

....

@Entity
public class EntityB{
@Id
@SequenceGenerator(name="entB", sequenceName="entityB_seq", allocationSize = 1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="entB")
private Long id;

@GeneratedValue(strategy = GenerationType.AUTO)
Delega en el proveedor la elección de la estrategia que considere oportuna en función de la BD subyacente.
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;

Es la estrategia más cómoda, pero debemos conocer qué hace nuestro framework ya que el estándar le da
vía libre y es posible que el resultado no sea el deseado.

@GeneratedValue(STRATEGY = GENERATIONTYPE.TABLE)
Por último, veremos la estrategia más portable de todas ya que se puede emplear de igual manera en
cualquier BD. Se basa en utilizar una tabla con dos columnas, una de tipo texto con el nombre que identifica
al generador de claves primarias (tendremos uno por cada tabla) y otra de tipo numérico con el último
valor que fue asignado como PK para un registro de esa tabla.
@Id
@GeneratedValue(strategy=GenerationType.TABLE)
private Long id;

Página 38 de 77
CLAVES MÚLTIPLES
Con la anotación @Id indicamos un atributo que puede ser de cierto tipo como clave primaria, pero ¿qué
pasaría si nuestra clave primaria es múltiple?
Frente a esta situación, lo que haremos es crear una clase que contenga todos los atributos de nuestra clave
múltiple, y la marcaremos con la anotación @Embeddable que permite que una clase pueda ser incluida en
una entidad y sus atributos formen parte de su mapeo a la BD. Por ejemplo:
@Embeddable
public class EntityPK implements Serializable{
private Long idRef1;
private Long idRef2;

//getters y setters

Ahora nuestra clave primaria estará compuesta por los dos atributos de esta clase y la usaremos con la
anotación @EmbeddedId:
@Entity
public class EntityA{
@EmbeddedId
EntityPK entityPK;

LA MULTIPLICIDAD DE RELACIONES DE ENTIDADES

Las multiplicidades son de los siguientes tipos.


• One to one: Cada instancia de la entidad está relacionada con una sola instancia de otra entidad. Por
ejemplo, para modelar un empleado que tiene una única dirección asociada. Se utiliza la anotación:
javax.persistence.OneToOne en la propiedad o campo persistente correspondiente.

• One to many: Una instancia de la entidad puede estar relacionada con varias instancias de las otras
entidades. Por ejemplo, una biblioteca que puede tener muchos libros. Se utiliza la anotación
javax.persistence.OneToMany en la propiedad o campo persistente correspondiente.

• Many to one: Múltiples instancias de una entidad pueden estar relacionados con una sola instancia de
la otra entidad. Esta multiplicidad es lo contrario de una relación uno-a-muchos. Por ejemplo: un libro
que pertenece a una biblioteca, y la misma puede tener muchos libros. Se utiliza la anotación
javax.persistence.ManyToOne en la propiedad o campo persistente correspondiente.

• Many to many: En este caso varias instancias de una entidad pueden relacionarse con múltiples
instancias de otras entidades. Por ejemplo, cada curso de la universidad tiene muchos estudiantes, y
cada estudiante puede tomar varios cursos. Se utiliza la anotación javax.persistence.ManyToMany en
la propiedad o campo persistente correspondiente.

DIRECCIÓN EN RELACIONES DE ENTIDADES


La dirección de una relación puede ser bidireccional o unidireccional:
• Una relación bidireccional tiene tanto un lado propietario y un lado inverso.
• Una relación unidireccional sólo tiene un lado propietario. El lado propietario de una relación
determina en tiempo de ejecución como se realizan los cambios a la relación en la base de datos.

Página 39 de 77
LAS RELACIONES BIDIRECCIONALES
En una relación bidireccional, cada entidad tiene un campo de relación o propiedad que se refiere a la otra
entidad. A través del campo de relación o de propiedad, el código de una clase de entidad puede tener
acceso a su objeto relacionado. Si una entidad tiene un campo relacionado, se dice que la entidad a "conoce"
su objeto relacionado. Por ejemplo, si CustomerOrder conoce que LineItem tiene y si LineItem conoce al
CustomerOrder que pertenece, se dice que tienen una relación bidireccional.
Las relaciones bidireccionales deben seguir estas reglas.
• El lado inverso de una relación bidireccional debe referirse a su lado propietario mediante el uso de la
mappedBy de la relación @OneToOne , @OneToMany , o @ManyToMany. El mappedBy designa la propiedad o
campo en la entidad que es el dueño de la relación.
• El lado Many de relaciones Many to one bidireccionales no debe definir el elemento mappedBy. El lado
Many es siempre el lado propietario de la relación.
• Para relaciones one to one bidireccionales, el lado propietario corresponde a la parte que contiene la
clave externa correspondiente.
• Para relaciones Many to many bidireccionales, cada lado puede ser la parte propietaria.

LAS RELACIONES UNIDIRECCIONALES


En una relación unidireccional, sólo una entidad tiene un campo de relación o propiedad que se refiere a
la otra. Por ejemplo, LineItem tendría un campo de relación que identifica Product, pero Product no tendría
un campo de relación o propiedad para LineItem . En otras palabras, LineItem conoce a Product, pero
Product no conoce que LineItems se refieren a ella.

LAS CONSULTAS Y DIRECCIÓN DE RELACIÓN


Java Persistence consultas lenguaje de consulta y los criterios del API menudo navegar a través de las
relaciones. La dirección de una relación determina si una consulta puede navegar desde una entidad a otra.
Por ejemplo, una consulta puede navegar desde LineItem al Product, pero no puede navegar en la dirección
opuesta. Para CustomerOrder y LineItem, una consulta podría realizarse en ambas direcciones debido a
que estas dos entidades tienen una relación bidireccional.

OPERACIONES EN CASCADA
Las entidades que utilizan relaciones a menudo tienen dependencias en la existencia de la otra entidad en
la relación.
Por ejemplo, un elemento de línea es parte de un pedido; si se elimina la orden, el elemento de línea también
debería eliminarse. Esto se llama una eliminación en cascada.
El tipo enumerado javax.persistence.CascadeType define las operaciones en cascada que pueden
aplicarse.

Página 40 de 77
OPERACIÓN
DESCRIPCIÓN
EN CASCADA
Todas las operaciones en cascada se aplicarán a la entidad relacionada. All es
ALL
equivalente a especificar cascade={DETACH, MERGE, PERSIST, REFRESH, REMOVE}

Si la entidad matriz se separa del contexto de persistencia, también puede separar la


DETACH
entidad relacionada.

Cuando una entidad es actualizada (se va a grabar), su entidad relacionada debe ser
MERGE
actualizada también.

Cuando una entidad es persistida (se crea), su entidad relacionada debe ser
PERSIST
persistida también.

Cuando una entidad es refrescada /se refresca con los datos de la base de datos), su
REFRESH
entidad relacionada debe ser refrescada también.

Cuando una entidad es removida (se borra), su entidad relacionada debe ser
REMOVE
removida también.

ALGUNOS EJEMPLOS

@OneToOne
@Entity
public class Departamento implements Serializable {

}

@Entity
public class Empleado implements Serializable {
@OneToOne(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.REMOVE},
optional=false)
private Direccion direccion;

}

Configuramos la opción fetch a LAZY, de forma que cuando recuperemos un objeto de la entidad Empleado
no recupere la instancia de Dirección asociada.
Luego pusimos cascade a PERSIST y REMOVE, de forma que cuando persistamos un empleado que tenga
asociada una nueva Direccion, éste también se persistirá, y como no tiene sentido que exista una dirección
sin un empleado asociado, si eliminamos la instancia del Empleado también eliminará la instancia de
Direccion asociada.
También hemos establecido la opción optional a false, de forma que no permitimos que se persista una
instancia de Empleado si no está asociada con una instancia de Direccion.
Por último, con la opción orphanRemoval a true indicamos que cualquier instancia de Direccion que no
esté asociada a una instancia de Empleado será eliminada de la base de datos.
Ahora vamos a convertir la relación one-to-one unidireccional en bidireccional. Bastaría con añadir a la
entidad Direccion un atributo haciendo referencia a la entidad Empleado y anotar el atributo con
@OneToOne.
@OneToOne(fetch=FetchType.LAZY,mappedBy="direccion”)
private Empleado empleado;
Página 41 de 77
Agregamos la opción mappedBy con la que indicamos el atributo de la entidad propietaria de la relación
(Empleado en nuestro caso). De esta forma a través de una instancia de la entidad Direccion podemos
recuperar la instancia de la entidad Empleado asociada.

@OneToMany
@Entity
public class Libro implements Serializable {

}

@Entity
public class Biblioteca implements Serializable {
@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.ALL})
private List libros;

}

La opción fetch está en LAZY, de forma que cuando recuperemos un objeto de la entidad Biblioteca no
recupere las instancias de Libro asociadas.
Luego pusimos cascade a todo, de forma que cuando persistamos, borremos o modifiquemos una
Biblioteca sus libros también se actualizarán.

@ManyToOne
@Entity
public class Biblioteca implements Serializable {
@Id
@GeneratedValue
private Long id;

}

@Entity
public class Libro implements Serializable {
@ManyToOne(fetch=FetchType.LAZY,optional=false)
@JoinColumn(name="id")
private Biblioteca biblioteca;

}

La anotación @JoinColumn o @JoinColumns se usa para especificar cuál es el campo de la tabla que actúa de
clave foránea o clave foránea compuesta, respectivamente.

@ManyToMany
@Entity
public class Clase{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;

@ManyToMany
private List profesores;

Página 42 de 77
@Entity
public class Profesor{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;

@ManyToMany(mappedBy="profesores")
private List clases;

HERENCIA

La herencia es el concepto de la base de cualquier lenguaje orientado a objetos, por lo tanto, podemos
utilizar las relaciones de herencia o estrategias entre las entidades. JPA admiten tres tipos de estrategias
de herencia: SINGLE_TABLE, JOINED_TABLE y TABLE_PER_CONCRETE_CLASS.

SINGLE_TABLE
Una sola tabla para guardar toda la jerarquía de clases.
Tiene la ventaja de ser la opción que mejor rendimiento da, ya que sólo es necesario acceder a una tabla
(está totalmente desnormalizada).
Tiene como inconveniente que todos los campos de las clases hijas tienen que admitir nulos, ya que
cuando guardemos un tipo, los campos correspondientes a los otros tipos de la jerarquía no tendrán valor.

JOINED_TABLE
Una tabla para el padre de la jerarquía, con las cosas comunes, y otra tabla para cada clase hija con las cosas
concretas.
Es la opción más normalizada, y por lo tanto la más flexible (puede ser interesante si tenemos un modelo
de clases muy cambiante), ya que para añadir nuevos tipos basta con añadir nuevas tablas y si queremos
añadir nuevos atributos sólo hay que modificar la tabla correspondiente al tipo donde se está añadiendo el
atributo.
Tiene la desventaja de que para recuperar la información de una clase, hay que ir haciendo join con las
tablas de las clases padre.

TABLE_PER_CONCRETE_CLASS
Una tabla independiente para cada tipo. En este caso cada tabla es independiente, pero los atributos del
padre (atributos comunes en los hijos), tienen que estar repetidos en cada tabla.
En principio puede tener serios problemas de rendimiento, si estamos trabajando con polimorfismo, por
los SQL UNIONS que se tienen que hacer para recuperar la información. Sería la opción menos
aconsejable.
Tanto es así que en la versión 3.0 de EJBs, aunque está recogida en la especificación, no es obligatoria su
implementación.

Página 43 de 77
EJEMPLO

Aquí tenemos un ejemplo clásico de herencia donde tenemos una Persona que puede ser un Alumno o un
Profesor.
Vamos a ver ahora como implemento esta realidad con la estrategia SINGLE_TABLE:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn( name="tipo" )
public abstract class Persona {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

private String apellido;


private String nombre;

// SETTERS AND GETTERS


}

@Entity
@DiscriminatorValue(value="ALUMNO")
public class Alumno extends Persona implements Serializable {

private int generacion;

// GETTERS AND SETTERS


}

@Entity
@DiscriminatorValue( value="PROFESOR" )
public class Profesor extends Persona implements Serializable {

private String gradoDocente;

// GETTERS AND SETTERS


}

Página 44 de 77
La tabla física que se genera es la siguiente:

Id Tipo Nombre Apellido Generacion GradoDocente

1 ALUMNO Juan Perez 2005 <null>

2 PROFESOR Maria Gonzalez <null> Grado 3

Ahora veamos este mismo ejemplo pero utilizando la estrategia JOINED_TABLE:


@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Persona {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

private String apellido;


private String nombre;

// SETTERS AND GETTERS


}

@Entity
@PrimaryKeyJoinColumn(referencedColumnName="id")
public class Alumno extends Persona implements Serializable {

private int generacion;

// GETTERS AND SETTERS


}

@Entity
@PrimaryKeyJoinColumn(referencedColumnName="id")
public class Profesor extends Persona implements Serializable {

private String gradoDocente;

// GETTERS AND SETTERS


}

Esto genera 3 tablas:


Persona

Id Nombre Apellido

1 Juan Perez

2 Maria Gonzalez

Alumno

Id Generacion

1 2005

Página 45 de 77
Profesor

Id GradoDocente

1 grado 3

UNIDADES DE PERSISTENCIA

La agrupación de entidades en una aplicación se llama unidad de persistencia. La unidad de persistencia de


la aplicación se define en un archivo llamado persistence.xml. Este archivo debe existir dentro del
directorio METAINF de la aplicación.
El archivo persistence.xml tiene muchas funciones, pero la más importante es la de listar todas las
entidades, nombrar la unidad de persistencia y brindar los datos necesarios para almacenar los datos en la
base de datos elegida.
Un ejemplo de archivo de persistencia es:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.1">
<persistenceunit name="ejemploJPA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source> java:/XAOracleDS</jta-data-source>
<class>com.ejemplo.Curso</class>
<class>com.ejemplo.Materia</class>
<properties>
<property name="hibernate.dialect" value =
"org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.hbm2ddl.auto" value="createdrop"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistenceunit>
</persistence>

Página 46 de 77
MANEJO DE ENTIDADES

ENTITY MANAGER

Las entidades son gestionadas por el gestor de entidades, que está representado por el
javax.persistence.EntityManager. Cada instancia del EntityManager, se asocia con un contexto de
persistencia: un conjunto de instancias de entidades manejadas que existen en cierto almacén de datos.
Un contexto de persistencia define el alcance bajo el cual instancias de entidades son creadas, persistidas y
removidas. La interfaz EntityManager define los métodos que se utilizan para interactuar con el contexto
de persistencia.

LA INTERFAZ ENTITYMANAGER
La API EntityManager crea y elimina instancias de entidad persistentes, encuentra las entidades por la clave
primaria de la entidad, y permite ejecutar consultas en las entidades.

ENTITY MANAGERS MANEJADOS POR CONTENEDOR


Con un gestor de entidades manejados por contenedor, una instancia del EntityManager del contexto de
persistencia se propaga automáticamente por el contenedor a todos los componentes de las aplicaciones
que utilizan la instancia del EntityManager dentro de una transacción única JTA (API Java Transaction).
Las transacciones JTA por lo general implican llamadas a través de componentes de la aplicación. Para
completar una transacción JTA, estos componentes por lo general necesitan tener acceso a un único
contexto de persistencia. Esto ocurre cuando un EntityManager se inyecta en los componentes de la
aplicación por medio de la anotación javax.persistence.PersistenceContext.
El contexto de persistencia se propaga automáticamente con la transacción JTA actual, y las referencias de
EntityManager que se asignan a la misma unidad de persistencia proporcionan acceso al contexto de
persistencia dentro de esa transacción. Al propagar automáticamente el contexto de persistencia, los
componentes de aplicaciones no necesitan pasar referencias a las instancias de EntityManager entre sí con
el fin de realizar cambios dentro de una única transacción. El contenedor Java EE gestiona el ciclo de vida
de los gestores de entidad manejados por el contenedor.
Para obtener una instancia del EntityManager, basta con inyectar el manejador de la entidad en el
componente de aplicación:
@PersistenceContext
EntityManager em;

LA GESTIÓN DEL CICLO DE VIDA DE UNA ENTIDAD


Se pueden administrar instancias de entidad a través de la invocación de operaciones utilizando una
instancia del EntityManager. Una instancia de una entidad puede estar en uno de estos cuatro estados: new,
managed, detached, o removed.
• New: no tienen identidad persistente y aún no están asociados con un contexto de persistencia.
• Managed: tienen una identidad persistente y están asociados con un contexto de persistencia.
• Detached: tienen una identidad persistente y en la actualidad no están asociados con un contexto de
persistencia.
• Removed: tienen una identidad persistente, están asociados con un contexto persistente, y están
programadas para ser removidas del almacén de datos.
Página 47 de 77
Supongamos el siguiente ejemplo de entidad:
@Entity
public class Curso {
@Id
@GeneratedValue
private Long id;

private String nombre;

@OneToMany (Cascade = ALL)


private List materias = new ArrayList();

// Getters y Setters
}

Para que JPA pueda persistir esta entidad, necesita un archivo de configuración XML llamado
persistence.xml, el cual debe estar ubicado en el directorio META-INF de nuestra aplicación.
Para este ejemplo sería:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistenceunit name="ejemploJPA" transactiontype="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.ejemplo.Curso</class>
<class>com.ejemplo.Materia</class>
<properties>
<property name="eclipselink.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
<property name="eclipselink.jdbc.url"
value="oracle:thin:@myhost:l521:MYSID"/>
<property name="eclipselink.jdbc.user" value="APP"/>
<property name="eclipselink.jdbc.password" value="APP"/>
<property name="eclipselink.ddlgeneration" value="createtables"/>
</properties>
</persistenceunit>
</persistence>

El archivo persistence.xml tiene toda la información necesaria para almacenar los datos en la base de datos
elegida, como el nombre de la unidad de persistencia, el tipo de transacciones que vamos a utilizar, las
clases que deseamos que sean manejadas por el proveedor de persistencia, y los parámetros para conectar
con nuestra base de datos.
El concepto de transacción representa un contexto de ejecución dentro del cual podemos realizar varias
operaciones como si fuera una sola, de manera que o todas ellas son ejecutadas, o el proceso entero falla.
JPA nos permite configurar en cada unidad de persistencia el tipo de transacción que queremos usar, que
puede ser:
• Manejada por la aplicación (RESOURCE_LOCAL).
• Manejada por el contenedor (JTA).

Para JPA, una entidad puede estar en uno de los dos estados siguientes:
• Managed (gestionada).
• Detached (separada).

Página 48 de 77
Cuando persistimos una entidad automáticamente se convierte en una entidad GESTIONADA. Todos los
cambios que efectuemos sobre ella dentro del contexto de una transacción se verán reflejados también en
la base de datos, de forma transparente para la aplicación.
El segundo estado en el que puede estar una entidad es SEPARADO, en el cual los cambios realizados en la
entidad no están sincronizados con la base de datos. Una entidad se encuentra en estado separado antes
de ser persistida por primera vez, y cuando tras haber estado gestionada es separada de su contexto de
persistencia.

PERSISTIENDO UNA ENTIDAD


Las instancias de entidad nuevas, se convierten en administradas y persistentes de dos maneras posibles:
mediante la invocación del método persist o por una operación cascada persist invocada por entidades
relacionadas que tienen la propiedad cascade=PERSIST o cascade=ALL.
Esto significa que los datos de la entidad se almacenan en la base de datos cuando la transacción asociada
al persist se completa.
El siguiente método realiza una persist operación:
@PersistenceContext
EntityManager em;

...

public void crearMateria (Materia materia) {


em.persist (materia);
}

Cuando llamamos a em.persist(materia) la entidad es persistida en nuestra base de datos, la entidad


Materia queda gestionada por el proveedor de persistencia mientras dure la transacción. Por ello, cualquier
cambio en su estado será sincronizado automáticamente y de forma transparente para la aplicación:
em.persist(materia);
materia.setNombre("otro nombre");

Modificamos el nombre de la entidad materia después de haber sido persistida, pero como estoy dentro de
la misma transacción que realizó la persistencia los datos se sincronizarán con la base de datos. Es
importante tener presente que esta sincronización puede no ocurrir hasta que se complete la transacción
e internamente se realice el commit en la base de datos (el momento en que la sincronización se lleve a
cabo depende enteramente de la implementación concreta del proveedor de persistencia que usemos). Lo
que podemos hacer en este caso es forzar a que cualquier cambio pendiente se guarde en la base de datos
en el momento que querramos invocando el método flush() de EntityManager:
em.persist(materia);
materia.setNombre("otro nombre");
em.flush();

También podemos realizar la sincronización en sentido inverso, actualizando una entidad con los datos que
se encuentran en la base de datos. Esto es útil cuando persistimos una entidad, y tras haber cambiado su
estado deseamos recuperar el estado persistido y deshacer los últimos cambios realizados sobre la entidad.
Esto lo realizamos con el método refresh() del EntityManager:
em.persist(materia);
materia.setNombre("otro nombre");
em.refresh(materia);

La llamada al em.refresh() deshace los cambios realizados en materia en la línea anterior.

Página 49 de 77
Otro método del EntityManager es el contains():
boolean gestionada = em.contains(materia);

El método contains() devuelve true si el objeto Java que le pasamos como parámetro se encuentra en
estado gestionado por el proveedor de persistencia, y false en caso contrario.
La operación persist se propaga a todas las entidades relacionadas con la entidad llamante que tienen la
propiedad cascade ALL o PERSIST en la anotación relación:
public Materia crearMateria(Curso curso, String nombre, int capacidad) {
Materia materia = new Materia(nombre, capacidad);
curso.getMaterias().add(materia);
em.persist(materia);
return materia;
}

BUSCANDO UNA ENTIDAD


Para obtener una entidad previamente persistida en la base de datos tengo 2 maneras de hacerlo:
• Obteniendo un objeto real.
• Obteniendo una referencia a los datos persistidos.

Obteniendo un objeto real: puedo realizarlo a través del método find. Este método del EntityManager se
utiliza para buscar entidades a partir de la clave primaria de la entidad:
Materia materia = em.find(Materia.class, id);

Obteniendo una referencia a los datos persistidos: nos permite obtener una referencia a los datos
almacenados en la base de datos, de manera que el estado de la entidad será leído de forma demorada. Se
lee en el primer acceso a cada propiedad y no en el momento de la creación de la entidad:
Materia materia = em.getReference(Materia.class, id);

En ambos casos, el valor de id es la clave primaria de la entidad.

ACTUALIZANDO UNA ENTIDAD


Primero veamos cómo puedo separar una entidad gestionada por el contexto de persistencia. Esto puedo
realizarlo con los métodos detach (separa un entidad) y clear (separa todas las entidades).
Una vez que una entidad se encuentra separada, esta deja de estar gestionada, y por tanto los cambios en
su estado dejan de ser sincronizados con la base de datos.
Para volver a tener nuestra entidad gestionada y sincronizada es que utilizaremos el método merge() de
EntityManager:
em.persist(materia);
em.detach(materia);
// otras operaciones
em.merge(materia);

Separa la materia del contexto de persistencia llamando al método detach(). La última línea, sin embargo,
indica al proveedor de persistencia que vuelva a gestionar la entidad, y que sincronice los cambios en la
base de datos.

Página 50 de 77
ELIMINANDO UNA ENTIDAD
Cuando invocamos al método remove del EntityManager la entidad es eliminada de la base de datos y
separada del contexto de persistencia. Sin embargo, la entidad seguirá existiendo como objeto Java en
nuestro código hasta que el ámbito de la variable termine:
em.remove(materia);
materia.setNombre("ya no soy una entidad, soy solo un objeto Java");

Si el remove método se invoca en una entidad nueva, la operación del remove se ignora. Si el remove se
invoca en una entidad detached, el remove lanzará una IllegalArgumentException o la confirmación de
transacción fallará.
Si se invoca en una entidad que ya se haya removido, el remove será ignorado. Los datos de la entidad se
eliminarán de la memoria de datos cuando se termina la transacción, o como resultado de la operación
flush.

En el siguiente ejemplo, todas las Materias asociadas al curso se removerán, esto es porque la lista de
materias tiene cascade=ALL:
public void removeCurso(Integer cursoId) {
try {
Curso curso = em.find(Curso.class, cursoId);
em.remove(curso);
} ...

SINCRONIZACIÓN DE DATOS DE LA ENTIDAD A LA BASE DE DATOS


Cuando llamamos a persist(), merge(), o remove(), estos cambios no se sincronizan con la base de
datos hasta que el EntityManager decida confirmarlos. Podemos forzar la sincronización en cualquier
momento llamando a flush() en el EntityManager, de modo que los cambios realizados ya pasen a la BD.
Por defecto, se invoca a flush antes que se ejecute una query relacionada con los cambios y al momento de
realizar commit en una transacción.

MÉTODOS CALLBACK

Los métodos callback son métodos que se ejecutan cuando se producen ciertos eventos relacionados con
el ciclo de vida de una entidad. Estos eventos se clasifican en cuatro categorías:
• Eventos de persistencia: Métodos callback asociados anotados con @PrePersists y @PostPersist:
antes y después de persistir.
• Eventos de actualización: Métodos callback asociados anotados con @PreUpdate y @PostUpdate:
antes y después de actualizar.
• Eventos de borrado: Métodos callback asociados anotados con @PreRemove y @PostRemove: antes
y después de remover.
• Eventos de carga: Método callback asociado anotado con @PostLoad: luego de cargar.

Página 51 de 77
@Entity
public class Materia{
...
@PrePersist
@PreUpdate
private void validar() {
// validación de parámetros antes de persistir/actualizar la entidad
}
}

El método validar() se ejecutará ante 2 eventos: el momento antes de realizarse la persistencia


(@PrePersist), y el momento previo a la actualización (@PreUpdate).
Al escribir métodos callback, debemos seguir algunas reglas para que nuestro código sea válido:
• Un método callback no puede ser declarado static ni final.
• Cada anotación de ciclo de vida puede aparecer una y solo una vez en cada entidad.
• Un método callback solo puede tirar excepciones de tipo unchecked (de runtime).
• Un método callback no puede invocar métodos de las clases EntityManager y/o Query.

CLASES LISTENER

Cuando necesitamos aplicar un mismo método callback a varias entidades, es preferible extraer de la
entidad este método y ponerlo en una clase externa, la cual podrá ser aplicada a varias entidades. Estas son
las clases listener:
public class ValidadorListener {
@PrePersist
@PreUpdate public void validar(Materia materia) {
// validar parametros antes de persistir/actualizar la entidad
}
}

Ahora debemos aplicar el listener a las entidades que querramos:


@Entity
@EntityListeners(ValidadorListener.class)
public class Materia { ... }

En tiempo de ejecución, cuando se produzca un evento que se encuentre definido en la clase listener, el
proveedor de JPA pasará a su método validar() una referencia de la entidad Materia.
También existe la anotación @EntityListeners puede hacer referencia a varias clases listener usando un
array de objetos .class. Cuando una entidad es asociada con varias clases listener, los métodos callback de
dichas clases que hagan referencia a un mismo evento serán invocados en el orden en que fueron
declarados dentro del array.
Así mismo, los métodos callback de las clases listener serán invocados de manera previa a los métodos
callback que hagan referencia al mismo tipo de evento y que estén declarados dentro de la entidad:

Página 52 de 77
@Entity
@EntityListeners({ ValidadorListener.class, OtroListener.class})
public class Materia {
// ...

@PrePersist
@PreUpdate
private void validar() {
// validar parámetros antes de persistir y actualizar la entidad
}
}

En este ejemplo, los métodos @PrePersist y @PreUpdate se ejecutarán en este orden: ValidatorListener,
OtroListener, Materia.

Página 53 de 77
JAVA PERSISTENCE QUERY LANGUAGE

QUÉ ES

JPQL es un lenguaje de consulta orientado a objetos definido en la especificación de Java Persistence API
(JPA).
JPQL es usado para hacer consultas contra las entidades almacenadas en una base de datos relacional. Su
sintaxis es muy similar a la de SQL, pero mientras SQL trabaja directamente con bases de datos relacionales,
registros y campos; JPQL lo hace con clases Java e instancias.
Además de recuperar objetos a través de las consultas SELECT, JPQL también soporta consultas de
actualización y borrado como lo son el UPDATE y DELETE.

SINTAXIS

Veamos primero la sintaxis de este tipo de consultas empezando con un ejemplo.


SELECT m FROM Materia m

Esta query lo que hace es obtener todas las instancias de la clase Materia de la base de datos. El SELECT se
utiliza para seleccionar cierta información desde el FROM. El “FROM Materia m” indica que m es un alias
para la clase Materia, mientras que el “SELECT m” indica que la expresión m se utiliza para acceder a la
clase Materia a la que refiere el alias o a sus propiedades.

Si quisiera obtener el nombre de las materias:


SELECT m.nombre FROM Materia m

También puede querer obtener los ids y nombres de todas las materias:
SELECT m.id, m.nombre FROM Materia m

Puedo querer eliminar los resultados duplicados usando la cláusula DISTINCT:


SELECT DISTINCT p.nombre FROM Materia m

También puedo utilizar funciones agregadas como el COUNT, SUM, MAX, MIN, AVG, etc. Si quisiera saber la
cantidad de materias que tengo:
SELECT COUNT(m) FROM Materia m

El WHERE permite restringir los resultados devueltos por una consulta, en base a ciertos criterios lógicos.
SELECT m FROM Materia m
WHERE m.capacidad < 50

En esta sentencia estoy obteniendo todas las instancias de Materia que tengan una capacidad de menos de
50 estudiantes. También puedo agregar más condiciones:

Página 54 de 77
SELECT m FROM Materia m
WHERE m.capacidad < 50 AND m.tipo = ‘CIENCIAS’

En este caso se obtienen las materias con capacidad menor a 50 estudiantes y que sean de tipo CIENCIAS.

Puedo utilizar los operadores lógicos AND, OR y NOT.


SELECT m FROM Materia m
WHERE m.capacidad < 50 AND NOT (m.tipo = ‘CIENCIAS’)

Ahora estoy obteniendo las materias con capacidad menor a 50 estudiantes y que NO sean de tipo
CIENCIAS.

También puedo utilizar el BETWEEN para comparar entre rangos:


SELECT m FROM Materia m
WHERE m.capacidad BETWEEN 20 AND 50

Otro operador de comparación muy útil es [NOT] LIKE (NOT es opcional), el cual nos permite comparar una
cadena de texto completa o solo una parte de ella:
SELECT m FROM Materia m
WHERE m.nombre LIKE 'A%'

En esta consulta se obtienen todas las instancias de Materia cuyo nombre comience con A.

PARÁMETROS
Podemos agregar parámetros en forma dinámica a nuestras sentencias JPQL de dos maneras: por posición
y por nombre.
Por posición:
SELECT m FROM Materia m
WHERE m.nombre = ?1

Por nombre:
SELECT m FROM Materia m
WHERE m.nombre = :nombre

Cuando quiera ejecutar la consulta tendré que pasar el o los valores que sustituyan a los parámetros
definidos.

Para poder ordenar los resultados de nuestras consultas, podemos utilizar la cláusula ORDER BY que admite
ordenamiento ascendente (ASC que es el por default) o descendente (DESC):
SELECT m FROM Materia m
ORDER BY m.capacidad DESC

Aquí se retornan las materias ordenadas por capacidad de mayor a menor.

Página 55 de 77
SELECT m FROM Materia m
WHERE m.tipo = ‘CIENCIAS’
ORDER BY m.capacidad DESC, m.nombre ASC

Ahora estoy obteniendo todas las materias de tipo CIENCIAS ordenadas por capacidad de mayor a menor
y el forma alfabética.

RESUMIENDO
Una sentencia SELECT puede tener 6 cláusulas: SELECT, FROM, WHERE, GROUP BY, HAVING, and ORDER BY.
El SELECT y FROM son obligatorias, pero el WHERE, GROUP BY, HAVING, y ORDER BY son opcionales.
La sintaxis de alto nivel sería:
QL_statement ::= select_clause from_clause
[where_clause][groupby_clause][having_clause][orderby_clause]

Donde:
• El SELECT define los tipos de objetos o valores que retorna la query.
• El FROM define el alcance de la query definiendo una o más variables de identificación que podrán ser
referenciadas en el SELECT y WHERE. Una variable de identificación representa uno de los siguientes
elementos:
o El nombre del esquema abstracto de una entidad.
o Un elemento colección de una relación.
o Un elemento de un solo valor de una relación.
o Un miembro de una colección que es el lado múltiple de una relación One-To-Many.
• El WHERE es una expresión condicional que restringe los objetos o valores que retorna la query.
• El GROUP BY agrupa resultado de acuerdo a un conjunto de propiedades.
• El HAVING es usado junto con el GROUP BY para restringir los resultados de acuerdo a la expresión.
• El ORDER BY ordena los objetos o valores retornados por la query.

ACTUALIZACIÓN DE DATOS Y BORRADO

La sentencia UPDATE nos permite realizar operaciones de actualización en la base de datos:


UPDATE Materia m
SET m.capacidad = 20
WHERE m.tipo = ‘CIENCIAS’

En la sentencia anterior se actualizan las instancias de Materia donde el tipo es CIENCIAS, poniéndoles
capacidad de 20 estudiantes.

También puedo hacer lo siguiente:


DELETE FROM Materia m
WHERE m.capacidad = 0

De esta manera borro las materias que no tengan capacidad para estudiantes.

Página 56 de 77
RESUMIENDO
La sintaxis es:
update_statement :: = update_clause [where_clause]
delete_statement :: = delete_clause [where_clause]

El UPDATE y DELETE determinan el tipo de entidades que serán actualizadas o borradas. El WHERE es
opcional y se usa para restringir el alcance de los datos actualizados o borrados.

EJECUTANDO SENTENCIAS JPQL

Los métodos EntityManager.createQuery y EntityManager.createNamedQuery se utilizan para realizar


búsquedas en la base de datos utilizando consultas JPQL.
El método createQuery se utiliza para crear las consultas dinámicas, que son consultas definidas
directamente dentro de la lógica de negocio de una aplicación:
public List obtenerMateriasPorTipo(String tipoMateria) {
return em.createQuery(
"SELECT m FROM Materia m WHERE m.tipo LIKE :tipo")
.setParameter("tipo", tipoMateria)
.setMaxResults(10) // indica cantidad máxima de resultados
.getResultList();
}

El método createNamedQuery se utiliza para crear consultas estáticas o consultas que se definen en los
metadatos mediante el uso de la anotación javax.persistence.NamedQuery. El elemento name de
@NamedQuery especifica el nombre de la consulta que se utilizará con el método createNamedQuery.
Por ejemplo: En el entity de Materia puedo definir:
@NamedQuery (
name = "Materia.obtenerPorTipo",
query = "SELECT m FROM Materia m WHERE m.tipo LIKE :tipo"
)

Y para usar el método createNamedQuery, que utiliza la @NamedQuery:


@PersistenceContext
public EntityManager em;
...
materias = em.createNamedQuery("Materia.obtenerPorTipo")
.setParameter("tipo", "CIENCIAS")
.getResultList();

Los named parameters son los parámetros de consulta con el prefijo dos puntos ( : ). Estos parámetros se
setean utilizando el método javax.persistence.Query.setParameter (String nombre, Object valor).
Los named parameters son case sensitive y pueden ser utilizados por ambas consultas dinámicas y
estáticas.
En el método obtenerMateriaPorTipo, el named parameter es “tipo”.
En vez de los named parameters pueden utilizarse parámetros posicionales en las consultas. Los
parámetros posicionales van precedidos de un signo de interrogación ( ? ), seguido de la posición numérica

Página 57 de 77
del parámetro de la consulta. El método Query.setParameter(integer position, Object value) se utiliza para
establecer los valores de los parámetros.
Reescribiendo el método de obtenerMateriasPorTipo con parámetros posicionales sería:
public List obtenerMateriasPorTipo(String tipoMateria) {
return em.createQuery(
"SELECT m FROM Materia m WHERE m.tipo LIKE ?1")
.setParameter(1, tipoMateria)
.setMaxResults(10)
.getResultList();
}

QUERY VS QUERY TIPADA

Para obtener todas las materias, por ejemplo, tengo 2 formas de hacerlo:
Query query = em.createQuery("SELECT m FROM Materia m");
List resultados = query.getResultList();

o
TypedQuery query = em.createQuery("SELECT m FROM Materia m", Materia.class);
List resultados = query.getResultList();

El objeto Query y el TypedQuery definen ambos un método getResultList, pero la versión de Query retorna
una lista de un tipo de dato no genérico, en vez de uno parametrizado (genérico).

Las queries tipadas también puedo utilizarlas de forma análoga con las named queries:
TypedQuery query = em.createNamedQuery("Materia.obtenerTodas", Materia.class);
List resultados = query.getResultList();

Es una buena práctica utilizar Queries tipadas, de esa manera ya le indicamos de antemano que tipo de dato
nos debe retornar.

CONSULTAS NATIVAS SQL

Por último puedo querer ejecutar sentencias SQL nativas en vez de una sentencia JPQL:
String sql = "SELECT * FROM MATERIA";
Query query = em.createNativeQuery(sql);
// ...

Estas consultas SQL nativas también pueden ser definidas de manera estática:
@Entity
@NamedNativeQuery(name=”Materia.obtenerTodas”, query="SELECT * FROM MATERIA")
public class Materia {
// ...
}

Página 58 de 77
IMPLEMENTACIÓN DE HERENCIAS Y RELACIONES

IMPLEMENTAR HERENCIA CON ESTRATEGIA SIMPLE

Característica: una tabla para toda la jerarquía.


Se implementó el siguiente diagrama de clases:

Se persistió una instancia de Profesor y otra de Alumno, y se obtuvo una tabla en la base de datos con la
siguiente estructura y contenido:

SERVIDOR
Se implementó de la siguiente manera en el servidor:

Página 59 de 77
PERSONA.JAVA
package com.entidades;

import java.io.Serializable;
import javax.persistence.*;

@Entity
@Table
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="tipo")
public class Persona implements java.io.Serializable {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;

@Column(length=20)
private String nombre;

@Column(length=20)
private String apellido;

public Persona() {
super();
}

// getters y setters

ALUMNO.JAVA
package com.entidades;

import java.io.Serializable;
import javax.persistence.*;

@Entity
@DiscriminatorValue(value="ALUMNO")
public class Alumno extends Persona implements Serializable {

private int generacion;

public Alumno() {
super();
}

//getters y setters
}

Página 60 de 77
PERSONASBEANREMOTE.JAVA
package com.servicios;

import java.util.List;
import javax.ejb.Remote;
import com.entidades.*;

@Remote
public interface PersonasBeanRemote {

public void crear(Profesor profesor);


public void crear(Alumno alumno);
public List<Persona> obtenerTodos();
public Profesor buscarProfesor(Long id);
public Alumno buscarAlumno(Long id);

PERSONASBEAN.JAVA
package com.servicios;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.*;
import com.entidades.*;

@Stateless
public class PersonasBean implements PersonasBeanRemote {

@PersistenceContext
private EntityManager em;

public PersonasBean() {

@Override
public void crear(Profesor profesor) {
em.persist(profesor);
em.flush();
}

@Override
public void crear(Alumno alumno) {
em.persist(alumno);
em.flush();
}

@Override
public List<Persona> obtenerTodos() {
TypedQuery<Persona> query = em.createQuery("SELECT p FROM Persona p",
Persona.class);
return query.getResultList();
}

Página 61 de 77
@Override
public Profesor buscarProfesor(Long id) {
Profesor p = em.find(Profesor.class, id);
return p;
}

@Override
public Alumno buscarAlumno(Long id) {
Alumno a = em.find(Alumno.class, id);
return a;
}
}

ARCHIVOS DE CONFIGURACIÓN EN EL SERVIDOR

PERSISTENCE.XML
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="Herencia_1_EJB">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/HerenciaDS</jta-data-source>
<mapping-file>META-INF/orm.xml</mapping-file>
<class>com.entidades.Persona</class>
<class>com.entidades.Alumno</class>
<class>com.entidades.Profesor</class>
<validation-mode>AUTO</validation-mode>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true" />
<property name="javax.persistence.schema-generation.create-database-
schemas" value="true"/>
</properties>
</persistence-unit>
</persistence>

ORM.XML
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd">
<persistence-unit-metadata>
<persistence-unit-defaults>
<access>FIELD</access>
</persistence-unit-defaults>
</persistence-unit-metadata>
<entity class="com.entidades.Persona" access="FIELD">
<table name="PERSONAS">
</table>
Página 62 de 77
</entity>
</entity-mappings>

CLIENTE
En el cliente se implementó la siguiente clase para realizar la prueba:
package com.cliente;

import java.util.List;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.entidades.*;
import com.servicios.PersonasBeanRemote;

public class Cliente_H1 {

public static void main(String[] args)throws NamingException {

PersonasBeanRemote person = (PersonasBeanRemote)


InitialContext.doLookup("Herencia_1_EJB/PersonasBean!com.servicios.PersonasBeanRem
ote");

altasPersonas(person);

List<Persona> per = person.obtenerTodos();


Alumno aux;
Profesor prof;

for (Persona pe : per) {

if (pe instanceof Profesor) {


System.out.println("Es un profesor");
Long id=pe.getId();
prof=person.buscarProfesor(id);
System.out.print(prof.getNombre()+" --- ");
System.out.print(prof.getApellido()+ "-- grado : ");
System.out.println(prof.getGradoDocente());

} else if(pe instanceof Alumno) {


System.out.println("Es un Alumno");
Long id=pe.getId();
aux=person.buscarAlumno(id);
System.out.print(aux.getNombre()+" --- ");
System.out.print(aux.getApellido()+ "-- generacion : ");
System.out.println(aux.getGeneracion());

}
}
}

// Metodo que da de altas Profesores y Alumnos


public static void altasPersonas(PersonasBeanRemote per) {

per.crear(new Profesor("Jose","Granada","grado4"));
per.crear(new Alumno("Ana","Marquez",2019));
per.crear(new Profesor("Marta","Dinardi","grado2"));

Página 63 de 77
per.crear(new Alumno("Daniel","Ventos",2020));
per.crear(new Alumno("Luis","Fontes",2020));
per.crear(new Alumno("Antonio","Rios",2020));
per.crear(new Alumno("Joaquin","Beal",2020));
per.crear(new Alumno("Emiliano","Silva",2019));
per.crear(new Profesor("Sergio","Trias","grado 2"));

}
}

Resultado de la salida por la consola del listado total de Personas :


Es un profesor
Jose --- Granada-- grado : grado4
Es un Alumno
Ana --- Marquez-- generacion : 2019
Es un profesor
Marta --- Dinardi-- grado : grado2
Es un Alumno
Daniel --- Ventos-- generacion : 2020
Es un Alumno
Luis --- Fontes-- generacion : 2020
Es un Alumno
Antonio --- Rios-- generacion : 2020
Es un Alumno
Joaquin --- Beal-- generacion : 2020
Es un Alumno
Emiliano --- Silva-- generacion : 2019
Es un profesor
Sergio --- Trias-- grado : grado 2

IMPLEMENTAR HERENCIA TIPO JOINED

Característica: una tabla para cada entidad.


Se implementó el siguiente diagrama de clases:

Página 64 de 77
Se persistió una instancia de Profesor y otra de Alumno, y se obtuvo las siguientes tablas en la base de datos
con la siguiente estructura y contenido:
Una tabla PERSONAS con los dos registros (un profesor y un alumno) y su ID correspondiente:

Una tabla PROFESORES sólo con el registro del profesor, con el ID que le corresponde y con el atributo
propio del profesor (gradoDocente).

Una tabla ALUMNOS sólo con el registro del alumno, con el ID que le corresponde y con el atributo propio
del alumno (generacion).

SERVIDOR
Se implementó de la siguiente manera en el servidor:

PERSONA.JAVA
package com.entidades;

import javax.persistence.*;

@Entity
@Table(name="PERSONAS")
@Inheritance(strategy=InheritanceType.JOINED)
public class Persona implements java.io.Serializable{

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_PER")
@SequenceGenerator(name = "SEQ_PER", initialValue = 1, allocationSize = 1)
private Long id;

Página 65 de 77
private String nombre;
private String apellido;

public Persona() {
super();
}

public Persona(Long id, String nombre, String apellido) {


this.id = id;
this.nombre = nombre;
this.apellido = apellido;
}

// Getters y setters
}

ALUMNO.JAVA
package com.entidades;

import java.io.Serializable;
import javax.persistence.*;

@Entity
@Table(name="ALUMNOS")
@PrimaryKeyJoinColumn(referencedColumnName="id")
public class Alumno extends Persona implements Serializable {

private int generación = 0;

public Alumno() {
super();
}

// Getters y setters
}

PROFESOR.JAVA
package com.entidades;

import java.io.Serializable;
import javax.persistence.*;

@Entity
@Table(name="PROFESORES")
@PrimaryKeyJoinColumn(referencedColumnName="id")
public class Profesor extends Persona {

private String gradoDocente;

public Profesor() {
super();
}

// Getters y setters
}
Página 66 de 77
PERSONASBEANREMOTE.JAVA
package com.servicios;

import java.util.List;
import javax.ejb.Remote;
import com.entidades.*;

@Remote
public interface PersonasBeanRemote {

public void crear(Profesor profesor);


public void crear(Alumno alumno);
}

PERSONASBEAN.JAVA
package com.servicios;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.*;
import com.entidades.*;

@Stateless
public class PersonasBean implements PersonasBeanRemote {

@PersistenceContext
private EntityManager em;

public PersonasBean() {

@Override
public void crear(Profesor profesor) {
em.persist(profesor);
em.flush();
}

@Override
public void crear(Alumno alumno) {
em.persist(alumno);
em.flush();
}
}

Página 67 de 77
ARCHIVOS DE CONFIGURACIÓN EN EL SERVIDOR

PERSISTENCE.XML
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="Herencia_2_EJB">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/HerenciaDS</jta-data-source>
<mapping-file>META-INF/orm.xml</mapping-file>
<validation-mode>AUTO</validation-mode>
<properties>
<property name = "hibernate.dialect" value =
"org.hibernate.dialect.Oracle10gDialect"/>
<property name = "hibernate.hbm2ddl.auto" value = "create-drop" />
<property name = "hibernate.show_sql" value = "true" />
<property name="javax.persistence.schema-generation.create-database-
schemas" value="true"/>
</properties>
</persistence-unit>
</persistence>

ORM.XML
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd">
<persistence-unit-metadata>
<persistence-unit-defaults>
<access>FIELD</access>
</persistence-unit-defaults>
</persistence-unit-metadata>
<entity class="com.entidades.Persona" access="FIELD">
<table name="PERSONAS"></table>
<inheritance strategy="JOINED"/></entity>
<entity class="com.entidades.Profesor" access="FIELD">
<table name="PROFESORES">
</table></entity>
<entity class="com.entidades.Alumno" access="FIELD">
<table name="ALUMNOS">
</table></entity></entity-mappings>

Página 68 de 77
CLIENTE
En el cliente se implementó la siguiente clase para realizar la prueba:
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.entidades.*;
import com.servicios.PersonasBeanRemote;

public class Cliente {

public static void main(String[] args)throws NamingException {

String ruta =
"ejb:/Herencia_2_EJB/PersonasBean!com.servicios.PersonasBeanRemote";
PersonasBeanRemote person = (PersonasBeanRemote)
InitialContext.doLookup(ruta);

Profesor p = new Profesor();


p.setNombre("Jose");
p.setApellido("Granada");
p.setGradoDocente("grado 4");

try {
person.crear(p);
} catch(Exception e) {
System.out.println("Error al crear Profesor");
System.out.println(e.getMessage());
}

Alumno a = new Alumno();


a.setNombre("Ana");
a.setApellido("Marquez");
a.setGeneracion(2019);

try{
person.crear(a);
} catch(Exception e) {
System.out.println("Error al crear Alumno");
System.out.println(e.getMessage());
}
}
}

Para hacer el listado total, se hace de la misma forma que con una sola tabla. Fijarse el ejemplo anterior.

Página 69 de 77
IMPLEMENTAR UNA CASO DE MANYTOMANY

Dado una entidad Libro, que puede tener muchos Autores, y que un Autor puede estar en muchos Libros,
tenemos una relación de N a N.
Vamos a verlo en un Ejemplo.

ENTIDADES

ENTIDAD LIBRO
package com.entidades;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.*;

@Entity
@Table(name="LIBROS")
public class Libro implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@SequenceGenerator(name = "SEQ_LIB", initialValue = 1, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_LIB")
private Long id;

private String nombre;

// Estas anotaciones hacen crear una tabla(auxiliar) en SQL con las dos id de
cada entidad que tiene la relación N a N
@JoinTable(
name = "LIBROS_AUTORES",
joinColumns = @JoinColumn(name = "FK_LIBRO", nullable = false),
inverseJoinColumns = @JoinColumn(name="FK_AUTOR", nullable = false)
)
@ManyToMany(cascade=CascadeType.ALL ,fetch = FetchType.EAGER)
private Set<Autor> autores;

Página 70 de 77
public void addAutor(Autor autor) {
if(this.autores == null){
this.autores = new HashSet<>();
}
this.autores.add(autor);
}

public Libro() {
super();
}

// Getters y Setters

public Long getId() {


return id;
}

public void setId(Long id) {


this.id = id;
}

public String getNombre() {


return nombre;
}

public void setNombre(String nombre) {


this.nombre = nombre;
}

public Set<Autor> getAutores() {


return autores;
}

public void setAutores(Set<Autor> autores) {


this.autores = autores;
}
}

ENTIDAD AUTOR
package com.entidades;

import java.io.Serializable;
import java.util.List;
import java.util.Set;

import javax.persistence.*;

@Entity
@Table(name="AUTORES")
public class Autor implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@SequenceGenerator(name = "SEQ_AUT", initialValue = 1, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_AUT")
private Long id;
Página 71 de 77
@Column
private String nombre;

// En esta relacion N a N lo que se mapea con mappedBy es el nombre de la lista


en la entidad Libro
@ManyToMany( mappedBy="autores")
private Set <Libro> lib;

public Autor() {
super();
}

public Long getId() {


return id;
}

public void setId(Long id) {


this.id = id;
}

public String getNombre() {


return nombre;
}

public void setNombre(String nombre) {


this.nombre = nombre;
}

public Set<Libro> getLib() {


return lib;
}

public void setLib(Set<Libro> lib) {


this.lib = lib;
}
}

SERVIDOR
Se implementó de la siguiente manera en el servidor:

LIBROBEANREMOTE
package com.servicios;

import javax.ejb.Remote;
import com.entidades.Libro;

@Remote
public interface LibroBeanRemote {

public void crearLibro(Libro libro);

Página 72 de 77
LIBROBEAN
package com.servicios;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.entidades.Libro;

@Stateless
public class LibroBean implements LibroBeanRemote {

@PersistenceContext
private EntityManager em;

public LibroBean() {

@Override
public void crearLibro(Libro libro) {

// Importante: El uso de merge en lugar de persist nos sirve para dar de alta
los autores ya que los que ya estan creados no los da de alta nuevamente.
em.merge(libro);
em.flush();
}
}

AUTORESBEANREMOTE
package com.servicios;

import javax.ejb.Remote;
import com.entidades.Autor;

@Remote
public interface AutoresBeanRemote {

public void crearAutor(Autor autor);


public Autor ObtenerAutor(Long id);
public Autor ObtenerAutor(String nombre);

AUTORESBEAN
package com.servicios;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import com.entidades.Autor;

Página 73 de 77
@Stateless
public class AutoresBean implements AutoresBeanRemote {

@PersistenceContext
private EntityManager em;

public AutoresBean() {

@Override
public void crearAutor(Autor autor) {
em.persist(autor);
em.flush();
}

@Override
public Autor ObtenerAutor(Long id) {
Autor autor=em.find(Autor.class, id);
return autor;
}

@Override
public Autor ObtenerAutor(String nombre) {
TypedQuery<Autor> query ;
query = em.createQuery("SELECT a FROM Autor a WHERE a.nombre LIKE :nombre",
Autor.class).setParameter("nombre", nombre);
return query.getSingleResult();
}
}

ARCHIVOS DE CONFIGURACIÓN EN EL SERVIDOR

ORM.XML
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd">
<persistence-unit-metadata>
<persistence-unit-defaults>
<access>FIELD</access>
</persistence-unit-defaults>
</persistence-unit-metadata>
<entity class="com.entidades.Libro" access="FIELD">
<table name="LIBROS">
</table>
</entity>
<entity class="com.entidades.Autor" access="FIELD">
<table name="AUTORES">
</table>
</entity>
</entity-mappings>

Página 74 de 77
CLIENTE

CLIENTE_MTM_1.JAVA
package com.cliente;

import java.util.HashSet;
import java.util.Set;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.entidades.Autor;
import com.entidades.Libro;
import com.servicios.AutoresBeanRemote;
import com.servicios.LibroBeanRemote;

public class Cliente_MTM_1 {


public static void main(String[] args)throws NamingException {

String ruta="MTM_EJB//LibroBean!com.servicios.LibroBeanRemote";
String ruta2="MTM_EJB//AutoresBean!com.servicios.AutoresBeanRemote";

LibroBeanRemote vari = (LibroBeanRemote) InitialContext.doLookup(ruta);


AutoresBeanRemote vari2 = (AutoresBeanRemote)
InitialContext.doLookup(ruta2);

// Nuevos Autores
Autor autor1 = new Autor();
autor1.setNombre("Maria Barrios");

Autor autor2 = new Autor();


autor2.setNombre("Julio Blanco");

Autor autor3 = new Autor();


autor3.setNombre("Marcos Martinez");

Autor autor4 = new Autor();


autor4.setNombre("Ana Paladino");

Autor autor5 = new Autor();


autor5.setNombre("Karen Lopez");

// Nuevos Libros
Libro libro1 = new Libro();
libro1.setNombre("El hombre y las computadoras");
libro1.addAutor(autor1);
libro1.addAutor(autor4);

vari.crearLibro(libro1);

System.out.println("Se creo el primer Libro");

// Como voy a poner en el siguiente libro un autor que ya di de alta hago el


control antes buscando para ver si existe. Si existe que cargado en la variable
correspondiente, con el id. Al hacer merge si ya tiene id, no lo da de alta.

autor4=vari2.ObtenerAutor("Ana Paladino");
System.out.println(autor4.getNombre()+" "+autor4.getId());
Página 75 de 77
Libro libro2 = new Libro();
libro2.setNombre("Encontrando la solucion de Java EE");
libro2.addAutor(autor4);

vari.crearLibro(libro2);

System.out.println("Se creo el segundo Libro");

Libro libro3 = new Libro();


libro3.setNombre("El hombre que sabia usar el merge");
libro3.addAutor(autor5);
libro3.addAutor(autor3);

// Como autor1 ya lo di de alta en el libro1 lo busco antes para que le


cargue la id, asi el merge no lo da de alta.

autor1=vari2.ObtenerAutor("Maria Barrios");
System.out.println(autor1.getNombre()+" "+autor1.getId());

libro3.addAutor(autor1);

vari.crearLibro(libro3);

System.out.println("Se creo el tercer Libro");

System.out.println("FIN DEL PROGRAMA");


}
}

TABLAS EN SQL
Como quedaron las tablas en sql.
Autores

Libros

Página 76 de 77
Libros_Autores

Página 77 de 77

También podría gustarte