PROYECTO FIN DE CARRERA ANÁLISIS Y USO DE FRAMEWORKS DE PERSISTENCIA EN JAVA Autor: Alfredo Payá Martín Director: José Miguel Ordax Cassá UNIVERSIDAD PONTIFICIA COMILLAS ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA (ICAI) INGENIERO TÉCNICO EN INFORMÁTICA DE GESTIÓN INGENIERO TÉCNICO EN INFORMÁTICA DE SISTEMAS
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
PROYECTO FIN DE CARRERA
ANÁLISIS Y USO DE FRAMEWORKS DE PERSISTENCIA EN JAVA
Autor: Alfredo Payá Martín Director: José Miguel Ordax Cassá
UNIVERSIDAD PONTIFICIA COMILLAS
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA (ICAI) INGENIERO TÉCNICO EN INFORMÁTICA DE GESTIÓN
INGENIERO TÉCNICO EN INFORMÁTICA DE SISTEMAS
Análisis y Uso de Frameworks de Persistencia en Java
I
Agradecimientos
Gracias a todos.
A mi familia que me ha apoyado durante toda la carrera. Pero en
especial a mis padres, por esta gran oportunidad.
A Esther, que me ha ayudado a sentar la cabeza, y ha sufrido todas las
horas de trabajo dedicadas al proyecto sacrificando preciosos días de
vacaciones.
A todos mis amigos y compañeros de clase, por haberme animado y
apoyado durante todos los años de carrera.
Análisis y Uso de Frameworks de Persistencia en Java
II
Resumen
Análisis y Uso de Frameworks de Persistencia en Java
III
RESUMEN
Este proyecto pretende realizar un análisis completo de las diferentes
alternativas que hay para conseguir la persistencia de datos en Java. A continuación, se
construirá una aplicación Web para la explotación de datos empleando una de las
alternativas analizadas en un principio. Como consecuencia, el proyecto va a estar
formado por dos partes bien diferenciadas, una primera parte teórica y otra práctica.
La motivación que inspira este proyecto es fácil de explicar. Lo más importante
para una empresa son los datos que maneja. Todos los elementos que conforman una
empresa están reflejados en datos, desde los empleados hasta los clientes, desde los
recursos que posee hasta los productos que vende, etc. La información y características
asociadas de estos elementos siempre pueden ser útiles y, en otros casos, indispensables
para el funcionamiento de la empresa.
¿Qué sería de un banco si tiene problemas a la hora de manejar los datos de sus
clientes? ¿Y los datos de sus transacciones? Es evidente que los datos conforman el
corazón de las empresas y, por esta razón, es crucial la forma de manejarlos.
Toda la información que posee cualquier empresa, generalmente, está
almacenada en forma de tablas que comparten datos y conforman bases de datos
relacionales. Si los accesos a la información toman un papel importante en las
operaciones rutinarias empresariales, es normal que la forma de explotar esos datos
Análisis y Uso de Frameworks de Persistencia en Java
IV
tenga una repercusión directa en la eficiencia de la empresa. Dada la trascendencia que
toman los accesos a dicha información, se puede afirmar que la forma de realizar
consultas a las bases de datos es tan importante como el diseño de sus tablas.
Hoy en día Java sigue siendo un lenguaje en pleno desarrollo. Su falta de
sencillez a la hora de trabajar con bases de datos, ha provocado la aparición de
diferentes frameworks que facilitan estas tareas. Existen diversas alternativas que
aportan métodos diferentes: Hibernate, EJB’s, JDO, o, sencillamente, JDBC. La
eficiencia de dichas alternativas será definitiva a la hora de manejar bases de datos con
Java.
Ahora, si nos paramos a pensar en las aplicaciones prácticas de esta tecnología
veremos que una gran forma de aprovechar estas tecnologías es la explotación de tablas
en un entorno Web. Por ejemplo, en una empresa sería de gran utilidad que, a través de
un portal común, los empleados de los diferentes departamentos puedan hacer consultas
directamente sobre las bases de datos de una forma sencilla e intuitiva. Gracias a los
perfiles de usuario, un mismo portal serviría a todos los componentes de la empresa.
Todo el mundo tendría un acceso cómodo, rápido y sin intermediarios a la información
que necesite en cada momento, dentro de una selección de los datos más usados por los
departamentos. A su vez, el departamento de informática sería el encargado del
mantenimiento del portal. Esto se puede realizar con tecnología J2EE y una de las
alternativas de persistencia de datos.
Análisis y Uso de Frameworks de Persistencia en Java
V
ABSTRACT
This proyect tries to do a complete analysis of the most important alternatives
that can be found in order to persist data with Java. Next, a web application will be
designed and built using one of the alternatives studied in the first place. This way, the
proyect will be divided into two different parts, theoretical and practical.
The motivation that inspires this proyect is easy to explain. The most important
thing about any company is the data management. Every component of the system is
going to be represented by data: employees and clients, products and resources... The
information associated to these elements is always useful, and many times is essential.
What would happen to a bank if it finds difficulties when managing the data
about its clients? And what would happen with the transactions? It is obvious that the
data is the heart of the companies and, because of this, its management is critical.
All the information about a company is usually stored with the help of relational
data bases. If the access to the information is important when doing daily operations in a
company, it is normal that the way used to get the data is linked to the company’s
efficiency. This means that the way used to get the information is as important as the
data base design
Análisis y Uso de Frameworks de Persistencia en Java
VI
Today, Java is still a growing technology. The complicated process involved
while working with data bases has caused the release of frameworks in order to make
the task a little easier. There are different alternatives such as Hibernate, JDO, EJB or
just JDBC. The efficiency of this layer will be critical while working with data bases.
Now, one of the possible ways to take advantage with these technologies is to
manage data bases through a web application. For example, it would be useful for a
company that the employees of the different departments could consult some data bases
trough a web site. The same site would provide services to everyone using different user
profiles. Every employee would have a fast and easy access to the information required
related to his department. This could be build with J2EE (Java 2 Enterprise Edition) and
one of the alternatives to persist data.
Análisis y Uso de Frameworks de Persistencia en Java
VII
Índice
Análisis y Uso de Frameworks de Persistencia en Java
VIII
ÍNDICE
1. Introducción……………………………………………………………………...1
2. Definición del Problema…………………………………………………………3
3. Análisis de las Tecnologías……………………………………………………...6
3.1. Objetivos…………………………………………………………………7
3.2. Alternativas de Persistencia……………………………………………...9
3.2.1. Introducción…….…………………………………………………9
El Mapeo Objeto-Relacional (ORM)…………………………….9
JDBC: Componente indispensable para los ORM……………...12
3.2.2. Tecnologías basadas en el estándar………………………………15
Java Data Objects (JDO) – Definición………………………….15
Enterprise Java Beans (EJB) de Entidad – Definición………….18
3.2.3. Tecnologías Open Source: Hibernate – Definición……………...20
3.3. Funcionamiento de las Alternativas…………………………………….21
3.3.1. Tecnologías basadas en el estándar………………………………21
Java Data Objects (JDO) – Funcionamiento……………………21
Crear un Objeto…………………………………………21
Crear un Gestor de Persistencia…………………………23
Crear un Descriptor JDO para el JDOEnhancer………...30
Construir y Ejecutar la Aplicación……………………...31
El Lenguaje de Consulta JDOQL……………………….35
Enterprise Java Beans (EJB) de Entidad – Funcionamiento……37
Persistencia Manejada por el Contenedor (CMP)………37
Análisis y Uso de Frameworks de Persistencia en Java
IX
La Clase Bean…………………………………..38
Interface Home………………………………….43
Interface Remoto………………………………..46
Métodos de Retrollamada……………………….48
Persistencia Manejada por el Bean (BMP)……………..53
3.3.2. Tecnologías Open Source: Hibernate – Funcionamiento………..62
Creación del Objeto……………………………………..63
Persistencia……………………………………………...65
El Fichero de Mapeo……………………………………67
Configuración de la Base de Datos……………………..71
Construcción y Ejecución……………………………….73
3.4. Evaluación……………………………………………………………...76
JDO vs. EJB…………………………….....................................76
JDO vs. JDBC/SQL…………………………………………….77
Hibernate vs. JDO………………………………………………79
3.5. Conclusiones……………………………………………………………80
4. Diseño y Desarrollo de la Aplicación Web…………………………………….84
4.1. Objetivos………………………………………………………………..85
4.2. Descripción de la Aplicación…………………………………………...86
4.3. Requisitos funcionales………………………………………………….87
4.3.1. Actores Participantes……………………………………………87
4.3.2. Casos de uso…………………………………………………….88
Descripción detallada de los Casos de Uso……………..90
Diagramas de Casos de Uso…………………………...100
4.4. Diseño Externo………………………………………………………..103
Análisis y Uso de Frameworks de Persistencia en Java
X
4.4.1. Diseño del Interfaz del Usuario……………………………….103
Inicio…………………………………………………...103
Navegación Básica…………………………………….105
Gestión de Pacientes…………………………………...108
Gestión de Alergias……………………………………111
Gestión del Portal (Noticias y Cuentas de Usuario)…...114
Cierre de Sesión………………………………………..120
4.5. Diseño Interno…………………………………………………………121
4.5.1. JSP y Servlets………………………………………………….121
4.5.2. Diagrama de navegación………………………………………126
4.5.3. Diagramas de clases…………………………………………...127
Clases Objeto…………………………………………..128
Clases de Acceso a la Base de Datos………………….131
4.5.4. Modelo de datos……………………………………………….133
5. La alternativa a JDBC: Hibernate……………………………………………..135
5.1. Las clases a persistir…………………………………………………..136
5.2. Los ficheros de mapeo………………………………………………...147
5.3. Las clases gestoras de objetos…………………………………………152
5.4. Implantación…………………………………………………………..172
5.4.1. Instalación y Configuración…………………………………...172
5.4.2. Requisitos del Sistema………………………………………...174
6. Presupuesto……………………………………………………………………175
7. Conclusiones.………….………………………………………………………177
8. Bibliografía……………………………………………………………………180
Análisis y Uso de Frameworks de Persistencia en Java
1
1- Introducción
Análisis y Uso de Frameworks de Persistencia en Java
2
1- INTRODUCCIÓN
El fin de este proyecto es dar a conocer ciertas alternativas a JDBC a la hora de
persistir objetos Java en bases de datos relacionales, así como ver su funcionamiento en
una aplicación real. Una forma de abordar el problema es realizar un análisis de las
alternativas más importantes que están a nuestra disposición.
Conocer el funcionamiento de las diferentes alternativas da pie a enfrentarlas y a
poder comparar su servicio al problema de la persistencia. Sin embargo, cada una de las
tecnologías tiene su propio origen y filosofía para alcanzar el mismo fin y, por esta
razón, no será fácil analizar sus ventajas y desventajas frente a las demás alternativas.
Una vez terminado el análisis de las tecnologías, se procederá a diseñar una
aplicación Web que se caracterice por su necesidad de persistir objetos. Dicha
aplicación contará con diversas funciones relacionadas con los accesos a bases de datos,
especialmente la persistencia de objetos Java.
La fase final del proyecto consistirá en introducir en la aplicación una de las
tecnologías analizadas. Dicha tecnología será seleccionada por ser la más adecuada, y se
encargará de realizar la tarea de persistir objetos, sirviendo de enlace entre la lógica y la
interacción con una base de datos. La aplicación será construida en un principio con
JDBC y sentencias SQL de forma que, al introducir la tecnología, se podrá ver
claramente la gran función que es capaz de desempeñar un framework de persistencia.
Análisis y Uso de Frameworks de Persistencia en Java
3
2- Definición del Problema
Análisis y Uso de Frameworks de Persistencia en Java
4
2- DEFINICIÓN DEL PROBLEMA
La persistencia de datos en Java viene facilitada por mapeadores
Objeto/Relacionales (O/R). Estas tecnologías conforman técnicas de programación para
enlazar un lenguaje de programación orientado a objetos con una base de datos
relacional. Los mecanismos de mapeo O/R permiten al programador mantener una
perspectiva orientada a objetos y cuidar que se consiga aportar una solución a la lógica
de negocio, eliminando el obstáculo que supone compatibilizar objetos con modelos
relacionales. El framework para la persistencia de datos se ocupa de todos los detalles
que conllevaría desarrollar un mecanismo de mapeo personalizado.
Hoy en día, uno de los asuntos más debatidos y discutidos más apasionadamente
en la industria del software es: ¿cuál de las tecnologías de persistencia (o frameworks
para el mapeo Objeto/Relacional) merece ser la alternativa dominante? Esta discusión
ha creado una división en la comunidad Java. Mientras esto siga así, dicho debate
seguirá en pie y los desarrolladores de software deberán elegir la tecnología que mejor
se adapte a sus necesidades, y esto se debe extender a cualquier componente que
conforme la arquitectura del sistema completo, incluyendo el driver JDBC.
Análisis y Uso de Frameworks de Persistencia en Java
5
En la figura podemos observar la estructura básica de una aplicación Web
desarrollada con Java empleando Servlets y JSP. La lógica de la aplicación localizada
en el servidor contiene, entre otros, un módulo (representado por una estrella roja) que
será el encargado de interactuar con las bases de datos. Todas y cada una de las
consultas y modificaciones que deba realizar la aplicación sobre las bases de datos
dependerán de la implementación del módulo en cuestión. Es en esa parte de la lógica
del programa donde entran en escena los frameworks de persistencia.
Análisis y Uso de Frameworks de Persistencia en Java
6
3- Análisis de las Tecnologías
Análisis y Uso de Frameworks de Persistencia en Java
7
3- ANÁLISIS DE LAS TECNOLOGÍAS
3.1.- OBJETIVOS
• Definición de las alternativas
Es necesario conocer qué alternativas de persistencia son las más
importantes actualmente. Se pretende definir cuáles son las se van a barajar y
cuáles son sus orígenes. Se especificará cómo cada una de las alternativas está
asociada a una organización o comunidad de desarrollo, así como su filosofía.
• Descripción de su funcionamiento
Se pretende conocer el funcionamiento de cada una de las alternativas
analizadas de una forma sencilla. Para ello es necesario explicar paso a paso la
metodología a seguir para conseguir la persistencia de los objetos, mostrando
ejemplos y código fuente.
• Evaluación: Características más relevantes
Análisis y Uso de Frameworks de Persistencia en Java
8
Antes de finalizar el análisis, se pretende identificar las características
más relevantes de cada una de las alternativas estudiadas. De esta forma,
enfrentando unas con otras se dará pie a obtener conclusiones.
• Conclusiones
A continuación, se obtendrán diversas conclusiones acerca de la
información reunida en los puntos anteriores.
Por último, para dar sentido al estudio, se elegirá la alternativa de
persistencia más apropiada para suplir la codificación JDBC empleada en la
aplicación que se desarrolle a continuación, incorporándola al servidor.
Análisis y Uso de Frameworks de Persistencia en Java
9
3.2- ALTERNATIVAS DE PERSISTENCIA
3.2.1. Introducción
El Mapeo Objeto-Relacional (ORM)
Si se está trabajando con programación orientada a objetos y bases de
datos relacionales, es fácil observar que estos son dos paradigmas diferentes. El
modelo relacional trata con relaciones y conjuntos, y es muy matemático por
naturaleza. Sin embargo, el paradigma orientado a objetos trata con objetos, sus
atributos y asociaciones de unos con otros.
Tan pronto como se quieran persistir los objetos utilizando una base de
datos relacional se puede observar que hay un problema de compatibilidad entre
estos dos paradigmas, la también llamada diferencia objeto-relacional.
Un mapeador objeto-relacional (ORM) es de gran ayuda para evitar esta
diferencia. Esta diferencia se manifiesta cuando se tienen diversos objetos en
una aplicación y se alcanza el punto donde es oportuno que sean persistentes. En
este caso se debe abrir una conexión JDBC, crear una sentencia SQL y copiar
todos los valores de las propiedades de los objetos sobre la selección. Esto
Análisis y Uso de Frameworks de Persistencia en Java
10
podría ser fácil para un objeto pequeño, pero si se considera para un objeto con
muchas propiedades, la labor se convierte en un proceso incómodo.
Este no es el único problema. Las asociaciones entre objetos también hay
que tenerlas en cuenta, así como las restricciones de claves. Lo mismo se puede
aplicar para la carga. Si se asume que se carga un objeto desde la base de datos y
que tiene una colección asociada. A la hora de carga el objeto ¿se cargará
también la colección? Si se cargan también los elementos de la colección, se
considerará que cada objeto elemento tiene una asociación con todavía más
objetos. En este caso, sería mejor cargar todo el árbol de objetos.
Por tanto, la diferencia objeto-relacional se amplia muy rápidamente
cuando se está trabajando con grandes modelos de objetos. Y hay muchas más
cosas a considerar como la carga lenta, las referencias circulares, el caché, etc.
Como detalle, se han realizado estudios que demuestran que el 35% del código
de una aplicación se produce para mapear datos entre la aplicación y la base de
datos.
Para la mayoría de las aplicaciones, almacenar y recuperar información
implica alguna forma de interacción con una base de datos relacional. Esto ha
representado un problema fundamental para los desarrolladores porque algunas
veces el diseño de datos relacionales y los ejemplares orientados a objetos
Análisis y Uso de Frameworks de Persistencia en Java
11
comparten estructuras de relaciones muy diferentes dentro de sus respectivos
entornos.
Las bases de datos relacionales están estructuradas en una configuración
tabular y los ejemplares orientados a objetos normalmente están relacionados en
forma de árbol. Esta 'diferencia de impedancia' ha llevado a los desarrolladores
de varias tecnologías de persistencia de objetos a intentar construir un puente
entre el mundo relacional y el mundo orientado a objetos.
Persistir objetos Java en una base de datos relacional es un reto único que
implica serializar un árbol de objetos Java en una base de datos de estructura
tabular y viceversa. Este reto actualmente está siendo corregido por varias
herramientas diferentes. La mayoría de estas herramientas permite a los
desarrolladores instruir a los motores de persistencia de cómo convertir objetos
Java a columnas/registros de la base de datos y al revés. Esencial para este
esfuerzo es la necesidad de mapear objetos Java a columnas y registros de la
base de datos de una forma optimizada en velocidad y eficiencia.
Análisis y Uso de Frameworks de Persistencia en Java
12
JDBC: Componente indispensable para los ORM
La mayoría de las aplicaciones que son importantes en una empresa están
respaldadas por una arquitectura normalizada y optimizada de bases de datos
relacionales. Tradicionalmente, dichas aplicaciones están basadas en sentencias
SQL con las cuales se gestionan todos los datos que manejan.
Este modelo continúa teniendo una gran importancia estratégica y es la
base para el continuo crecimiento del mapeo Objeto-Relacional (O/R) y está
asociado a los mecanismos de persistencia.
El mapeo O/R es una herramienta muy útil para la programación en Java
puesto que el desarrollador se puede concentrar en la construcción de la
aplicación mientras que delega los detalles de la persistencia de datos al
framework de persistencia.
Hay múltiples alternativas para los programadores de Java cuando se
pretende trabajar con mapeadores O/R. Hay tres organizaciones o comunidades
que están implicadas en el mundo de la persistencia O/R de Java de forma
activa: organizaciones basadas en el estándar, comunidades open source y
grupos comerciales.
Las comunidades open source incluyen importantes tecnologías, entre ellas
Hibernate y el framework Spring. Las alternativas más importantes basadas en el
estándar, son EJB 3.0 y JDO. Entre las implementaciones comerciales se pueden
Análisis y Uso de Frameworks de Persistencia en Java
13
resaltar Oracle’s TopLink. Para este proyecto se analizarán las tecnologías open
souce y las basadas en el estándar.
Sin tener en cuenta el mecanismo de mapeo O/R que se vaya a utilizar
para comunicarse con la base de datos relacional, todos ellos dependen de
JDBC. Teniendo en cuenta que la mayor parte de las aplicaciones se comunican
con bases de datos relacionales, es fundamental considerar cada uno de los
niveles del software (desde el código del programa hasta la fuente de datos) para
asegurar que el diseño de persistencia O/R sea óptimo.
Tal y como se verá más adelante, cada uno de los mecanismos de mapeo
O/R tiene una dependencia particular en el driver JDBC para poder comunicarse
con la base de datos de una forma eficiente. Si el driver JDBC que va a
participar en la comunicación no es óptimo, la posible gran eficiencia de
cualquier framework quedará debilitada. Por tanto, elegir el driver JDBC que
mejor se adapte a la aplicación es esencial a la hora de construir un sistema
eficiente en el que participe un mecanismo de mapeo O/R.
Análisis y Uso de Frameworks de Persistencia en Java
14
La figura muestra una representación de los diferentes mecanismos de
mapeo O/R y cómo se relacionan con el código de la aplicación y con los
recursos de datos relacionados. Esto muestra claramente la función crítica que
desempeña el driver JDBC puesto que está situado en la base de cada uno de los
frameworks.
La eficiencia del driver JDBC tiene importantes consecuencias en el
comportamiento de las aplicaciones. Cada mecanismo de mapeo O/R es
completamente dependiente del driver, sin tener en cuenta el diseño de la API
del framework que esté expuesta al código fuente de la aplicación.
Como los mecanismos de mapeo O/R generan llamadas eficientes para
acceder a la base de datos, mucha gente defiende que la importancia del driver
JDBC se ha visto reducida. Sin embargo, como en cualquier arquitectura, la
Análisis y Uso de Frameworks de Persistencia en Java
15
totalidad de eficiencia en una aplicación siempre estará afectada por el nivel más
débil del sistema.
Independientemente del código JDBC generado, los mecanismos de
mapeo O/R son incapaces de controlar cómo los drivers interactúan con la base
de datos. Al fin y al cabo la eficiencia de la aplicación depende en gran parte de
la habilidad que tenga el driver del nivel JDBC para mover todos los datos
manejados entre la aplicación y la base de datos.
Aunque hay múltiples factores que considerar a la hora de elegir un
driver JDBC, seleccionar el mejor driver JDBC posible basándose en
comportamiento, escalabilidad y fiabilidad es la clave para obtener el máximo
beneficio de cualquier aplicación basada en un framework O/R.
3.2.2. Definición de las tecnologías basadas en el estándar
• Java Data Objects (JDO) – Definición
Java Data Objects (JDO) es una especificación desarrollada para
conseguir una persistencia de objetos Java de forma transparente. Es una API de
alto nivel que permite a las aplicaciones almacenar objetos Java en un almacén
Análisis y Uso de Frameworks de Persistencia en Java
16
de datos transaccional (ficheros y bases de datos) siguiendo unos estándares
predefinidos.
Esta API puede ser utilizada para acceder a datos en servidores o
sistemas embebidos. Además, las implementaciones de JDO pueden llegar a la
telefonía móvil, PDA y demás tecnologías wireless. Sin embargo, su función
más destacada es su capacidad para manejar como objetos cierta información
perteneciente a una base de datos relacional.
JDO ha sido creado bajo la dirección de la comunidad de Java y
documentado como una Especificación Java (JSAR 12). Craig Russell de Sun
Microsystems lideró a un grupo de expertos de varias compañías para desarrollar
la documentación.
Como con otras muchas tecnologías de Java, Sun Microsystems ha
lanzado una especificación y una referencia para la implementación. Además,
los vendedores están desarrollando productos compatibles con JDO.
La siguiente tabla muestra una lista de algunos vendedores:
Análisis y Uso de Frameworks de Persistencia en Java
17
Vendedores de JDO
Compañía Producto URL Asociada
SolarMetric Kodo JDO Enterprise Edition, Kodo
JDO Standard Edition
www.solarmetric.com
Poet Software
Corporation
FastObjects www.fastobjects.com
LiBeLIS LiDO www.libelis.com
Hemisphere
Technologies
JDO Genie www.hemtech.co.za/jdo
ObjectFrontier Inc. FrontierSuite for JDO www.objectfrontier.com
Versant Versant enJin www.versant.com
Sun Microsystems,
Inc.
Reference Implementation www.java.sun.com
Object Industries
GMBH
JRelay www.objectindustries.com
JDO ha sido diseñado para poderse incorporar fácilmente a servidores de
aplicación. Esto permite que la tecnología pueda asumir muchas funciones
ofrecidas también por las Enterprise Java Beans (EJB) de Entidad, CMP. Dicha
funcionalidad consiste en separar los objetos Java del código JDBC con sus
correspondientes sentencias SQL necesarios para acceder a las bases de datos.
Análisis y Uso de Frameworks de Persistencia en Java
18
JDO define un lenguaje de consulta conocido como JDOQL. Este
lenguaje está embebido dentro del interface javax.jdo.Query.
• Enterprise Java Beans (EJB) de Entidad – Definición
El bean de entidad es uno de los dos tipos de beans primarios: entidad y
sesión. El bean de entidad es usado para representar datos en una base de datos.
Proporciona un interface orientado a objetos a los datos que normalmente serían
accedidos mediante el JDBC u otro API. Más que eso, los beans de entidad
proporcionan un modelo de componentes que permite a los desarrolladores de
beans enfocar su atención en la lógica de negocio del bean, mientras el
contenedor tiene cuidado de manejar la persistencia, las transacciones, y el
control de accesos.
El objetivo de los EJB de entidad es encapsular los objetos de lado del
servidor que almacena los datos. Los EJBs de entidad presentan la característica
fundamental de la persistencia:
Análisis y Uso de Frameworks de Persistencia en Java
19
* Persistencia gestionada por el contenedor (CMP): el contenedor se
encarga de almacenar y recuperar los datos del objeto de entidad mediante un
mapeado en una tabla de una base de datos.
* Persistencia gestionada por el bean (BMP): el propio objeto entidad
se encarga, mediante una base de datos u otro mecanismo, de almacenar y
recuperar los datos a los que se refiere, por lo cual, la responsabilidad de
implementar los mecanismos de persistencia es del programador.
Con CMP, el contenedor maneja la persistencia del bean de entidad. Las
herramientas de los vendedores se usan para mapear los campos de entidad a la
base de datos y no se escribe ningún código de acceso a las bases de datos en la
clase del bean. Con BMP, el bean de entidad contiene código de acceso a la base
de datos (normalmente JDBC) y es responsable de leer y escribir en la base de
datos su propio estado. Las entidades CMP tienen mucha ayuda ya que el
contenedor alertará al bean siempre que sea necesario hacer una actualización o
leer su estado desde la base de datos. El contenedor también puede manejar
cualquier bloqueo o transacción, para que la base de datos se mantenga íntegra.
Análisis y Uso de Frameworks de Persistencia en Java
20
3.2.3. Tecnologías Open Source: Hibernate - Definición
Hibernate es un marco de trabajo de mapeo O/R Open Source que
evita la necesidad de utilizar el API JDBC. Hibernate soporta la mayoría de los
sistemas de bases de datos SQL. El Hibernate Query Language, diseñado como
una extensión mínima, orientada a objetos, de SQL, proporciona un puente
elegante entre los mundos objeto y relacional. Además, ofrece facilidades para
recuperación y actualización de datos, control de transacciones, repositorios de
conexiones a bases de datos, consultas programáticas y declarativas, y un control
de relaciones de entidades declarativas.
Hibernate es un servicio de alto rendimiento para la persistencia O/R.
Permite desarrollar clases que se pueden persistir y que son acordes con la
programación orientada a objetos, incluyendo asociación, herencia,
polimorfismo, composición y colecciones. Hibernate dispone de si propio
lenguaje llamado HQL, que ofrece portabilidad a SQL.
Hibernate es un proyecto profesional Open Source y un componente
crítico del catálogo de productos de JBoss Enterprise Middleware System
(JEMS). JBoss es una división de Red Hat, y ofrece servicios de mantenimiento,
consulta y entrenamiento para asistir a sus usuarios.
Análisis y Uso de Frameworks de Persistencia en Java
21
3.3- FUNCIONAMIENTO
3.3.1. Tecnologías basadas en el estándar
• Java Data Objects (JDO) - Funcionamiento
Para comprender el funcionamiento de JDO se pretende describir los
diversos pasos a seguir para construir una aplicación que permita realizar el
proceso de persistencia. Primero, se creará un objeto Persona (Person) para
persistirlo en la base de datos. A continuación, se creará el objeto
PersistePersona (PersistPerson) que será el encargado de gestionar el objeto
persona en la base de datos. Después se construirá un descriptor JDO para
decirle al JDOEnhancer qué es lo que deseamos persistir. Por último se verá qué
pasos se deben seguir para construir y ejecutar el sistema.
OBJETO:
Creación del objeto Persona (Person.java)
El objeto ‘Person’ incluye los métodos “getters” y “setters” para sus
atributos, tal y como es conveniente para cualquier clase de Java. Los únicos
requisitos para que una clase se pueda persistir son:
Análisis y Uso de Frameworks de Persistencia en Java
22
1. Sus atributos deben ser accesibles para las clases JDO (“public” o métodos
“setters”).
2. Los tipos de datos de los atributos deben estar permitidos por la JDO
specification.
3. Ciertos a tributos no son admitidos (por ejemplo, Thread, File o Socket, que
no son “serializable”.
Teniendo en cuenta los requisitos, la clase ‘Person.java’ podría tener este
Paso 2º: Persistir tres personas en la base de datos
El método ‘persistPeople()’ crea a tres personas, usando el constructor
que aparece en ‘Person.java’. Lo primero que ha de hacerse es conseguir un
gestor de persistencia a través del método ‘getPersistenceManager()’. Después
se ha de crear una transacción donde se hará la operación. Para persistir el array
de personas llamamos al método ‘makePersistentAll()’ sobre el “Persistence
Análisis y Uso de Frameworks de Persistencia en Java
26
Manager” (pm). El bucle for{}sirve para obtener un identificador por cada
persona persistida, guardándolos para usarlos en el futuro.
public void persistPeople() { // CREACION DEL ARRAY DE PERSONAS people = new Person[SIZE]; // CREACION DE TRES PERSONAS (FUTBOLISTAS INGLESES) people[0] = new Person("Gary Segal", "123 Foobar Lane", "123-123-1234", "[email protected]", "(608) 294-0192", "(608) 029-4059"); people[1] = new Person("Michael Owen", "222 Bazza Lane, Liverpool, MN", "111-222-3333", "[email protected]", "(720) 111-2222", "(303) 222-3333"); people[2] = new Person("Roy Keane", "222 Trafford Ave, Manchester, MN", "234-235-3830", "[email protected]", "(720) 940-9049", "(303) 309-7599)"); // PERSISTENCIA DEL ARRAY DE PERSONAS pm = pmf.getPersistenceManager(); transaction = pm.currentTransaction(); pm.makePersistentAll(people); transaction.commit(); // OBTENCION DE LOS IDENTIFICADORES for(int i = 0; i < people.length; i++) { id.add(pm.getObjectId(people[i])); } // CLAUSURA DEL GESTOR DE PERSISTENCIA // AHORA LOS OBJETOS SE LEERAN DE LA BASE DE DATOS pm.close(); }
He aquí algunos otros métodos que se pueden usar sobre el gestor de
persistencia. Hay tres categorías:
• Hace Instancias Persistentes. Persiste un objeto transitorio.
• Elimina Instancias Persistidas. Elimina información de la base de datos.
Análisis y Uso de Frameworks de Persistencia en Java
27
• Hace Instancias Transitorias. Rompe la asociación de las instancias con el
gestor de persistencia. Sin embargo, la base de datos mantiene la información.
Hace Instancia Persitente Elimina Instancia Persistida Hace Instancia Transitoria makePersistent(Object o)
deletePersistent(Object o)
makeTransient(Object o)
makePersistentAll(Object[] os)
deletePersistentAll(Object[] os)
makeTransientAll(Object[] os)
makePersistentAll(Collection os)
deletePersistentAll(Collection os)
makeTransientAll(Collection os)
Paso 3º: Mostrar el contenido de la base de datos
El código para mostrar el contenido de la base de datos comienza por
obtener el gestor de persistencia (‘getPersistenceManager()’). Para mostrar las
personas creadas anteriormente, es necesario obtener los identificadores
guardados a través del método ‘persistPeople()’. Una vez devueltos los objetos,
se puede ejecutar los métodos que tienen definidos, en este caso los Getters:
public void display(int end) { Person person; int max = end <= SIZE ? end : SIZE; // OBTENCION DEL GESTOR DE PERSISTENCIA pm = pmf.getPersistenceManager(); // OBTENCION DE LAS PERSONAS for(int i = 0; i < max; i++) { person = (Person) pm.getObjectById(id.elementAt(i), false); System.out.println("Name : " + person.getName()); System.out.println("Address : " + person.getAddress()); System.out.println("SSN : " + person.getSsn()); System.out.println("Email : " + person.getEmail());
Análisis y Uso de Frameworks de Persistencia en Java
Paso 6º: Realizar las operaciones desde el método ‘main ( )’
Por último, el programa que contiene todo el código anterior, tiene un
método ‘main ( )’ donde se crea la gente, se modifica y se borra.
public static void main(String[] args) { System.out.println("Create PersonPersist"); PersonPersist personPersist = new PersonPersist();
Análisis y Uso de Frameworks de Persistencia en Java
30
System.out.println("Setup and persist a group of people"); personPersist.persistPeople(); System.out.println("Display the persisted people"); personPersist.display(SIZE); System.out.println("Change a name "); personPersist.change(); personPersist.display(SIZE); System.out.println("Delete a person "); personPersist.delete(); personPersist.display(SIZE - 1); }
JDOEnhancer:
Crear un JDO Descriptor para el JDOEnhancer
Ahora se ha codificado toda la aplicación. El siguiente paso a seguir es crear un
“JDO Descriptor” que usará el JDOEnhancer.
¿Qué es el JDOEnhancer? La arquitectura JDO está construida con la idea de
que una implementación JDO puede “mejorar” el bytecode de las clases a persistir
manipulándolas, con el fin de añadir funcionalidades necesarias para los objetos. Por
ejemplo, el JDOEnhancer hará que el interface ‘PersistanceCapable’ esté implementado
en la clase (tarea que ahorra al codificador), así como algunos de los métodos del
interface. Por tanto, después de compilar el código, se deberá ejecutar el JDOEnhancer
para que realice las manipulaciones oportunas.
Es necesario crear un fichero “Descriptor” para darle al “Enhancer” la
información sobre las clases que se desean persistir. He aquí el descriptor:
Análisis y Uso de Frameworks de Persistencia en Java
Estos son los pasos a seguir para construir el sistema que permitirá
ejecutar la aplicación:
1. Compilar el Código
Análisis y Uso de Frameworks de Persistencia en Java
32
2. Ejecutar en JDOEnhancer
3. Preparar la base de datos (utilizando la salida del Enhancer)
4. Ejecutar la aplicación
Paso 1º: Compilar el código
La compilación se realizará como en cualquier código Java, usando
‘javac’. Por otra parte, es necesario asignar el ‘CLASSPATH’ correctamente. He
aquí un ejemplo en Windows:
% set OPENFUSION_DIR=D:\Apps\OpenFusionJDO % set CLASSPATH=%OPENFUSION_DIR%\lib\connector.jar;%OPENFUSION_DIR%\ lib\jndi.jar;%OPENFUSION_DIR%\lib\log4j.jar;%OPENFUSION_DIR%\l ib\xerces.jar;%OPENFUSION_DIR%\lib\classes12.zip;%OPENFUSION_D IR%\lib\jdo.jar;%OPENFUSION_DIR%\lib\jta- spec1_0_1.jar;%OPENFUSION_DIR%\lib\ofjdo.jar;. % javac –d . Person*.java
Paso 2º: Ejecutar el JDOEnhancer
El JDOEnhancer toma por un lado el código compilado y por otro el
fichero descriptor. Esta es la sintaxis completa del OpenFusion JDOEnhancer:
java com.prismt.j2ee.jdo.enhancer.JDOEnhancer Mandatory Options: -cp base directory to begin searching for classes to be enhanced. This is not the CLASSPATH, just where our compiled persistent classes are
Análisis y Uso de Frameworks de Persistencia en Java
33
-oc directory to place the enhanced classes -pd JDO descriptor file(s) Optional: -db specific target database [oracle, sybase, etc] -od directory to generate SQL scripts to
Para la aplicación compilada en el ejemplo, he aquí cómo se ejecutaría el
El interface ‘Query’ también proporciona un método para declarar un grupo arbitrario
de parámetros separados por comas:
• void declareParameters(String paramStr);
Este grupo de parámetros debe formatearse como una definición ‘String’ de las parejas
tipo-nombre. Por ejemplo, el siguiente fragmento ilustra un grupo de parámetros para
un nombre y una cuenta de usuario:
query.declareParameters("String userName, int accountNumber");
Análisis y Uso de Frameworks de Persistencia en Java
37
El siguiente código muestra una consulta completa utilizando JDOQL:
String filter = "userInfo.fullName == fullName && " + "userInfo.zip.startsWith(userZip)"; Extent extent = persistenceMgr.getExtent(UserInfo.class, true); Query query = persistenceMgr.newQuery(extent, filter); query.declareParameters("String city, String state"); Collection result = (Collection)query.execute("Shire", "New York"); Iterator iter = result.iterator(); while(iter.hasNext()) { UserInfo user = (UserInfo)iter.next(); System.out.println("User: " + user.getID()); }
• Entity Java Beans (EJB) de Entidad – Funcionamiento
PERSISTENCIA MANEJADA POR CONTENEDOR (CMP)
Los beans con persistencia manejada por contenedor son los más simples
para el desarrollador y los más complicados para que los soporte el servidor
EJB. Esto es porque toda la lógica de sincronización del estado del bean con la
base de datos es manejada automáticamente por el contenedor. Esto significa
que el desarrollador del bean no necesita escribir ninguna lógica de acceso a
datos, mientras que se supone que el servidor EJB tiene cuidado de toda la
persistencia que necesita automáticamente. La mayoría de los vendedores EJB
soportan la persistencia automática a una base de datos relacional, pero el nivel
Análisis y Uso de Frameworks de Persistencia en Java
38
de soporte varía. Algunos proporcionan un mapeo O/R muy sofisticado,
mientras que otros están muy limitados.
La clase Bean
Un bean enterprise es un componente completo que está compuesto de al
menos dos interfaces y una clase de implementación del bean.
import javax.ejb.EntityBean; public class CustomerBean implements EntityBean { int customerID; Address myAddress; Name myName; CreditCard myCreditCard; // CREATION METHODS public Integer ejbCreate(Integer id) { customerID = id.intValue(); return null; } public void ejbPostCreate(Integer id) { } public Customer ejbCreate(Integer id, Name name) { myName = name; return ejbCreate(id); } public void ejbPostCreate(Integer id, Name name) { } // BUSINESS METHODS public Name getName() { return myName; } public void setName(Name name) { myName = name; } public Address getAddress() { return myAddress; }
Análisis y Uso de Frameworks de Persistencia en Java
39
public void setAddress(Address address) { myAddress = address; } public CreditCard getCreditCard() { return myCreditCard; } public void setCreditCard(CreditCard card) { myCreditCard = card; } // CALLBACK METHODS public void setEntityContext(EntityContext cntx) { } public void unsetEntityContext() { } public void ejbLoad() { } public void ejbStore() { } public void ejbActivate() { } public void ejbPassivate() { } public void ejbRemove() { } }
Este es un buen ejemplo de un bean de entidad CMP bastante simple. Se
puede observar que no hay lógica de acceso a base de datos en el bean. Esto es
porque el vendedor del EJB proporciona herramientas para mapear los campos
del CustomerBean a la base de datos. La clase CustomerBean, por ejemplo,
podría ser mapeada a cualquier base de datos proporcionando los datos que
contienen y que son muy similares a los campos del bean. En este caso lo
campos de ejemplar del bean están comprendidos por un int y unos sencillos
Análisis y Uso de Frameworks de Persistencia en Java
40
objetos dependientes (Name, Address, y CreditCard) con sus propios atributos.
He aquí las definiciones de estos objetos dependientes.
// The Name class public class Name implements Serializable { public String lastName, firstName, middleName; public Name(String lastName, String firstName, String middleName) { this.lastName = lastName; this.firstName = firstName; this.middleName = middleName; } public Name() {} } // The Address class public class Address implements Serializable { public String street, city, state, zip; public Address(String street, String city, String state, String zip) { this.street = street; this.city = city; this.state = state; this.zip = zip; } public Address() {} } // The CreditCard class public class CreditCard implements Serializable { public String number, type, name; public Date expDate; public CreditCard(String number, String type, String name, Date expDate) { this.number = number; this.type = type; this.name = name; this.expDate = expDate;
Análisis y Uso de Frameworks de Persistencia en Java
41
} public CreditCard() {} }
Estos campos se llaman campos manejados por contenedor porque el
contenedor es el responsable de sincronizar su estado con la base de datos; el
contenedor maneja los campos. Estos campos pueden ser cualquier tipo de dato
primitivo o tipo serializable. Este caso usa tanto un tipo primitivo int
(customerID) y objetos serializables (Address, Name, CreditCard). Para mapear
los objetos dependientes a la base de datos necesitaríamos usar una herramienta
de mapeado muy sofisticada. No todos los campos del bean son
automáticamente campos manejados por el contenedor; algunos de ellos son sólo
campos de ejemplar para el uso temporal del bean. Un desarrollador de beans
distingue un campo manejado por contenedor de un campo de ejemplar normal
indicando los campos manejados por el contenedor en el descriptor de
desarrollo.
Los campos manejados por contenedor deben tener sus tipos
correspondientes (columnas en RDBMS) en la base de datos bien directamente o
a través de mapeo O/R. El CustomerBean podría, por ejemplo, mapear una tabla
CUSTOMER en la base de datos que tenga la siguiente definición.
CREATE TABLE CUSTOMER
Análisis y Uso de Frameworks de Persistencia en Java
42
{ id INTEGER PRIMARY KEY, last_name CHAR(30), first_name CHAR(20), middle_name CHAR(20), street CHAR(50), city CHAR(20), state CHAR(2), zip CHAR(9), credit_number CHAR(20), credit_date DATE, credit_name CHAR(20), credit_type CHAR(10) }
Con la persistencia controlada por contenedor, el vendedor debe tener
alguna clase de herramienta propietaria que pueda mapear los datos manejados
por el contenedor del bean a sus correspondientes columnas en la tabla
específica, CUSTOMER en este caso.
Una vez que los campos del bean se han mapeado a la base de datos, y se
ha desarrollado el bean CustomerBean, el contenedor manejará la creacción de
registros, el borrado, la carga y la actualización de registros en la tabla
CUSTOMER en respuesta a los métodos invocados en los interfaces home y
remoto del bean Customer.
Un subconjunto (uno o más) de los campos manejados por el contenedor
será identificado como la clave primaria del bean. Esta clave primaria es el
índice o puntero a un único registro(s) en la base de datos que crea el estado del
bean. En el caso de CustomerBean, el campo id es el campo clave primario y
Análisis y Uso de Frameworks de Persistencia en Java
43
será usado para localizar los datos de los beans en la base de datos. Los campos
clave de un campo sencillo primitivo se representan como su correspondiente
objeto envoltura. La clave primaria del bean CustomerBean por ejemplo es un
int primitivo en la clase bean pero los clientes del bean la manifestarán como del
tipo java.lang.Integer. Las claves primarias que se componen de varios campos,
llamadas claves primarias compuestas, serán representadas por un clase especial
definida por el desarrollador del Bean.
Interface Home
Para crear un nuevo ejemplar de un bean de entidad CMP, y por lo tanto
insertar los datos en la base de datos, se debe llamar al método create() del
interface home del bean. He aquí la definición del interface ‘CustomerHome’.
public interface CustomerHome extends javax.ejb.EJBHome { public Customer create( Integer customerNumber) throws RemoteException,CreateException; public Customer create(Integer customerNumber, Name name) throws RemoteException,CreateException; public Customer findByPrimaryKey(Integer customerNumber) throws RemoteException, FinderException; public Enumeration findByZipCode(int zipCode) throws RemoteException, FinderException; }
Análisis y Uso de Frameworks de Persistencia en Java
44
A continuación está un ejemplo de cómo se usaría el interface ‘home’ en
una aplicación cliente para crear un nuevo cliente.
CustomerHome home = // Get a reference to the //CustomerHome object Name name = new Name("John", "W", "Smith"); Customer customer = home.create( new Integer(33), name);
Un interface ‘home’ de un bean podría declarar cero o más métodos
create(), cada uno de los cuales debe tener sus correspondientes métodos
ejbCreate() y ejbPostCreate() en la clase del bean. Estos métodos de creación
son enlazados en tiempo de ejecución, para que cuando se llame a un método
create() del interface ‘home’, el contenedor delegue la invocación a los
correspondientes métodos ejbCreate() y ejbPostCreate() de la clase Bean.
Cuando se invoca al método create() de un interface ‘home’, el
contenedor delega esta llamada al correspondiente método ejbCreate() en el
bean. Estos métodos se usan para inicializar el estado del ejemplar antes de que
el registro sea insertado en la base de datos. En este caso, inicializa los campos
customerID y Name. Cuando el método ejbCreate() ha finalizado (devuelven
null en CMP) el contenedor lee los campos manejados por el contenedor e
inserta un nuevo registro en la tabla CUSTOMER indexado por la clave
primaria, en este caso customerID que se mapea a la columna CUSOTMER.ID.
Análisis y Uso de Frameworks de Persistencia en Java
45
En EJB un bean de entidad no existe técnicamente hasta después de que
sus datos hayan sido insertados en la base de datos, lo que ocurre durante el
método ejbCreate(). Una vez que los datos han sido insertados, el bean de
entidad existe y puede acceder a su propia clave primaria y a referencias
remotas, lo que no es posible hasta que se complete el método ejbCreate() y que
los datos estén en la base de datos. Si el bean necesita acceder a su propia clave
primaria o a una referencia remota después de haber sido creado, pero antes de
servir a cualquier método de negocio, puede hacerlo en el método
ejbPostCreate(). Este método permite al bean realizar cualquier proceso post-
creacción antes de empezar a servir peticiones de clientes. Por cada ejbCreate()
debe haber un método ejbPostCreate() correspondiente (con los mismos
argumentos).
Los métodos del interface ‘home’ que empiezan con "find" son llamados
métodos de búsqueda. Se usan para consultar al servidor EJB sobre beans de
entidad específicos, basándose en el nombre del método y los argumentos
pasados. Desafortunadamente, no hay un lenguaje de consultas estándard
definido para los métodos de búsqueda, por eso cada vendedor implementará
estos métodos de forma diferente. En los beans de entidad CMP, los métodos de
búsqueda no están implementados con los métodos correspondientes en la clase
del bean; los contenedores los implementan cuando el bean se desarrolla de una
forma específica del vendedor. El desarrollador usará las herramientas
Análisis y Uso de Frameworks de Persistencia en Java
46
específicas del vendedor para decirle al contenedor cómo se debería comportar
un método de búsqueda particular. Algunos vendedores usaran herramientas de
mapeo Objeto-Relacional para definir el comportamiento de un método de
búsqueda mientras que otros sólo requerirán que el desarrollador introduzca el
comando SQL apropiado.
Interface Remoto
Cada bean de entidad debe definir una interface remoto en adición del
interface ‘home’. El interface remoto define los métodos de negocio del bean de
entidad. A continuación está la definición del interface remoto del bean
CustomerBean.
import javax.ejb.EJBObject; import java.rmi.RemoteException; public interface Customer extends EJBObject { public Name getName() throws RemoteException; public void setName(Name name) throws RemoteException; public Address getAddress() throws RemoteException; public void setAddress( Address address) throws RemoteException; public CreditCard getCreditCard() throws RemoteException; public void setCreditCard(CreditCard card) throws RemoteException; }
Análisis y Uso de Frameworks de Persistencia en Java
47
Este es un ejemplo de cómo una aplicación cliente podría usar el
interface remoto para interactuar con un bean.
Customer customer = // ... obtain a remote //reference to the bean // get the customer's address Address addr = customer.getAddress(); // change the zip code addr.zip = "56777"; // update the customer's address customer.setAddress(addr);
Los métodos de negocio en el interface remoto se delegan a los
correspondientes métodos de negocio en el ejemplar del bean. En el bean
Customer, los métodos de negocios son todos simples accesores y
modificadores, pero podrían ser más complicados. En otras palabras, los
métodos de negicio de una entidad no están limitados a leer y escribir datos,
también pueden realizar tareas de cálculo.
Si, por ejemplo, los clientes tuvieran un programa de fidelidad que
premiara el uso frecuente, podría haber un método para mejorar los premios en
el programa, basado en una acumulación de estancias superiores a una noche.
import javax.ejb.EJBObject; import java.rmi.RemoteException; public interface Customer extends EJBObject { public MembershipLevel addNights(int nights_stayed) throws RemoteException;
Análisis y Uso de Frameworks de Persistencia en Java
48
public MembershipLevel upgradeMembership() throws RemoteException; public MembershipLevel getMembershipLevel() throws RemoteException; ... Simple accessor business methods go here }
Los métodos addNights() y upgradeMembership() son más sofisticados
que los sencillos métodos accesores. Aplican reglas de negocio para cambiar el
nivel del premio y van más allá de leer y escribir datos.
Métodos de RetroLlamada (CallBack Methods)
La clase bean define métodos create que corresponden con métodos del
interface home y métodos de negocio que corresponden con métodos del
interface remoto. La clase bean también implementa un conjunto de métodos
callback que permiten al contenedor notificar al bean los eventos de su ciclo de
vida. Los métodos de retrollamada están definidos en el interface
javax.ejb.EntityBean que es implementado por todos los beans de entidad,
incluyendo la clase CustomerBean. El interface EntityBean tiene la siguiente
definición. Se puede observar que la clase del bean implementa estos métodos.
public interface javax.ejb.EntityBean { public void setEntityContext(); public void unsetEntityContext(); public void ejbLoad(); public void ejbStore();
Análisis y Uso de Frameworks de Persistencia en Java
49
public void ejbActivate(); public void ejbPassivate(); public void ejbRemove(); }
El método setEntityContext() proporciona al bean un interface con el
contenedor llamado el EntityContext. Este interface contiene métodos para
obtener información sobre el contexto bajo el que opera el bean en un momento
particular. El interface EntityContext se usa para acceder a información de
seguridad sobre su llamador; para determinar el estado de la transación actual o
para forzar a deshacer una transación; o para obtener una referencia al propio
bean, su interface home o su clave primaria. Este interface sólo se configura una
vez en la vida de un ejemplar de bean de entidad, por eso su referencia debería
ponerse en uno de los campos de ejemplar del bean si la vamos a necesitar más
tarde.
El bean Customer de arriba no usa EntityContext, pero podría hacerlo.
Por ejemplo, podría usarlo para validad al llamador en un rol de seguridad
particular. Abajo tenemos un ejemplo, donde se usa el EntityContext para
validad que el llamador es un Manager, el único rol (indentidad de seguridad)
que puede seleccionar el tipo de la tarjeta de crédito de un cliente para que sea
una tarjeta mundial, no una tarjeta limitada. (A los clientes con esta tarjeta se le
ofrecen servicios especiales).
Análisis y Uso de Frameworks de Persistencia en Java
50
import javax.ejb.EntityBean; public class CustomerBean implements EntityBean { int customerID; Address myAddress; Name myName; CreditCard myCreditCard; EntityContext ejbContext; // CALLBACK METHODS public void setEntityContext( EntityContext cntx) { ejbContext = cntx } public void unsetEntityContext() { ejbContext = null; } // BUSINESS METHODS public void setCreditCard(CreditCard card) { if (card.type.equals("WorldWide")) if (ejbContext.isCallerInRole( "Manager")) myCreditCard = card; else throw new SecurityException(); else myCreditCard = card; } public CreditCard getCreditCard() { return myCreditCard; } ... }
El método unsetEntityContext() se usa al final del ciclo de vida del bean -
- antes de que el ejemplar sea sacado de la memoria -- para quitar la refencia del
EntityContext y realizar cualquier pequeña tarea de limpieza.
Análisis y Uso de Frameworks de Persistencia en Java
51
Los métodos ejbLoad() y ejbStore() en entidades CMP se invocan
cuando el estado del bean de entidad está siendo sincronizado con la base de
datos. El ejbLoad() se invoca justo después de que el contenedor haya refrescado
los campos del bean manejados por contenedor con su estado desde la base de
datos. El método ejbStore() se invoca justo antes de que el contenedor escriba
los campos del bean manejados por contenedor en la base de datos. Estos
métodos se usan para modificar datos que están siendo sincronizados. Los
métodos podrían usarse, por ejemplo, para comprimir los datos antes de
almacenarlos y descomprimirlos cuando son recuperados de la base de datos.
En el bean Customer los métodos ejbLoad() y ejbStore() podrían usarse
para converitir objetos dependientes (Name, Address, CreditCard) a sencillos
objetos String y tipos primitivos, si el contenedor EJB no es lo suficientemente
sofisticado para mapear los objetos dependientes a la tabla CUSTOMER. Abajo
tenemos un ejemplo de como se podría modificar el Bean.
import javax.ejb.EntityBean; public class CustomerBean implements EntityBean { //container-managed fields int customerID; String lastName; String firstName; String middleName; ... // not-container-managed fields Name myName; Address myAddress; CreditCard myCreditCard; // BUSINESS METHODS
Análisis y Uso de Frameworks de Persistencia en Java
52
public Name getName() { return myName; } public void setName(Name name) { myName = name; } ... public void ejbLoad() { if (myName == null) myName = new Name(); myName.lastName = lastName; myName.firstName = firstName; myName.middleName = middleName; ... } public void ejbStore() { lastName = myName.lastName; firstName = myName.firstName; middleName = myName.middleName; ... } }
Los métodos ejbPassivate() y ejbActivate() se invocan sobre el bean justo
antes de que el bean sea "pasivizado" o justo después de que se activado,
respectivamente. "Pasivizado" en un bean de entidad significa que el ejemplar
del bean ha sido des-asociado con su referencia remota para que el contenedor
pueda eliminarlo de la memoria o reutilizarlo. Es una medida de conservación de
recursos que emplea el contenedor para reducir el número de ejemplares en
memoria. Un bean podría ser "pasivizado" si no ha sido utilizado durante un
tiempo o como una operación normal realizada por el contenedor para
maximizar la reutilización del los recursos. Algunos contenedores eliminarán los
beans de la memoria, mientras que otros reutilizarán ejemplares para otros
interfaces remotos más activos. Los métodos ejbPassivate() y ejbActivate()
Análisis y Uso de Frameworks de Persistencia en Java
53
proporcionan al bean una notificación cuando está apunto de ser "pasivizado"
(des-asociado con la referencia remota) o activado (asociado con un referencia
remota).
PERSISTENCIA CONTROLADA POR EL BEAN (BMP)
En un bean enterprise con la persistencia manejada por el Bean (BMP)
maneja la sincronización de su estado con la base de datos directamente. El Bean
usa el API de bases de datos (normalmente JDBC) para leer y escribir sus
campos en la base de datos, pero el contenedor le dice cuando hacer cada
operación de sincronización y maneja las transacciones por el bean
automáticamente. La persistencia manejada por el bean le da al desarrollador de
bean la flexibilidad de realizar operaciones de persistencia que son demasiado
complicadas para el contenedor o para usar una fuente de datos que no está
soportada por el contenedor -- por ejemplo bases de datos legales y
personalizadas.
En esta sección, modificaremos la clase CustomerBean para crear un
bean con persistencia manejada por el Bean (BMP). Esta modificación no
impactará en absoluto en los interfaces home o remoto. De hecho, no
modificaremos directamente el CustomerBean original. En su lugar, lo
Análisis y Uso de Frameworks de Persistencia en Java
54
cambiaremos a persistencia manejada por el bean extendiendo el bean y
sobreescribiendo la clase para crear una entidad BMP. En la mayoría de los
casos, no extenderemos el bean para hacerlo BMP, sólo implementaremos el
bean como BMP directamente. Esta estrategia (extender el bean CMP) se hace
por dos razones: permite al bean ser un bean CMP o BMP; y acorta
significativamente la cantidad de código a mostrar. Abajo tenemos la definición
de la clase BMP.
public class CustomerBean_BMP extends CustomerBean { public void ejbLoad() { // override implementation } public void ejbStore() { // override implementation } public void ejbCreate() { // override implementation } public void ejbRemove() { // override implementation } private Connection getConnection() { // new helper method } }
Con beans BMP, los métodos ejbLoad() y ejbStore() los usa el
contenedor de forma diferente a como lo hacía con un bean CMP. En BMP,
estos métodos contienen código para leer los datos de la base de datos y para
escribir los cambios en la base de datos, respectivamente. Estos métodos se
llaman sobre el bean cuando el servidor EJB decide que es un buen momento
para leer o escribir los datos.
Análisis y Uso de Frameworks de Persistencia en Java
55
El bean CustomerBean_BMP maneja su propia persistencia. En otras
palabras, los métodos ejbLoad() y ejbStore() deben incluir lógica de acceso a
base de datos para que el bean pueda cargar y almacenar sus datos cuando el
contenedor EJB se lo diga. El contenedor ejecutará automátiamente los métodos
ejbLoad() y ejbStore() cuando crea apropiado.
El método ejbLoad() se invoca normalmente al principio de una
transación, justo antes de que el contenedor delege un método de negocio del
bean. El código mostrado abajo muestra cómo implementar el método ejbLoad()
usando JDBC.
import java.sql.Connection; public class CustomerBean_BMP extends CustomerBean { public void ejbLoad() { Connection con; try { Integer primaryKey = (Integer)ejbContext.getPrimaryKey(); con = this.getConnection(); Statement sqlStmt = con.createStatement("SELECT * FROM Customer " + " WHERE customerID = " + primaryKey.intValue()); ResultSet results = sqlStmt.executeQuery(); if (results.next()) { // get the name information //from the customer table myName = new Name(); myName.first = results.getString(" FIRST_NAME"); myName.last = results.getString(" LAST_NAME"); myName.middle = results.getString(" MIDDLE_NAME"); // get the address information from //the customer table myAddress = new Address(); myAddress.street =
Análisis y Uso de Frameworks de Persistencia en Java
56
results.getString("STREET"); myAddress.city = results.getString("CITY"); myAddress.state = results.getString("STATE"); myAddress.zip = results.getInt("ZIP"); // get the credit card information //from the customer table myCreditCard = new CreditCard(); myCreditCard.number = results.getString("CREDIT_NUMBER"); myCreditCard.expDate = results.getString("CREDIT_DATE"); myCreditCard.type = results.getString("CREDIT_TYPE"); myAddress.name = results.getInt("CREDIT_NAME"); } } catch (SQLException sqle) { throw new EJBException(sqle); } finally { if (con!=null) con.close(); } } }
El método ejbLoad(), usa la referencia ejbContext() hacia el
EntityContext del bean para obtener la clave primaria del ejemplar. Esto asegura
que usamos el índice correcto en la base de datos. Obviamente, el
CustomerBean_BMP necesitará usar los métodos heredados setEntityContext() y
unsetEntityContext().
El método ejbStore() es invocado sobre el bean, al final de la transación,
justo antes de que el contenedor intente enviar todos los cambios a la base de
datos.
import java.sql.Connection; public class CustomerBean_BMP extends CustomerBean {
Análisis y Uso de Frameworks de Persistencia en Java
57
public void ejbLoad() { ... read data from database } public void ejbStore() { Connection con; try { Integer primaryKey = (Integer)ejbContext.getPrimaryKey(); con = this.getConnection(); PreparedStatement sqlPrep = con.prepareStatement( "UPDATE customer set " + "last_name = ?, first_name = ?, middle_name = ?, " + "street = ?, city = ?, state = ?, zip = ?, " + "card_number = ?, card_date = ?, " + "card_name = ?, card_name = ?, " + "WHERE id = ?" ); sqlPrep.setString(1,myName.last); sqlPrep.setString(2,myName.first); sqlPrep.setString(3,myName.middle); sqlPrep.setString(4,myAddress.street); sqlPrep.setString(5,myAddress.city); sqlPrep.setString(6,myAddress.state); sqlPrep.setString(7,myAddress.zip); sqlPrep.setInt(8, myCreditCard.number); sqlPrep.setString(9, myCreditCard.expDate); sqlPrep.setString(10, myCreditCard.type); sqlPrep.setString(11, myCreditCard.name); sqlPrep.setInt(12,primaryKey.intValue()); sqlPrep.executeUpdate(); } catch (SQLException sqle) { throw new EJBException(sqle); } finally { if (con!=null) con.close(); } } }
En ambos métodos ejbLoad() y ejbStore() el bean sincroniza su propio
estado con la base de datos usando JDBC. El código muestra que el bean obtiene
sus conexiones a la base de datos desde una invocación misteriosa al método
this.getConnection(). Un método todavía no implementado. El método
getConnection() no es un método estándard EJB, sólo una ayuda privada
Análisis y Uso de Frameworks de Persistencia en Java
58
implementada para ocultar los mecanismos de obtención de conexiones a bases
de datos. Este es del método getConnection().
import java.sql.Connection; public class CustomerBean_BMP extends CustomerBean { public void ejbLoad() { ... read data from database } public void ejbStore() { ... write data to database } private Connection getConnection() throws SQLException { InitialContext jndiContext = new InitialContext(); DataSource source = (DataSource) jndiContext.lookup(" java:comp/env/jdbc/myDatabase"); return source.getConnection(); } }
Las conexiones a bases de datos se obtienen desde el contenedor usando
un contexto JNDI por defecto llamado "JNDI Environment Naming Context"
(ENC). El ENC proporciona acceso a almacenes de conexiones JDBC
transaccionales a través de la factoría de conexiones estándar, del tipo
javax.sql.DataSource.
En BMP, los métodos ejbLoad() y ejbStore() los invoca el contenedor
para sincronizar el ejemplar del bean con los datos en la base de datos. Para
insertar y eliminar entidades en la base de datos, se implementan los métodos
ejbCreate() y ejbRemove() con una lógica de acceso a bases de datos muy
similar. Los métodos ejbCreate() se implementan para insertar un nuevo registro
Análisis y Uso de Frameworks de Persistencia en Java
59
en la base de datos y los métodos ejbRemove() para eliminar los datos de una
entidad de la base de datos. Estos métodos de una entidad son invocados por el
contenedor en respuesta a invocaciones a sus correspondientes métodos en los
interface home y remoto. Estas son las implementaciones de estos métodos.
public void ejbCreate(Integer id) { this.customerID = id.intValue(); Connection con; try { con = this.getConnection(); Statement sqlStmt = con.createStatement("INSERT INTO customer id VALUES (" + customerID + ")"); sqlStmt.executeUpdate(); return id; } catch(SQLException sqle) { throw new EJBException(sqle); } finally { if (con!=null) con.close(); } } public void ejbRemove() { Integer primaryKey = (Integer)ejbContext.getPrimaryKey(); Connection con; try { con = this.getConnection(); Statement sqlStmt = con.createStatement("DELETE FROM customer WHERE id = " primaryKey.intValue()); sqlStmt.executeUpdate(); } catch(SQLException sqle) { throw new EJBException(sqle); } finally { if (con!=null) con.close(); } }
Análisis y Uso de Frameworks de Persistencia en Java
60
En BMP, la clase bean es responsable de implementar los métodos de
búsqueda definidos en el interface home. Por cada método de búsqueda definido
en el interface home debe haber el correspondiente método ejbFind() en la clase
bean. Estos métodos localizan los registros del bean apropiado en la base de
datos y devuelve sus claves primarias al contenedor. El contenedor convierte la
clave primara en referencias a beans y los devuelve al cliente. Abajo tenemos un
ejemplo de implementación del método ejbFindByPrimaryKey() en la clase
CustomerBean_BMP, que corresponde al findByPrimaryKey() definido en el
interface CustomerHome.
public Integer ejbFindByPrimaryKey( Integer primaryKey) throws ObjectNotFoundException { Connection con; try { con = this.getConnection(); Statement sqlStmt = con.createStatement("SELECT * FROM Customer " + " WHERE customerID = " + primaryKey.intValue()); ResultSet results = sqlStmt.executeQuery(); if (results.next()) return primaryKey; else throw ObjectNotFoundException(); } catch (SQLException sqle) { throw new EJBException(sqle); } finally { if (con!=null) con.close(); } }
Los métodos de búsqueda de entidades simples como el de arriba
devuelven una sola clave primara y lanza una ObjectNotFoundException si no se
Análisis y Uso de Frameworks de Persistencia en Java
61
localiza un registro correspondiente. Los métodos de búsqueda multi-entidad
devuelven una colección (java.util.Enumeration o java.util.Collection) de claves
primarias. El contenedor convierte la colección de claves primarias en una
colección de referencias remotas, que son devueltas al cliente. Abajo tenemos un
ejemplo de cómo el método ejbFindByZipCode() multi-entidad, que corresponde
al método findByZipCode() definido en el interface CustomerHome, sería
implementado en la clase CustomerBean_BMP.
public Enumeration ejbFindByZipCode( int zipCode) { Connection con; try { con = this.getConnection(); Statement sqlStmt = con.createStatement("SELECT id FROM Customer " + " WHERE zip = " +zipCode); ResultSet results = sqlStmt.executeQuery(); Vector keys = new Vector(); while(results.next()){ int id = results.getInt("id"); keys.addElement(new Integer(id)); } return keys.elements(); } catch (SQLException sqle) { throw new EJBException(sqle); } finally { if (con!=null) con.close(); } }
Si no se encuentran registros correspondientes, se devuelve una colección
vacía al contenedor, que devuelve una colección vacía al cliente.
Análisis y Uso de Frameworks de Persistencia en Java
62
Con la implementación de todos estos métodos y unos pocos cambios
menores en el descriptor de desarrollo del bean, el CustomerBean_BMP esta
listo para ser desplegado como una entidad BMP.
3.3.2. Tecnología Open Source: HIBERNATE – Funcionamiento
Para comprender el funcionamiento de Hibernate se pretende describir
los diversos pasos a seguir para construir una aplicación que permita realizar el
proceso de persistencia. Primero, se creará un objeto Evento (Event) para
persistirlo en la base de datos. A continuación, se verá cómo persistir el objeto
Evento en la base de datos y realizar una transacción para obtenerlo de nuevo.
Después se procederá a construir un archivo XML de mapeo para decirle a
Hibernate qué es lo que deseamos persistir. A través de otro archivo XML se
configurarán las propiedades de Hibernate y la base de datos. Por último se verá
qué pasos se deben seguir para construir y ejecutar el sistema
Lo primero que tenemos que hacer es configurar nuestro directorio de
trabajo y poner en él todos los ficheros jar que necesitamos. Tenemos que
descargar la distribución de Hibernate de su página de descarga. Extraer los jars
necesarios desde el archivo de Hibernate. Los situaremos en un directorio lib
Análisis y Uso de Frameworks de Persistencia en Java
63
bajo el directorio de trabajo, tu despliegue de directorios debería parecerese a
Análisis y Uso de Frameworks de Persistencia en Java
65
PERSISTENCIA:
1º Creación del Objeto
El siguiente código muestra cómo se crea un objeto Evento desde el
método main:
public static void main(String[] args) throws java.text.ParseException { EventManager instance = new EventManager(); if (args[0].equals("store")) { String title = args[1]; Date theDate = new Date(); instance.store(title, theDate); } System.exit(0); }
Para este ejemplo se están pasando parámetros desde la línea de
comandos y se podrán leer en ‘args[]’. Si el primer argumento de recibido por la
aplicación es store, se toma el segundo argumento como un título, se crea un
nuevo Date y se pasan los dos al método store, donde se realiza la transacción
Ahora se deben compilar todos los ficheros fuentes ejecutando el fichero
build.bat desde el directorio de trabajo y lo ejecutamos utilizando el fichero
run.bat. Esta sería la salida:
Initializing Hibernate log4j:WARN No appenders could be found for logger (net.sf.hibernate.cfg.Environment). log4j:WARN Please initialize the log4j system properly. Finished Initializing Hibernate
Análisis y Uso de Frameworks de Persistencia en Java
76
3.4.- EVALUACIÓN
JDO vs. EJB
Desde la aparición de JDO se ha especulado que esta tecnología podría
sustituir a las EJB de entidad. Para entender esta afirmación se debe examinar
que es exactamente un EJB de entidad. Como ya se ha explicado, los beans de
entidad se dividen en dos categorías: persistencia manejada por contenedor
(CMP) y persistencia manejada por bean (BMP). Los beans BMP contienen un
código que puede almacenar el contenido del bean en un almacén de datos
permanente. Los BMP tienden a ser independientes y no forman relaciones
directas con otros beans BMP. No sería correcto decir que los beans BMP
pueden ser sustituidos por JDO, puesto que un bean BMP hace uso directo de
código JDBC. Esto viola uno de los principios de diseño de JDO ya que esta
tecnología pretende abstraer al usuario de codificar con JDBC.
Los beans CMP permiten manejar la persistencia al contenedor. El
contenedor es cualquier servidor que esté ejecutando el bean, y se encarga de
manejar todo el almacenamiento actual. Los beans CMP también pueden formar
las típicas relaciones [1 – n] ó [n a m] con otros beans CMP.
La función de un bean CMP es muy similar a la de JDO. Ambas
tecnologías permiten persistir datos con una perspectiva orientada a objetos ya
Análisis y Uso de Frameworks de Persistencia en Java
77
que siempre se persisten objetos y evitan tener que conocer los detalles de cómo
los objetos están almacenados. JDO y CMP también son capaces de manejar
relaciones entre objetos. Por tanto sí se puede hablar de que JDO puede sustituir
a CMP.
Se debe tener en cuenta el crecimiento de las tecnologías. Los beans
CMP todavía necesitan aumentar su aceptación en la comunidad de
programadores. La mayor parte de las mejoras y crecimiento en general de las
EJBs ha sido en el área de sesión. CMP y JDO padecen los mismos problemas a
la hora de ser acogidos ya que ambas tecnologías abstraen demasiado al
programador de lo que realmente sucede a nivel SQL. A la hora de realizar
consultas complicadas el programador debe dedicar mucho tiempo intentando
descubrir cómo generar dicha consulta equivalente a la sentencia SQL. En estos
casos los programadores preferirían haber programado en SQL desde un primer
momento.
JDO vs. JDBC/SQL
Sustituir a JDBC no es exactamente lo que busca JDO de la misma forma
que podría hacerlo con CMP. JDO puede ser realmente una buena capa en el
nivel superior a JDBC. En la mayoría de las instancias de JDO, se debe
especificar una fuente de datos JDBC que establezca una referencia a la base de
datos que JDO va a estar manejando. Por tanto, comparar a JDO con JDBC es
Análisis y Uso de Frameworks de Persistencia en Java
78
algo que se debe hacer si se duda entre usar directamente JDBC o permitir que
JDO lo use en lugar del programador.
Por una parte JDO libera al programador de la tarea de construir
consultas SQL y de distribuir entre los atributos de un objeto Java los resultados
obtenidos en un result set. Si se considera que la mayor parte de consultas JDBC
se realizan con el fin de dar valores a los atributos de objetos Java, JDO debería
ser una alternativa a tener en cuenta, puesto que en lugar de ejecutar una
consulta y copiar los campos desde el result set de JDBC a objetos Java, JDO se
puede hacer cargo de todo ello.
Las críticas a JDO vienen precisamente por las grandes cantidades de
accesos innecesarios que realiza para llevar a cabo su tarea. JDO debe coger su
consulta JDOQL y convertirla en su consulta SQL correspondiente. Entonces,
esta consulta SQL es enviada a la base de datos, los resultados son recibidos y
almacenados en sus respectivos objetos. Si hubiera un gran número de relaciones
entre los objetos, es muy fácil que, como consecuencia, JDO haya accedido a
muchos más datos de los necesarios. Es evidente que JDBC siempre va a ser más
rápido que JDO ya que es más directo. Será elección del programador si la
comodidad en la forma de trabajar que le ofrece JDO compensa su peor
rendimiento.
Otro de los aspectos discutidos de JDO es la posibilidad de sustituir SQL
por JDOQL. Cuando se usa JDBC se debe acudir a SQL para componer las
consultas mientras que con JDO se usa JDOQL. JDOQL es un lenguaje de
Análisis y Uso de Frameworks de Persistencia en Java
79
consultas basado en Java. Por una parte, JDOQL es mucho más sencillo de
componer que SQL, especialmente cuando nos referimos a consultas sencillas.
Sin embargo, no existen muchos programadores que dominen JDOQL.
De momento, este problema va a seguir existiendo ya que, como se ha
comentado anteriormente, JDO no ha sido muy acogido en la industria del
desarrollo de software. La mayoría de los programadores dominan SQL, y
además son capaces de construir consultas SQL muy optimizadas a pesar de
tener una gran complejidad.
Para muchos programadores, una herramienta que crea consultas
automáticamente no es de gran utilidad, sobre todo si nos referimos a JDOQL,
que solamente actúa en aplicaciones Java. Antes o después SQL será sustituido,
pero para ello tendrá que llevarlo a cabo una tecnología más universal.
Hibernate vs. JDO
Hibernate se caracteriza por su completa transparencia para el
programador. Al contrario que JDO, Hibernate se encarga de todo el proceso de
persistencia. No hay que pasar por la tarea de ejecutar nada parecido al
JDOEnhancer. Hibernate se encarga de hacer todo el proceso transparente, ya
que basta con añadir sus librerías a la aplicación y rellenar su archivo de
Análisis y Uso de Frameworks de Persistencia en Java
80
configuración para asignar la base de datos con la que se va a trabajar. Una vez
dispuestos los ficheros de mapeo, se puede trabajar con la misma facilidad con la
que se codifica con cualquier librería Java.
Otro punto muy a su favor es que Hibernate mantiene la posibilidad de
realizar sus consultas en SQL. El HQL es el lenguaje para consulta específico de
Hibernate, al igual que el JDOQL es el lenguaje a través del cual se realizan las
consultas cuando se trabaja con JDO. Para usar JDO, el JDOQL es
indispensable, ofreciendo una gran comodidad al programador a la hora de
componer consultas sencillas. Sin embargo, cuando se trata de realizar
sentencias más complejas, un programador que domine SQL con un nivel alto
seguramente eche de menos la alternativa estándar. Hibernate ofrece ambas
posibilidades.
3.5.- CONCLUSIONES
Se han encontrado muchos puntos de interés a través de la búsqueda de
información para el análisis de las diferentes tecnologías. Entre tantos, cabe
destacar la cantidad de usuarios que defienden una tecnología advirtiendo que es
la que mejor se adapta a su sistema.
Análisis y Uso de Frameworks de Persistencia en Java
81
El uso de los frameworks de persistencia se lleva a cabo, generalmente,
cuando un equipo de programadores busca una alternativa para intentar mejorar
el rendimiento de sus aplicaciones o para incrementar la sencillez de su
codificación y portabilidad. Las tecnologías que se han propuesto brindan esa
oportunidad a los usuarios, pero la clave a la hora de decidir sobre su
implantación está en su forma de adaptarse al sistema, y esto depende de algunos
factores que solamente se pueden identificar por medio de la experiencia
obtenida al probar varias alternativas.
Para mostrar la viabilidad de estas tecnologías se ha de escoger una de las
alternativas estudiadas. Siendo coherentes con la reflexión precedente y con el
apartado de evaluación, Hibernate es la alternativa más apropiada para ocuparse
de la persistencia en la aplicación que se va a desarrollar en el siguiente capítulo.
Estas son las razones fundamentales de por qué Hibernate se adapta a las
necesidades que se presentan:
o Es 100% orientado a objetos:
Hibernate es capaz de persistir clases que siguen una
orientación orientada a objetos, incluyendo herencia,
polimorfismo, relaciones de asociación y composición, y
colecciones.
Análisis y Uso de Frameworks de Persistencia en Java
82
o Máxima transparencia:
Hibernate es capaz de que el programador se olvide de la
tarea extraordinaria que se realiza al trabajar con una base de
datos. Todo el código para utilizar Hibernate será Java puro, ya
que existen cómodos asistentes para crear los archivos de
configuración y mapeo, que son XML. Además, en ninguna fase
de su utilización (instalación, configuración, desarrollo y
ejecución) será necesario escribir una sola instrucción en línea de
comandos, como sucede con JDO a la hora de ejecutar el
modificador de byte codes, el JDOEnhancer.
o Ofrece HQL pero también permite SQL:
Hibernate proporciona HQL, su propio lenguaje de
consulta cuya sintaxis busca mayor sencillez en cada sentencia.
Este lenguaje es similar a SQL, lo que aporta mucha facilidad a la
hora de aprender sus cláusulas. Sin embargo, para los
programadores que lo prefieran, Hibernate permite el uso de
sentencias SQL, con el fin de proporcionar libertad de elección,
sobre todo cuando hay que componer sentencias complejas.
o Herramientas oficiales de ayuda al mapeo:
Dentro de las diferentes herramientas oficiales que ofrece
Hibernate para facilitar su implantación, se encuentra el Mapping
Editor. Esta herramienta para la creación de los ficheros XML de
mapeo proporciona auto-relleno de campos como el nombre de la
Análisis y Uso de Frameworks de Persistencia en Java
83
clase, de los atributos, de la tabla correspondiente y de sus
columnas.
o Respaldo de una comunidad Open Source activa:
Hibernate es un proyecto profesional Open Source y un
componente crítico del catálogo de productos de JBoss Enterprise
Middleware System (JEMS). JBoss es una división de Red Hat, y
ofrece servicios de mantenimiento, consulta y entrenamiento para
asistir a sus usuarios.
Análisis y Uso de Frameworks de Persistencia en Java
84
4- Diseño y Desarrollo de la Aplicación
Análisis y Uso de Frameworks de Persistencia en Java
85
4- DISEÑO Y DESARROLLO DE LA APLICACIÓN
4.1- OBJETIVOS
Se pretende diseñar una aplicación que verifique la viabilidad de una de las
alternativas de persistencia O/R. La aplicación consistirá en un portal Web que
proporcione un interfaz mediante el cual se realicen múltiples accesos a una base de
datos relacional. Dicho portal presentará los resultados solicitados de forma vistosa y
ordenada. Con esto se pretende aplicar la tecnología a las actividades cotidianas
empresariales.
Puesto que el fin elemental del portal es la explotación de tablas y la distribución
de su información por todos los departamentos interesados en una empresa, se pretende
situar la aplicación en un entorno de intranet, de forma que solamente tengan acceso a
ella los empleados. Para hacer del portal una herramienta adecuada para todo tipo de
departamentos se deberán gestionar los perfiles de los usuarios con el fin de ofrecer los
servicios correspondientes a cada uno de ellos. Finalmente, para ser coherentes con la
motivación del proyecto, se deberá conseguir que la aplicación sea una herramienta
intuitiva y de uso cotidiano por parte de empleados de cualquier departamento de la
empresa, independientemente de su nivel de conocimientos.
La aplicación deberá adaptarse a MySQL Server, siendo este el gestor de bases
de datos que se va a utilizar. Se trabajará con MySQL por ser un sistema que admite
Análisis y Uso de Frameworks de Persistencia en Java
86
varias conexiones simultáneas, además de ser Open Source. Además, MySQL está
acompañado de herramientas como MySQL Administrator y MySQL Query Browser,
que, gracias a sus cuidados interfaces, son de gran ayuda a la hora de gestionar las bases
de datos.
4.2- DESCRIPCIÓN DE LA APLICACIÓN
La aplicación a desarrollar consiste en un portal Web para uso cotidiano, que
será accesible a través de la intranet en una pequeña empresa. Dado el carácter del
proyecto, la aplicación se basa en una empresa ficticia, pero gracias a un diseño sencillo
y sólido, añadiendo nuevas funcionalidades se podría adaptar a múltiples usos reales.
La empresa en cuestión consiste en una clínica privada de alergología. El portal
pretende servir de punto de encuentro entre todos los empleados, desde los médicos
hasta el personal informático. Además de ser una fuente de información para todos los
usuarios (noticias, enlaces de interés, etc…) el portal proporciona servicios a los
empleados, convirtiéndose en una útil herramienta para su trabajo cotidiano.
Al existir diferentes tipos de empleados, el portal adoptará un aspecto
determinado para cada perfil de usuario, ofreciendo a cada uno los servicios
correspondientes. En este caso, el personal informático tomará un papel de
Análisis y Uso de Frameworks de Persistencia en Java
87
administrador del portal, al servicio de las funcionalidades que están a disposición del
personal médico y administrativo de la clínica.
Para realizar un sencillo diseño de la aplicación Web se van a seguir las
siguientes etapas:
• Identificación de los requisitos funcionales mediante la definición de los Casos
de Uso y su representación mediante diagramas.
• Diseño externo mediante la asociación entre los Casos de Uso y los diseños de
páginas Web correspondientes realizados con HTML.
• Diseño interno a partir de los Casos de Uso, definiendo las herramientas, las
clases Java y el modelo de datos.
4.3– REQUISITOS FUNCIONALES
4.3.1. Actores Participantes
El portal está dirigido a todos los empleados de la clínica, entre los que se
distinguen tres grupos con perfiles diferentes:
a) Personal Informático (INF):
Análisis y Uso de Frameworks de Persistencia en Java
88
Este grupo desempeña el papel de administrador del portal, ocupándose
principalmente de la gestión de las cuentas. Por otra parte, debe tener acceso a
otras funcionalidades con el fin de supervisar la integridad de los datos.
b) Personal Médico (MED):
En este grupo se encuentran los médicos de la clínica. Éstos tendrán
acceso privilegiado a los datos de los pacientes que tengan asignados, así como a
su historia médica.
c) Personal Administrativo (AMD)
Los administrativos son los empleados encargados de recibir a los
clientes. De este modo gestionan los datos de todos los pacientes y los asocian
con un médico determinado.
4.3.2. Casos de Uso
Los requisitos funcionales de la aplicación vienen definidos por los siguientes
casos de uso:
1. Inicio
1.1. Solicitud de cuenta
1.2. Identificación
2. Navegación básica
2.1. Consulta de noticias
2.2. Cambio de contraseña
2.3. Consulta de enlaces
3. Acceso a Tablas
Análisis y Uso de Frameworks de Persistencia en Java
89
3.1. Gestión de pacientes
3.1.1. Creación de paciente
3.1.2. Edición de paciente
3.1.3. Eliminación de paciente
4. Acceso a Pacientes
4.1. Gestión de alergias
4.1.1. Asignación de alergia
4.1.2. Edición de alergia
4.1.3. Eliminación de alergia
5. Acceso a Portal
5.1. Gestión de noticias
5.1.1. Creación de noticia
5.1.2. Edición de noticia
5.1.3. Eliminación de noticia
5.2. Gestión de cuentas
5.2.1. Activación/Desactivación de cuenta
5.2.2. Edición de cuenta
5.2.3. Eliminación de cuenta
6. Cierre de sesión
6.1. Cierre de Sesión
Análisis y Uso de Frameworks de Persistencia en Java
90
DESCRIPCIÓN DETALLADA DE LOS CASOS DE USO
1. Inicio
ESCENARIO: 1.1. Solicitud de cuenta
ACTORES: INF, MED, ADM
Precondición: Seleccionar la opción “Registrarse” en la pantalla de inicio.
Flujo Primario:
1. El sistema pide los datos del usuario y su perfil.
2. El usuario introduce sus datos y envía el formulario.
3. El sistema valida los datos y advierte que la cuenta ha sido solicitada.
Flujo Secundario:
- El campo “Usuario” tiene un valor que ya existe:
El sistema advierte del error en la pantalla y vuelve a pedir los datos.
- La confirmación de contraseñas es incorrecta:
El sistema advierte del error en la pantalla y vuelve a pedir los datos.
- El campo “Dni” está vacío o no se ha seleccionado ningún perfil:
El sistema vuelve a pedir los datos.
ESCENARIO: 1.2. Identificación
ACTORES: INF, MED, ADM
Precondición: -
Flujo Primario:
1. El sistema pide los datos de identificación: Usuario y Contraseña.
2. El usuario introduce sus datos y envía el formulario.
Análisis y Uso de Frameworks de Persistencia en Java
91
3. El sistema valida los datos y da acceso al portal habilitando las opciones
correspondientes según su perfil.
Flujo Secundario:
- Los datos introducidos son válidos pero la cuenta no ha sido activada:
El sistema advierte del error y vuelve a pedir los datos.
- Los datos introducidos no son válidos:
El sistema advierte del error y vuelve a pedir los datos.
2. Navegación Básica
ESCENARIO: 2.1. Consulta de noticias
ACTORES: INF, MED, ADM
Precondiciones:
- El usuario acaba de acceder al portal.
- El usuario ha seleccionado la opción “Noticias” en la barra de navegación.
Flujo Primario:
1. El sistema muestra todas las noticias que se encuentran en la base de
datos, ordenadas por Fecha descendientemente.
Flujo Secundario: -
ESCENARIO: 2.2. Cambio de contraseña
ACTORES: INF, MED, ADM
Precondición: El usuario ha seleccionado la opción “Usuario” en la barra de
navegación.
Análisis y Uso de Frameworks de Persistencia en Java
92
Flujo Primario:
1. El sistema pide la contraseña actual del usuario y la nueva contraseña.
2. El usuario introduce los datos y envía el formulario.
3. El sistema valida los datos y advierte que la contraseña ha cambiado.
Flujo Secundario:
- La contraseña actual o la confirmación de nueva contraseña es incorrecta:
El sistema advierte del error y vuelve a pedir los datos.
ESCENARIO: 2.3. Consulta de enlaces
ACTORES: INF, MED, ADM
Precondición: El usuario ha seleccionado la opción “Enlaces” en la barra de
navegación.
Flujo Primario:
1. El sistema muestra diversos enlaces de interés.
2. El usuario pulsa sobre un enlace, que se abrirá en otra ventana o pestaña
de su navegador.
Flujo Secundario: -
3. Acceso a Tablas
3.1. Gestión de Pacientes
ESCENARIO: 3.1.1. Creación de paciente
ACTORES: INF, ADM
Análisis y Uso de Frameworks de Persistencia en Java
93
Precondición: El usuario ha seleccionado la opción “Nuevo Paciente” dentro de la
sección “Tablas” de la barra de navegación.
Flujo Primario:
1. El sistema pide los datos del nuevo paciente y muestra los médicos
disponibles en la base de datos.
2. El usuario introduce los datos del nuevo paciente, asignándole un médico
y envía el formulario.
3. El sistema valida los datos y advierte que el paciente ha sido dado de
alta.
Flujo Secundario:
- El dni del paciente ya ha sido registrado anteriormente:
El sistema advierte del error y vuelve a pedir los datos.
- No se ha asignado ningún médico:
El sistema advierte del error y vuelve a pedir los datos.
ESCENARIO: 3.1.2. Edición de paciente
ACTORES: INF, ADM
Precondición: El usuario ha seleccionado un paciente y pulsa sobre la opción “Editar”
dentro de la sección “Tablas” de la barra de navegación.
Flujo Primario:
1. El sistema muestra los datos del paciente y da opción a cambiarlos.
2. El usuario hace las modificaciones pertinentes y envía el formulario.
3. El sistema advierte que los datos del paciente se han actualizado.
Flujo Secundario: -
Análisis y Uso de Frameworks de Persistencia en Java
94
ESCENARIO: 3.1.3. Eliminación de paciente
ACTORES: INF, ADM
Precondición: El usuario ha seleccionado un paciente y pulsa sobre la opción “Borrar”
dentro de la sección “Tablas” de la barra de navegación.
Flujo Primario:
1. El sistema elimina el paciente seleccionado de la base de datos.
Flujo Secundario: -
4. Acceso a Pacientes
4.1. Gestión de Alergias
ESCENARIO: 4.1.1. Asignación de Alergia
ACTORES: MED
Precondición: El usuario ha seleccionado la opción “Pacientes” en la barra de
navegación.
Flujo Primario:
1. El sistema muestra los pacientes que tiene asignados el usuario.
2. El usuario selecciona un paciente y elige la opción “Ver Alergias”.
3. El sistema muestra las alergias que tiene asignadas el paciente.
4. El usuario elige la opción “Asignar Alergia”.
5. El sistema pide los datos de la alergia.
6. El usuario introduce los datos de la alergia y envía el formulario.
7. El sistema valida los datos y advierte que se ha asignado una alergia.
Flujo Secundario:
Análisis y Uso de Frameworks de Persistencia en Java
95
- No se ha especificado el tipo de alergia:
El sistema advierte del error y vuelve a pedir los datos.
- El tipo de alergia especificado ya ha sido asignado a ese paciente:
El sistema advierte del error y vuelve a pedir los datos.
ESCENARIO: 4.1.2. Edición de Alergia
ACTORES: MED
Precondición: El usuario ha seleccionado la opción “Pacientes” en la barra de
navegación.
Flujo Primario:
1. El sistema muestra los pacientes que tiene asignados el usuario.
2. El usuario selecciona un paciente y elige la opción “Ver Alergias”.
3. El sistema muestra las alergias que tiene asignadas el paciente.
4. El usuario selecciona un tipo de alergia y elige la opción “Ver Detalles”.
5. El sistema muestra los datos de la alergia.
6. El usuario modifica los datos de la alergia y envía el formulario.
7. El sistema valida los datos y advierte que se han modificado los detalles.
Flujo Secundario: -
ESCENARIO: 4.1.3. Eliminación de Alergia
ACTORES: MED
Desencadenante: El usuario ha seleccionado la opción “Pacientes” en la barra de
navegación.
Flujo Primario:
1. El sistema muestra los pacientes que tiene asignados el usuario.
Análisis y Uso de Frameworks de Persistencia en Java
96
2. El usuario selecciona un paciente y elige la opción “Ver Alergias”.
3. El sistema muestra las alergias que tiene asignadas el paciente.
4. El usuario selecciona un tipo de alergia y elige la opción “Borrar”.
5. El sistema elimina la alergia asignada y vuelve a mostrar la lista.
Flujo Secundario: -
5. Acceso a Portal
5.1. Gestión de Noticias
ESCENARIO: 5.1.1. Creación de noticia
ACTORES: INF
Precondición: El usuario ha seleccionado la opción “Portal” en la barra de navegación.
Flujo Primario:
1. El sistema muestra las opciones de gestión del portal.
2. El usuario selecciona la opción “Gestión de Noticias”.
3. El sistema muestra las noticias existentes.
4. El usuario selecciona la opción “Nueva Noticia”.
5. El sistema pide los datos de la nueva noticia.
6. El usuario introduce los datos y envía el formulario.
7. El sistema crea la noticia.
Flujo Secundario: -
ESCENARIO: 5.1.2. Edición de noticia
ACTORES: INF
Análisis y Uso de Frameworks de Persistencia en Java
97
Precondición: El usuario ha seleccionado la opción “Portal” en la barra de navegación.
Flujo Primario:
1. El sistema muestra las opciones de gestión del portal.
2. El usuario elige la opción “Gestión de Noticias”.
3. El sistema muestra las noticias existentes.
4. El usuario selecciona una noticia y elige la opción “Editar”.
5. El muestra los datos de la noticia seleccionada y permite su modificación.
6. El usuario modifica los datos de la noticia y envía el formulario.
7. El sistema actualiza los datos y advierte que la noticia ha sido modificada.
Flujo Secundario: -
ESCENARIO: 5.1.3. Eliminación de noticia
ACTORES: INF
Precondición: El usuario ha seleccionado la opción “Portal” en la barra de navegación.
Flujo Primario:
1. El sistema muestra las opciones de gestión del portal.
2. El usuario elige la opción “Gestión de Noticias”.
3. El sistema muestra las noticias existentes.
4. El usuario selecciona una noticia y elige la opción “Borrar”.
5. El sistema elimina la noticia y vuelve a mostrar la lista.
Flujo Secundario: -
5.2. Gestión de Cuentas de Usuario
Análisis y Uso de Frameworks de Persistencia en Java
98
ESCENARIO: 5.2.1. Activación / Desactivación de cuenta
ACTORES: INF
Precondición: El usuario ha seleccionado la opción “Portal” en la barra de navegación.
Flujo Primario:
1. El sistema muestra las opciones de gestión del portal.
2. El usuario elige la opción “Gestión de Cuentas”.
3. El sistema muestra las cuentas existentes, incluyendo las que están
desactivadas.
4. El usuario selecciona una cuenta y elige la opción “Activar / Desactivar”.
5. El sistema cambia el estado de actividad de la cuenta y vuelve a mostrar la
lista.
Flujo Secundario: -
ESCENARIO: 5.2.2. Edición de cuenta
ACTORES: INF
Precondición: El usuario ha seleccionado la opción “Portal” en la barra de navegación.
Flujo Primario:
1. El sistema muestra las opciones de gestión del portal.
2. El usuario elige la opción “Gestión de Cuentas”.
3. El sistema muestra las cuentas existentes, incluyendo las que están
desactivadas.
4. El usuario selecciona una cuenta y elige la opción “Editar”.
5. El sistema muestra los datos de la cuenta y permite su modificación,
exceptuando el perfil.
6. El usuario modifica los datos pertinentes y envía el formulario.
Análisis y Uso de Frameworks de Persistencia en Java
99
7. El sistema valida los datos y advierte que la cuenta ha sido actualizada.
Flujo Secundario: -
ESCENARIO: 5.2.3. Eliminación de cuenta
ACTORES: INF
Precondición: El usuario ha seleccionado la opción “Portal” en la barra de navegación.
Flujo Primario:
1. El sistema muestra las opciones de gestión del portal.
2. El usuario elige la opción “Gestión de Cuentas”.
3. El sistema muestra las cuentas existentes, incluyendo las que están
desactivadas.
4. El usuario selecciona una cuenta y elige la opción “Borrar”.
5. El sistema elimina la cuenta y vuelve a mostrar la lista.
Flujo Secundario: -
6. Cierre de Sesión
ESCENARIO: 6.1. Cierre de Sesión
ACTORES: INF, MED, ADM
Precondición: El usuario ha seleccionado la opción “Cerrar Sesión” en la barra de
navegación.
Flujo Primario:
1. El sistema muestra la pantalla inicial pidiendo los datos de identificación.
Flujo Secundario: -
Análisis y Uso de Frameworks de Persistencia en Java
100
DIAGRAMAS DE LOS CASOS DE USO
• Casos de uso del Personal Informático (INF):
Análisis y Uso de Frameworks de Persistencia en Java
101
• Casos de uso del Personal Administrativo (ADM):
Análisis y Uso de Frameworks de Persistencia en Java
102
• Casos de uso del Personal Médico (MED):
Análisis y Uso de Frameworks de Persistencia en Java
103
4.4- DISEÑO EXTERNO
4.4.1. Diseño del Interfaz del Usuario
• Inicio
- Identificación
Caso de uso: 1.2. Login de Acceso
Esta es la pantalla de inicio de la aplicación. A través del botón “Registrarse” en
la parte inferior derecha, el sistema pedirá los datos a un nuevo usuario para que realice
su solicitud de una nueva cuenta.
Análisis y Uso de Frameworks de Persistencia en Java
104
- Solicitud de Cuenta
Caso de uso: 1.1. Solicitud de Cuenta
Después de realizar la solicitud el sistema conducirá de nuevo al inicio de la
aplicación, donde se pedirán otra vez los datos de identificación.
Análisis y Uso de Frameworks de Persistencia en Java
105
• Navegación básica
- Consulta de noticias
Caso de uso: 2.1. Consulta de Noticias
Este es el aspecto que tendrá el portal. Desde aquí se accede a todas las
funcionalidades disponibles para el usuario a través de la barra de navegación situada en
el lateral izquierdo. En la parte superior derecha, el sistema muestra el perfil y el
nombre del usuario que ha iniciado la sesión.
La aplicación da la bienvenida con las últimas noticias ordenadas por fecha
descendentemente. Esta información será accesible en cualquier momento desde la
opción “Noticias” que aparece en la barra de navegación.
Análisis y Uso de Frameworks de Persistencia en Java
106
- Cambio de contraseña
Caso de uso: 2.2. Cambio de Contraseña
Esta funcionalidad se ubicará en el apartado “Usuario” de la barra de
navegación. Como se aprecia en la imagen, el sistema pedirá que el usuario introduzca
de nuevo su contraseña actual por cuestiones de seguridad.
Análisis y Uso de Frameworks de Persistencia en Java
107
- Consulta de enlaces
Caso de uso: 2.3. Consulta de Enlaces
En el apartado “Enlaces” los usuarios tendrán acceso a diversos enlaces de
utilidad para su uso cotidiano. Al pulsar sobre uno de ellos, la página Web
correspondiente se abrirá en una nueva ventana o pestaña del navegador.
Análisis y Uso de Frameworks de Persistencia en Java
108
• Gestión de pacientes
- Creación de paciente
Caso de uso: 3.1.1. Creación de Paciente
Este es el formulario que presentará el sistema al usuario para recibir los datos
de un nuevo paciente. Los médicos que figuren en la base de datos aparecerán en la
casilla “Médico” para realizar la asignación del paciente.
Análisis y Uso de Frameworks de Persistencia en Java
109
- Edición de paciente
Caso de uso: 3.1.2. Edición de Paciente
Este formulario muestra los datos del paciente correspondiente, así como el
médico que tiene asignado. Se permitirá el cambio de médico entre otras cosas.
Análisis y Uso de Frameworks de Persistencia en Java
110
- Eliminación de paciente
Caso de uso: 3.1.3. Eliminación de paciente
Esta será la pantalla que presenta el sistema para gestionar los pacientes. El
sistema muestra una lista con todos los pacientes registrados en la base de datos. Desde
aquí se accederá a los formularios para la creación y edición de los pacientes.
Para eliminar un paciente, se debe seleccionar uno de ellos y pulsar el botón
“Borrar” situado en la parte superior de la lista.
Análisis y Uso de Frameworks de Persistencia en Java
111
• Gestión de alergias
- Asignación de alergia
Caso de uso: 4.1.1. Asignación de Alergia
Mediante este formulario el médico asignará un tipo de alergia a uno de sus
pacientes. El sistema no permitirá registrar dos veces un tipo de alergia determinado a
un mismo paciente.
Análisis y Uso de Frameworks de Persistencia en Java
112
- Edición de alergia
Caso de uso: 4.1.2. Edición de Alergia
A través de este formulario el médico podrá ver los detalles de la alergia
correspondiente, así como cambiar el tratamiento.
Análisis y Uso de Frameworks de Persistencia en Java
113
- Eliminación de alergia
Caso de uso: 4.1.3. Eliminación de Alergia
Esta será la pantalla que presenta el sistema para gestionar las alergias. El
sistema muestra una lista con las alergias asignadas a un paciente determinado. Desde
aquí se accederá a los formularios para la asignación y edición de las alergias.
Para eliminar una alergia, se debe seleccionar una de ellas y pulsar el botón
“Borrar” situado en la parte superior de la lista.
Análisis y Uso de Frameworks de Persistencia en Java
114
• Gestión del Portal (Noticias y Cuentas de Usuario)
Esta es la pantalla que presenta el sistema al informático para gestionar el portal.
Desde aquí se accederá a la “Gestión de Noticias” y a la “Gestión de Cuentas”.
Análisis y Uso de Frameworks de Persistencia en Java
115
- Creación de noticia
Caso de uso: 5.1.1. Creación de Noticia
Este es el formulario que presentará el sistema al informático para recibir los
datos de una nueva noticia.
Análisis y Uso de Frameworks de Persistencia en Java
116
- Edición de noticia
Caso de uso: 5.1.2. Edición de Noticia
A través de este formulario el informático podrá ver los detalles de la noticia
correspondiente y modificar cualquiera de sus datos.
Análisis y Uso de Frameworks de Persistencia en Java
117
- Eliminación de noticia
Caso de uso: 5.1.3. Eliminación de Noticia
Esta será la pantalla que presenta el sistema para gestionar las noticias. El
sistema muestra una lista con las noticias existentes en la base de datos. Desde aquí se
accederá a los formularios para la creación y edición de las noticias.
Para eliminar una noticia, se debe seleccionar una de ellas y pulsar el botón
“Borrar” situado en la parte superior de la lista.
Análisis y Uso de Frameworks de Persistencia en Java
118
- Activación/Desactivación de cuenta y Eliminación de cuenta
Casos de uso:
5.2.1. Activación / Desactivación de Cuenta
5.2.3. Eliminación de cuenta
Esta será la pantalla que presenta el sistema para gestionar las cuentas. El
sistema muestra una lista con las cuentas de usuario, incluyendo las que no están
activas. Desde aquí se accederá al formulario para la edición de las cuentas.
Para eliminar una noticia o cambiar su estado de actividad, se debe seleccionar
una de ellas y pulsar el botón “Borrar” o “Activar / Desactivar” respectivamente.
Análisis y Uso de Frameworks de Persistencia en Java
119
- Edición de cuenta
Caso de uso: 5.2.2. Edición de Cuenta
A través de este formulario el informático podrá ver los detalles de la cuenta de
usuario correspondiente y modificar cualquiera de sus. Además, el sistema mostrará su
perfil, su dni y su estado de actividad en la parte superior. Para cambiar el perfil o el
dni, el usuario correspondiente a la cuenta deberá realizar una nueva solicitud.
Análisis y Uso de Frameworks de Persistencia en Java
120
• Cierre de Sesión
Caso de uso: 6.1. Cierre de Sesión
Con el fin de abandonar el portal el usuario deberá elegir la opción “Cerrar
Sesión” situada en la parte inferior de la barra de navegación. El sistema volverá a pedir
los datos de identificación en la página de inicio de la aplicación.
Análisis y Uso de Frameworks de Persistencia en Java
121
4.5- DISEÑO INTERNO
4.5.1- JSP y Servlets
Para hacer posible el desarrollo de la aplicación Web se va a diseñar una
estructura unida de páginas dinámicas JSP. Las páginas JSP permiten ejecutar
código Java con el fin de generar HTML dinámicamente. Esto será esencial,
entre otras cosas, para mostrar resultados de consultas a las bases de datos y para
mostrar mensajes de error cuando sea necesario.
Para la recepción de los formularios y la validación de sus datos se
utilizarán Servlets. Mediante algoritmos de validación y accesos a las bases de
datos, los diversos Servlets se encargarán de ejecutar un código u otro
dependiendo de los datos introducidos en los formularios. Posteriormente
devuelven el control a las páginas JSP.
Para realizar el diseño se analizarán los diferentes subsistemas de casos
de uso y se definirán las páginas JSP y Servlets necesarios para su viabilidad.
Los subsistemas son: Inicio, Navegación Básica, Gestión de Pacientes, Gestión
de Tablas, Gestión de Alergias, Gestión de Noticias y Gestión de Cuentas.
Análisis y Uso de Frameworks de Persistencia en Java
122
Subsistema: INICIO
Caso de Uso: 1.1. Solicitud de cuenta
- JSP: registro.jsp
- Servlet asociado: ValidaRegistro.java
Caso de Uso: 1.2. Identificación
- JSP: index.jsp
- Servlet asociado: ValidaUsuario.java
Subsistema: NAVEGACIÓN BÁSICA
Caso de Uso: 2.1. Consulta de Noticias
- JSP: home.jsp
- Servlet asociado: -
Caso de Uso: 2.2. Cambio de Contraseña
- JSP: usuario.jsp
- Servlet asociado: CambiaPass.java
Caso de Uso: 2.3. Consulta de Enlaces
- JSP: enlaces.jsp
- Servlet asociado: -
Análisis y Uso de Frameworks de Persistencia en Java
123
Subsistema: GESTIÓN DE PACIENTES
Caso de Uso: 3.1.1. Creación de Paciente
- JSP: creacionPaciente.jsp
- Servlet asociado: CreaPaciente.java
Caso de Uso: 3.1.2. Edición de Paciente
- JSP: edicionPaciente.jsp
- Servlet asociado: EditaPaciente.java
Caso de Uso: 3.1.3. Eliminación de Paciente
- JSP: tablas.jsp
- Servlet asociado: GestionaPaciente.java
Subsistema: GESTIÓN DE ALERGIAS
Caso de Uso: 4.1.1. Asignación de Alergia
- JSP: creacionAlergia.jsp
- Servlet asociado: CreaAlergia.java
Caso de Uso: 4.1.2. Edición de Alergia
- JSP: edicionAlergia.jsp
- Servlet asociado: EditaAlergia.java
Análisis y Uso de Frameworks de Persistencia en Java
124
Caso de Uso: 4.1.3. Eliminación de Alergia
- JSP: pacientesAlergias.jsp
- Servlet asociado: GestionaEnfermedad.java
Subsistema: GESTIÓN DE NOTICIAS
Caso de Uso: 5.1.1. Creación de Noticia
- JSP: creacionNoticia.jsp
- Servlet asociado: CreaNoticia.java
Caso de Uso: 5.1.2. Edición de Noticia
- JSP: edicionNoticia.jsp
- Servlet asociado: EditaNoticia.java
Caso de Uso: 5.1.3. Eliminación de Noticia
- JSP: portalNoticias.jsp
- Servlet asociado: GestionaNoticia.java
Subsistema: GESTIÓN DE CUENTAS
Caso de Uso: 5.2.1. Activación / Desactivación de Cuenta
- JSP: portalCuentas.jsp
Análisis y Uso de Frameworks de Persistencia en Java
125
- Servlet asociado: GestionaCuenta.java
Caso de Uso: 5.2.2. Edición de Cuenta
- JSP: edicionCuenta.jsp
- Servlet asociado: EditaCuenta.java
Caso de Uso: 5.2.3. Eliminación de Cuenta
- JSP: portalCuentas.jsp
- Servlet asociado: GestionaCuenta.java
Análisis y Uso de Frameworks de Persistencia en Java
126
4.5.2- Diagrama de Navegación
En el siguiente diagrama viene reflejada la intaracción entre todas las
páginas JSP que forman el sistema. Todas las líneas de conexión implican
navegación bidireccional, exceptuando aquellas que terminan con punta de
flecha. Las páginas JSP situadas dentro del recuadro gris sólo son accesibles
después de realizar la identificación.
Análisis y Uso de Frameworks de Persistencia en Java
127
4.5.3- Diagramas de clases
La aplicación va a trabajar con dos tipos de clases:
a) Clases objeto
b) Clases de acceso a la base de datos
Las clases objeto, que van a situarse en un paquete llamado “obj”, vienen
definidas por los subsistemas de gestión, debiendo crear una clase por cada uno
de ellos:
GESTIÓN DE PACIENTES Paciente.java
GESTIÓN DE ALERGIAS Alergia.java
GESTIÓN DE NOTICIAS Noticia.java
GESTIÓN DE CUENTAS DE USUARIO Usuario.java
Sin embargo, las clases de acceso a base de datos, que van a situar se en
un paquete llamado “util”, vienen definidas por la necesidad de persistencia de
cada uno de los objetos. En un principio, para desarrollar una primera versión
del portal, utilizaremos clases DAO para trabajar con JDBC. En el capítulo 5 se
verá cómo se va a sustituir JDBC por un framework de persistencia. Hasta
entonces se construirá la aplicación con JDBC, y éstas serán sus clases DAO:
Análisis y Uso de Frameworks de Persistencia en Java
128
Paciente.java DAO_paciente.java
Alergia.java DAO_alergia.java
Noticia.java DAO_noticia.java
Usuario.java DAO_usuario.java
Las clases no tienen relaciones entre sí, por tanto se representan por separado:
DIAGRAMAS UML DE CLASES OBJETO
Paciente.java
Análisis y Uso de Frameworks de Persistencia en Java
129
Alergia.java
Noticia.java
Análisis y Uso de Frameworks de Persistencia en Java
130
Usuario.java
Análisis y Uso de Frameworks de Persistencia en Java
131
DIAGRAMAS UML DE CLASES DE ACCESO A LA BASE DE DATOS
DAO_paciente.java
DAO_alergia.java
Análisis y Uso de Frameworks de Persistencia en Java
132
DAO_noticia.java
DAO_usuario.java
Análisis y Uso de Frameworks de Persistencia en Java
133
4.5.4- El modelo de datos
En esta aplicación el modelo de datos se debe ajustar perfectamente a la
estructura de las clases objeto. De esta forma se consigue simplificar la persistencia y
poder incorporar cómodamente la tecnología que va a sustituir a JDBC.
Las clases están definidas, y cada una de ellas será correspondida con una tabla
en la base de datos. Todos sus atributos van a ser reflejados por columnas en las tablas,
y las claves se definirán por la lógica de la aplicación.
Tabla PACIENTES
Tabla ALERGIAS
En el caso de las Alergias, la clave debe ser compuesta, ya que la aplicación no
permite tener más de un registro de un tipo de alergia para un mismo paciente.
Análisis y Uso de Frameworks de Persistencia en Java
134
Tabla NOTICIAS
Tabla USUARIOS
Análisis y Uso de Frameworks de Persistencia en Java
135
5- La alternativa a JDBC: Hibernate
Análisis y Uso de Frameworks de Persistencia en Java
136
5- LA ALTERNATIVA A JDBC: HIBERNATE
Después de haber diseñado la aplicación, se pueden identificar varias entidades
que, a la hora de persistirlas en su base de datos, se van a corresponder con tablas. En
este capítulo se pretende describir cómo Hibernate abstrae al programador de la
persistencia, creando las tablas a partir de las clases con las que se trabaja en la
aplicación.
La correspondencia entre clases y tablas es fundamental para mantener esa
perspectiva orientada a objetos. Además, se van a enfrentar las clases gestoras de
objetos de Hibernate con las DAO equivalentes de JDBC, con el fin de observar cómo
Hibernate evita el proceso de encapsulamiento y desencapsulamiento. Por último se
verá cómo es el proceso de implantación, echando un vistazo a los requisitos del sistema
y a la configuración de la tecnología.
5.1- LAS CLASES A PERSISTIR
- Usuario.java
La clase Usuario es la más extensa de todas las que se van a
persistir. La aplicación se encarga de que los valores correspondientes a
Análisis y Uso de Frameworks de Persistencia en Java
137
sus atributos “dni” y “user” sean únicos para cada usuario real que
representa la clase.
Este es el código final de la clase “Usuario.java”:
package obj; public class Usuario { private int dni; private String user; private String pass; private String nombre; private String ap1; private String ap2; private String email; private String cod_perfil; private int activo; //Cuenta 0:inactiva, 1:activa public static String PERFIL_MEDICO = "med"; public static String PERFIL_ADMINISTRATIVO = "adm"; public static String PERFIL_INFORMATICO = "inf"; // CONSTRUCTORES public Usuario( int dni, String user, String pass, String nombre, String ap1, String ap2, String email, String cod_perfil, int activo) { this.dni = dni; this.user = user; this.pass = pass; this.nombre = nombre; this.ap1 = ap1; this.ap2 = ap2; this.email = email; this.cod_perfil = cod_perfil; this.activo = activo; } //Constructor para la validación de usuarios public Usuario (String user, String pass){ this.user = user; this.pass = pass; } // Constructor por defecto: necesario para Hibernate
Análisis y Uso de Frameworks de Persistencia en Java
138
public Usuario(){ } // ----- Getters y Setters public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public int getActivo() { return activo; } public void setActivo(int activo) { this.activo = activo; } public String getAp1() { return ap1; } public void setAp1(String ap1) { this.ap1 = ap1; } public String getAp2() { return ap2; } public void setAp2(String ap2) { this.ap2 = ap2; } public String getCod_perfil() { return cod_perfil; } public void setCod_perfil(String cod_perfil) { this.cod_perfil = cod_perfil; } public int getDni() { return dni; } public void setDni(int dni) {
Análisis y Uso de Frameworks de Persistencia en Java
139
this.dni = dni; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } // ----- Otros métodos // Devuelve un String con el nombre completo del usuario public String getNombreCompleto() { String res = this.getAp1() +" "+ this.getAp2()+", "+ this.getNombre(); return res; } // Devuelve el código HTML para mostrar una imagen del Perfil public String perfilToHTML() { String res; if ((this.cod_perfil).equals(Usuario.PERFIL_MEDICO)) { res = "<img src=\"Iconos/perfilMed.jpg\">"; } else { if ((this.cod_perfil).equals(Usuario.PERFIL_ADMINISTRATIVO)) { res = "<img src=\"Iconos/perfilAdm.jpg\">"; } else { res = "<img src=\"Iconos/perfilInf.jpg\">"; } } return res; } // Devuelve el código HTML para mostrar una fila de tabla // con la información de la cuenta. public String toListaHTML(){ String iconoPerfil; String iconoActividad; // Asignación de perfil if ((this.cod_perfil).equals(Usuario.PERFIL_MEDICO)) { iconoPerfil = "<img src=\"Iconos/perfilMedMini.jpg\"width=\"40\" height=\"15\">"; }
Análisis y Uso de Frameworks de Persistencia en Java
// Con JDBC: public void editarCuenta(Usuario u) { if (this.conexion != null) { // DESENCAPSULAMIENTO: int dni = u.getDni(); String user = u.getUser(); String pass = u.getPass(); String nom = u.getNombre(); String ap1 = u.getAp1(); String ap2 = u.getAp2(); String email = u.getEmail();
Análisis y Uso de Frameworks de Persistencia en Java
159
try { Statement st = (this.conexion).createStatement(); st.executeUpdate("UPDATE personal.usuarios SET usuario='"+user+"' WHERE dni='"+dni+"'"); st.executeUpdate("UPDATE personal.usuarios SET pass='"+pass+"' WHERE dni='"+dni+"'"); st.executeUpdate("UPDATE personal.usuarios SET nombre='"+nom+"' WHERE dni='"+dni+"'"); st.executeUpdate("UPDATE personal.usuarios SET apellido1='"+ap1+"' WHERE dni='"+dni+"'"); st.executeUpdate("UPDATE personal.usuarios SET apellido2='"+ap2+"' WHERE dni='"+dni+"'"); st.executeUpdate("UPDATE personal.usuarios SET email='"+email+"' WHERE dni='"+dni+"'"); } catch (SQLException e) { System.out.println("ERROR query update"); } } }
Es fácil comprobar que la diferencia en cuanto a cantidad de
líneas de código es muy notable. Hibernate se sirve con
“session.update(u)”, comprobando el campo clave para
identificar el registro que se va a actualizar y sustituyendo todos los
valores que haya en la tabla por los que se encuentran poblando los
atributos del objeto “u”. Lo mismo sucede con instrucciones como
“session.save(u)” o “session.delete(u)” que aparecen en
de inserción y borrado, respectivamente.
Otro punto interesante es que la clase Query de Hibernate
redefine el método List(), de forma que facilita el uso del resultado y
no hay que recorrer el ResultSet como ocurre cuando se trabaja con
JDBC.
Análisis y Uso de Frameworks de Persistencia en Java
160
- GestorPaciente.java
Para trabajar con la clase Paciente se usará esta clase gestora:
Análisis y Uso de Frameworks de Persistencia en Java
165
/* Al tener una clave compuesta, para ejecutar el método load(), el identificador del objeto es una instancia del propio objeto con los atributos que forman la clave compuesta poblados con los datos correspondientes. */ Alergia res = null; Alergia a = new Alergia (dni,tipo,"",""); try { Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); /* Con .load() */ res = (Alergia)session.load(Alergia.class, a); System.out.println(res.getNotas()); /* Con QUERY: */ // String dniString = String.valueOf(dni); // res = (Alergia)session.createQuery("from Alergia as alergia where alergia.dni = ? and alergia.tipo = ?") // .setString(0,dniString) // .setString(1,tipo) // .uniqueResult(); tx.commit(); session.close(); } catch (HibernateException e) { e.printStackTrace(); } return res; } public void borrarAlergia(Alergia a) { try { Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); session.delete(a); tx.commit(); session.close(); } catch (HibernateException e) { e.printStackTrace(); } } public void editarAlergia(Alergia a) { try { Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction();
Análisis y Uso de Frameworks de Persistencia en Java
166
String tratamiento = a.getTratamiento(); String notas = a.getNotas(); Alergia a_old = (Alergia)session.load(Alergia.class, a); a_old.setTratamiento(tratamiento); a_old.setNotas(notas); session.flush(); //Hibernate guarda los cambios en "a_old" tx.commit(); session.close(); } catch (HibernateException e) { e.printStackTrace(); } } public boolean existeRegistro(int dni, String tipo) { boolean res = false; try { Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); Alergia a = (Alergia)session.get(Alergia.class, new Alergia(dni,tipo,"","")); if (a != null){ res = true; } tx.commit(); session.close(); } catch (HibernateException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return res; } public Iterator obtenerAlergiasAsignadas(int dni){ Iterator it = null; String dniString = String.valueOf(dni); try { Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); it = session.createQuery("from Alergia as alergia where alergia.dni = ?") .setString(0,dniString) .list() .iterator(); tx.commit();
Análisis y Uso de Frameworks de Persistencia en Java