Download análisis y uso de frameworks de persistencia en java

Document related concepts
no text concepts found
Transcript
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
PROYECTO FIN DE CARRERA
ANÁLISIS Y USO DE FRAMEWORKS DE
PERSISTENCIA EN JAVA
Autor: Alfredo Payá Martín
Director: José Miguel Ordax Cassá
Análisis y Uso de Frameworks de Persistencia en Java
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.
I
Análisis y Uso de Frameworks de Persistencia en Java
Resumen
II
Análisis y Uso de Frameworks de Persistencia en Java
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
III
Análisis y Uso de Frameworks de Persistencia en Java
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.
IV
Análisis y Uso de Frameworks de Persistencia en Java
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
V
Análisis y Uso de Frameworks de Persistencia en Java
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.
VI
Análisis y Uso de Frameworks de Persistencia en Java
Índice
VII
Análisis y Uso de Frameworks de Persistencia en Java
Í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
VIII
Análisis y Uso de Frameworks de Persistencia en Java
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
IX
Análisis y Uso de Frameworks de Persistencia en Java
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
X
Análisis y Uso de Frameworks de Persistencia en Java
1- Introducción
1
Análisis y Uso de Frameworks de Persistencia en Java
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.
2
Análisis y Uso de Frameworks de Persistencia en Java
2- Definición del
Problema
3
Análisis y Uso de Frameworks de Persistencia en Java
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.
4
Análisis y Uso de Frameworks de Persistencia en Java
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.
5
Análisis y Uso de Frameworks de Persistencia en Java
3- Análisis de las
Tecnologías
6
Análisis y Uso de Frameworks de Persistencia en Java
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
7
Análisis y Uso de Frameworks de Persistencia en Java
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.
8
Análisis y Uso de Frameworks de Persistencia en Java
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
9
Análisis y Uso de Frameworks de Persistencia en Java
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
10
Análisis y Uso de Frameworks de Persistencia en Java
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.
11
Análisis y Uso de Frameworks de Persistencia en Java
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
12
Análisis y Uso de Frameworks de Persistencia en Java
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.
13
Análisis y Uso de Frameworks de Persistencia en Java
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
14
Análisis y Uso de Frameworks de Persistencia en Java
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
15
Análisis y Uso de Frameworks de Persistencia en Java
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:
16
Análisis y Uso de Frameworks de Persistencia en Java
Vendedores de JDO
Compañía
Producto
SolarMetric
URL Asociada
Kodo JDO Enterprise Edition, Kodo www.solarmetric.com
JDO Standard Edition
Poet Software
FastObjects
www.fastobjects.com
LiBeLIS
LiDO
www.libelis.com
Hemisphere
JDO Genie
www.hemtech.co.za/jdo
ObjectFrontier Inc.
FrontierSuite for JDO
www.objectfrontier.com
Versant
Versant enJin
www.versant.com
Sun Microsystems,
Reference Implementation
www.java.sun.com
JRelay
www.objectindustries.com
Corporation
Technologies
Inc.
Object Industries
GMBH
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.
17
Análisis y Uso de Frameworks de Persistencia en Java
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:
18
Análisis y Uso de Frameworks de Persistencia en Java
* 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.
19
Análisis y Uso de Frameworks de Persistencia en Java
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.
20
Análisis y Uso de Frameworks de Persistencia en Java
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:
21
Análisis y Uso de Frameworks de Persistencia en Java
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
aspecto:
public class Person {
// -- ATRIBUTOS
private String
private String
private String
private String
private String
private String
name;
address;
ssn;
email;
homePhone;
workPhone;
// -- CONSTRUCTOR
public Person(String name, String address, String ssn,
String email, String homePhone, String workPhone) {
this.name = name;
this.address = address;
this.ssn = ssn;
this.email = email;
this.homePhone = homePhone;
this.workPhone = workPhone;
}
// -- MÉTODOS
public String getName() { return name; }
public String getAddress() { return address; }
public String getSsn() { return ssn; }
public String getEmail() { return email; }
public String getHomePhone() { return homePhone; }
public String getWorkPhone() { return workPhone; }
22
Análisis y Uso de Frameworks de Persistencia en Java
// -- mutators
public void setName(String name) { this.name = name; }
public void setAddress(String address) {
this.address = address;
}
public void setSsn(String ssn) { this.ssn = ssn; }
public void setEmail(String email) { this.email = email;
}
public void setHomePhone(String homePhone) {
this.homePhone = homePhone;
}
public void setWorkPhone(String workPhone) {
this.workPhone = workPhone;
}
}
PERSISTENCIA:
Creación del objeto gestor de la persistencia (PersonPersist.java)
Una vez que se tiene un objeto ‘Person’ con el cuál podemos trabajar,
necesitamos crear un objeto que se encargue de gestionar su persistencia. Este
objeto será el ‘PersonPersist’. Seguidamente, por pasos, se realizarán diversas
operaciones con el objeto ‘Person’:
1. Inicializar el JDO Persistente Manager.
2. Persistir tres personas en la base de datos.
3. Mostrar el contenido de la base de datos.
4. Cambiar el nombre de una persona.
5. Borrar una de las personas.
6. Realizar las operaciones desde el método main ( ).
23
Análisis y Uso de Frameworks de Persistencia en Java
Paso 1º: Inicializar el JDO Persistence Manager
Aquí figura el principio de la codificación del objeto ‘PersistPerson’. Es
necesario importar las clases estándar de JDO y la ‘ManagedConnectionFactory’
desde la implementación de OpenFusion. El constructor asigna la “Connection
Factory”, empleando la propiedad ‘javax.jdo.PersistenceManagerFactoryClass’.
Esto es como asignar el driver de la base de datos si se trabaja con JDBC.
package addressbook;
import java.util.*;
import javax.jdo.*;
import
com.prismt.j2ee.connector.jdbc.ManagedConnectionFactoryImpl;
public class PersonPersist
{
private final static int SIZE
= 3;
private PersistenceManagerFactory pmf = null;
private PersistenceManager pm
= null;
private Transaction transaction
= null;
// Array de personas a persistir
private Person[] people;
// Vector de identificadores de objetos
private Vector id = new Vector(SIZE);
public PersonPersist() {
try {
Properties props = new Properties();
props.setProperty("javax.jdo.PersistenceManagerFactoryClass",
"com.prismt.j2ee.jdo.PersistenceManagerFactoryImpl");
pmf = JDOHelper.getPersistenceManagerFactory(props);
pmf.setConnectionFactory( createConnectionFactory() );
} catch(Exception ex) {
ex.printStackTrace();
System.exit(1);
}
}
24
Análisis y Uso de Frameworks de Persistencia en Java
La “Connection Factory” se crea en un método estático llamado
‘createConnectionFactory()’. Esta factoría necesita la URL de JDBC, el driver
JDBC, un nombre de usuario y la contraseña. OpenFusion JDO también viene
con una ‘DBHelper’ que busca un fichero de propiedades que contiene las
propiedades a usar de la base de datos.
public static Object createConnectionFactory() {
ManagedConnectionFactoryImpl mcfi = new
ManagedConnectionFactoryImpl();
Object connectionFactory = null;
try {
mcfi.setUserName("scott");
mcfi.setPassword("tiger");
mcfi.setConnectionURL(
"jdbc:oracle:thin:@localhost:1521:thedb");
mcfi.setDBDriver("oracle.jdbc.driver.OracleDriver");
connectionFactory = mcfi.createConnectionFactory();
} catch(Exception e) {
e.printStackTrace();
System.exit(1);
}
return connectionFactory;
}
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
25
Análisis y Uso de Frameworks de Persistencia en Java
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.
26
Análisis y Uso de Frameworks de Persistencia en Java
•
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(Obj
ect[] os)
deletePersistentAll(Obje makeTransientAll(Objec
ct[] os)
t[] os)
makePersistentAll(Col
lection os)
deletePersistentAll(Coll makeTransientAll(Colle
ection os)
ction 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());
27
Análisis y Uso de Frameworks de Persistencia en Java
System.out.println("Home Phone: " +
person.getHomePhone());
System.out.println("Work Phone: " +
person.getWorkPhone());
}
pm.close();
}
Paso 4º: Cambiar el nombre de una persona
El código para cambiar información de una persona de la base de datos es
muy similar al necesario para mostrar la información de las personas, sencillamente,
se ha de ejecutar el método ‘setName()’ sobre la persona correspondiente. Sin
embargo, hay una diferencia muy importante: en este caso se está realizando una
transacción, ya que la fila en la base de datos se ha de modificar. Por tanto, hay que
utilizar el método ‘commit()’ para guardar los cambios, al igual que se ha hecho al
crear las personas. La única diferencia entre esta operación y trabajar con objetos
transitorios es que hay que verificar la transacción.
public void change() {
Person person;
// OBTENCION DEL OBJETO
pm = pmf.getPersistenceManager();
transaction = pm.currentTransaction();
person = (Person) pm.getObjectById(id.elementAt(1),
false);
person.setName("Steve Gerrard");
// VERIFICACIÓN DEL CAMBIO
transaction.commit();
pm.close();
}
28
Análisis y Uso de Frameworks de Persistencia en Java
Paso 5º: Eliminar una persona de la base de datos
Para eliminar un objeto persistido hay que obtenerlo y ejecutar el método
‘deletePersistent()’ sobre el mismo, tal y como se ha mencionado en el Paso 2º. En este
caso, también se está realizando una transacción. Además, el identificador del objeto
también es eliminado.
public void delete() {
pm = pmf.getPersistenceManager();
transaction = pm.currentTransaction();
pm.deletePersistent(pm.getObjectById(id.remove(1),
false));
transaction.commit();
pm.close();
}
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();
29
Análisis y Uso de Frameworks de Persistencia en Java
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:
30
Análisis y Uso de Frameworks de Persistencia en Java
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jdo SYSTEM
"file:/D:/Apps/OpenFusionJDO/xml/schema/jdo.dtd">
<jdo>
<package name="addressbook">
<class name="Person" identity-type="datastore">
</class>
</package>
</jdo>
Este es un fichero de mapeo sencillo. Sin embargo, he aquí un extracto de
uno un poco más complejo que pretende mapear un objeto Departamento con su
correspondiente ‘collection’ de empleados:
<class name="Department" identity-type="datastore">
<field name="name"/>
<field name="employees">
<collection elementtype="com.prismt.j2ee.jdo.examples.appKeyDepartment.Employee">
</collection>
</field>
<field name="manager"/>
</class>
CONSTRUCCIÓN:
Pasos para construir y ejecutar la aplicación
Estos son los pasos a seguir para construir el sistema que permitirá
ejecutar la aplicación:
1. Compilar el Código
31
Análisis y Uso de Frameworks de Persistencia en Java
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\jtaspec1_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
32
Análisis y Uso de Frameworks de Persistencia en Java
-oc
-pd
directory to place the enhanced classes
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
JDOEnhancer:
% java com.prismt.j2ee.jdo.enhancer.JDOEnhancer -oc . -pd
person.jdo -db oracle -od db -cp .
Paso 3º: Preparar la base de datos
El JDOEnhancer es capaz de crear scripts para preparar la base de datos,
siempre que se transmitan las opciones ‘–db baseDeDatos’ y ‘-od
directorioDestino’. El Enhancer creará muchos scripts diferentes, pero uno de
ellos se llama ‘load_all.sql’. El archivo se ha de abrir y cargar en la localización
del SQL pertinente (ej: ‘sqlplus’ en Oracle).
Este es un ejemplo de lo que contiene el fichero de sentencias SQL que
ha sido creado para Oracle:
CREATE SEQUENCE instid_seq INCREMENT BY 1
;
CREATE TABLE JDO_addressbook_Person_SCO
33
Análisis y Uso de Frameworks de Persistencia en Java
(
inst_id INTEGER NOT NULL,
class INTEGER NOT NULL,
JDO_address VARCHAR2(255),
JDO_email VARCHAR2(255),
JDO_homePhone VARCHAR2(255),
JDO_name VARCHAR2(255),
JDO_ssn VARCHAR2(255),
JDO_workPhone VARCHAR2(255)
)
;
CREATE TABLE JDO_addressbook_Person
(
inst_id INTEGER NOT NULL,
class INTEGER NOT NULL,
JDO_address VARCHAR2(255),
JDO_email VARCHAR2(255),
JDO_homePhone VARCHAR2(255),
JDO_name VARCHAR2(255),
JDO_ssn VARCHAR2(255),
JDO_workPhone VARCHAR2(255)
)
;
CREATE TABLE prismjdoProp
(
name VARCHAR2(255) PRIMARY KEY,
value VARCHAR2(255)
)
;
CREATE TABLE prismjdoExtents
(
class_id NUMBER(38,0) PRIMARY KEY,
class_name VARCHAR2(255) UNIQUE,
app_key VARCHAR2(255)
)
;
ALTER TABLE JDO_addressbook_Person_SCO ADD PRIMARY KEY
(inst_id, class)
;
ALTER TABLE JDO_addressbook_Person ADD PRIMARY KEY (inst_id,
class)
;
INSERT INTO prismjdoExtents VALUES(0, 'addressbook.Person',
'com.prismt.j2ee.jdo.spi.DBKey')
;
COMMIT WORK
;
INSERT INTO prismjdoProp VALUES('USE.RDBMS.TRIGGERS', 'true')
;
COMMIT WORK
;
34
Análisis y Uso de Frameworks de Persistencia en Java
Paso 4º: Ejecutar la Aplicación
% java addressbook.PersonPersist
EL LENGUAJE DE CONSULTA JDOQL
JDO define un lenguaje de consulta conocido como JDOQL. Este lenguaje está
embebido dentro del interface ‘javax.jdo.Query’. El ‘PersistenceManager’ de JDO
define los siguientes métodos para construir ejemplares de las clases de implementación
de la consulta:
•
Query newQuery();
•
Query newQuery(Class cls);
•
Query newQuery(Class cls, Collection coll);
•
Query newQuery(Class cls, String filter);
•
Query newQuery(Class cls, Collection c, String filter);
•
Query newQuery(Extent ext);
•
Query newQuery(Extent ext, String filter);
El ‘filter’ se especifica como una expresión booleana que se parece algo a los
operadores booleanos de SQL. El resultado de una consulta depende de si la expresión
booleana se evalúa a ‘true’ por las clases candidatas especificadas. El interface ‘Query’
proporciona el siguiente método para especificar un filtro:
•
void setFilter(String filter);
35
Análisis y Uso de Frameworks de Persistencia en Java
Las clases candidatas se pueden especificar utilizando uno de los siguientes métodos del
interface ‘Query’:
•
void setClass(Class candidateClass);
•
void setCandidates(Collection candidates);
•
void setCandidates(Extent candidates);
El interface ‘Query’ proporciona métodos para ejecutar una consulta. Los parámetros de
la consulta se pueden pasar directamente a cualquiera de estos métodos:
•
Object execute(Object param);
•
Object execute(Object param1, Object param2);
•
Object execute(Object param1, Object param2, Object param3);
•
Object executeWithMap(Map paramMap);
•
Object executeWithArray(Object[] paramArray);
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");
36
Análisis y Uso de Frameworks de Persistencia en Java
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
37
Análisis y Uso de Frameworks de Persistencia en Java
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
Address
Name
CreditCard
customerID;
myAddress;
myName;
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;
}
38
Análisis y Uso de Frameworks de Persistencia en Java
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
39
Análisis y Uso de Frameworks de Persistencia en Java
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;
40
Análisis y Uso de Frameworks de Persistencia en Java
}
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
41
Análisis y Uso de Frameworks de Persistencia en Java
{
id
last_name
first_name
middle_name
street
city
state
zip
credit_number
credit_date
credit_name
credit_type
INTEGER PRIMARY KEY,
CHAR(30),
CHAR(20),
CHAR(20),
CHAR(50),
CHAR(20),
CHAR(2),
CHAR(9),
CHAR(20),
DATE,
CHAR(20),
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
42
Análisis y Uso de Frameworks de Persistencia en Java
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;
}
43
Análisis y Uso de Frameworks de Persistencia en Java
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.
44
Análisis y Uso de Frameworks de Persistencia en Java
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 postcreacció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
45
Análisis y Uso de Frameworks de Persistencia en Java
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;
}
46
Análisis y Uso de Frameworks de Persistencia en Java
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;
47
Análisis y Uso de Frameworks de Persistencia en Java
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();
48
Análisis y Uso de Frameworks de Persistencia en Java
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).
49
Análisis y Uso de Frameworks de Persistencia en Java
import javax.ejb.EntityBean;
public class CustomerBean
implements EntityBean {
int
Address
Name
CreditCard
EntityContext
customerID;
myAddress;
myName;
myCreditCard;
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.
50
Análisis y Uso de Frameworks de Persistencia en Java
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
51
Análisis y Uso de Frameworks de Persistencia en Java
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()
52
Análisis y Uso de Frameworks de Persistencia en Java
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
53
Análisis y Uso de Frameworks de Persistencia en Java
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.
54
Análisis y Uso de Frameworks de Persistencia en Java
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 =
55
Análisis y Uso de Frameworks de Persistencia en Java
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 {
56
Análisis y Uso de Frameworks de Persistencia en Java
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
57
Análisis y Uso de Frameworks de Persistencia en Java
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
58
Análisis y Uso de Frameworks de Persistencia en Java
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();
}
}
59
Análisis y Uso de Frameworks de Persistencia en Java
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
60
Análisis y Uso de Frameworks de Persistencia en Java
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.
61
Análisis y Uso de Frameworks de Persistencia en Java
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
62
Análisis y Uso de Frameworks de Persistencia en Java
bajo el directorio de trabajo, tu despliegue de directorios debería parecerese a
esto:
+lib
cglib2.jar
commons-logging.jar
hibernate2.jar
jta.jar
odmg.jar
commons-collections.jar
dom4j.jar
jdbc2_0-stdext.jar
log4j.jar
OBJETO:
Definición del objeto Evento
Lo primero será crear una clase que represente los eventos que se desean
persistir. Esta será un simple Java Bean, que contenga algunas propiedades.
package de.gloegl.road2hibernate;
public class Event {
private String title;
private Date date;
private Long id;
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
63
Análisis y Uso de Frameworks de Persistencia en Java
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
La propiedad id es una identificador único para el Event. Todos los
objetos persistentes necesitarán dicha id. Cuando se construyen aplicaciones
Hibernate es recomendable mantener dichas ids únicas separadas de la lógica de
la aplicación. Esto impide manipular la id en nuestro código, dejando que
Hibernate se ocupe de ella. De ahí viene porqué el método set de la id es
privado, permitiendo que Hibernate lo utilice (Hibernate podría acceder a los
métodos set y get de propiedades para todas las visibilidades), pero se aísla del
programador.
Este fichero se debe situar en un directorio llamado src en nuestro
directorio de trabajo. El directorio debería aparecer de esta forma:
+lib
<hibernate jars>
+src
+de
+gloegl
+road2hibernate
Event.java
64
Análisis y Uso de Frameworks de Persistencia en Java
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
con la base de datos:
private void store(String title, Date theDate) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDate(theDate);
session.save(theEvent);
tx.commit();
session.close();
} catch (HibernateException e) {
65
Análisis y Uso de Frameworks de Persistencia en Java
}
e.printStackTrace();
}
2º Mostrar los objetos almacenados
Modificando el método main, cuando el parámetro de entrada sea ‘list’,
se mostrarán los eventos persistidos:
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);
} else if (args[0].equals("list")) {
List events = instance.listEvents();
for (int i = 0; i<events.size(); i++) {
Event theEvent = (Event) events.get(i);
System.out.println("Event " + theEvent.getTitle() + "
Time: " + theEvent.getDate());
}
}
System.exit(0);
}
Se está llamando a listEvents() para imprimir todos los objetos Event
contenidos en la lista devuelta. Al llamar a listEvents() es donde se realizan
las transacciones:
66
Análisis y Uso de Frameworks de Persistencia en Java
private List listEvents() {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
List result = session.find("from Event");
tx.commit();
session.close();
return result;
} catch (HibernateException e) {
throw new RuntimeException(e.getMessage());
}
}
EL FICHERO DE MAPEO
Una vez definida la clase para persistir en la base de datos, hay que
especificar a Hibernate cómo persistirla. Para ello es necesario construir un
fichero de mapeo. El fichero de mapeo le dice a Hibernate qué debería
almacenar en la base de datos y cómo.
La estructura exterior de un fichero de mapeo se parece a esto:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//hibernate/hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
</hibernate-mapping>
67
Análisis y Uso de Frameworks de Persistencia en Java
Entre las dos etiquetas <hibernate-mapping>, hay que incluir un
elemento class, donde se declara a que clase se refiere este mapeo y a qué tabla
de la base de datos SQL se debería mapear. La estructura interior del documento
de mapeo se debería parecer a esto:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//hibernate/hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="de.gloegl.road2hibernate.Event" table="EVENTS">
</class>
</hibernate-mapping>
Se le ha indicado a Hibernate que persista la clase Event en la tabla
EVENTS.
Ahora hay que dar a Hibernate la propiedad a utilizar como
identificador único: la propiedad id. Además hay que especificar cómo generar
los ids. Incluyendo esto, así queda el fichero de mapeo:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//hibernate/hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="de.gloegl.road2hibernate.Event" table="EVENTS">
<id name="id" column="uid" type="long">
<generator class="increment"/>
</id>
</class>
</hibernate-mapping>
68
Análisis y Uso de Frameworks de Persistencia en Java
El elemento <id> es la declaración de la propiedad id. name="id" es el
nombre de la propiedad. Hibernate usará los métodos getId y setId para
acceder a ella. El atributo column le dice a Hibernate que cólumna de la tabla
EVENTS
contendrá el id. El atributo type le dice a Hibernate el tipo de la
propiedad - en este caso un long.
El elemento <generator> especifica la técnica que se usará para la
generación de id. En este caso se usa un incremento. Finalmente se deben
incluir las declaraciones para las propiedades persistentes en el fichero de
mapeo:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//hibernate/hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="de.gloegl.road2hibernate.Event" table="EVENTS">
<id name="id" column="uid" type="long">
<generator class="increment"/>
</id>
<property name="date" type="timestamp"/>
<property name="title" column="eventtitle"/>
</class>
</hibernate-mapping>
69
Análisis y Uso de Frameworks de Persistencia en Java
Al principio, igual que en el elemento <id>, el atributo name del
elemento <property> le dice a Hibernate que métodos get y set utilizar. Sin
embargo, la propiedad title contiene un atributo column, y el atributo date no
lo tiene. Esto es posible porque cuando no se utiliza el atributo column,
Hibernate usará por defecto el nombre de la propiedad como el nombre de
columna.
Por otra parte, la propiedad title carece de un atributo type. Otra vez,
Hibernate intentará determinar el tipo correcto por sí mismo. Sin embargo,
algunas veces Hibernate simplemente no puede hacer esto y hay que especificar
el tipo, como es el caso de la propiedad date. Hibernate no puede saber si la
propiedad se mapeará a una columna date, timestamp o time, por eso se debe
que especificar.
El mapeo se sitúa en un fichero llamado Event.hbm.xml en el mismo
directorio donde está la clase Event. Así quedaría la estructura del directorio de
trabajo:
+lib
<hibernate jars>
+src
+de
+gloegl
+road2hibernate
Event.java
Event.hbm.xml
70
Análisis y Uso de Frameworks de Persistencia en Java
CONFIGURACIÓN DE LA BASE DE DATOS
Para configurar Hibernate se necesitan la información de la base de
datos, en este caso HSQLDB, una base de datos SQL en-memoria basada en
Java. Se debe copiar el fichero hsqldb.jar del directorio lib de la descarga al
directorio lib dentro del directorio de trabajo, que quedará de esta forma:
.
+lib
<hibernate jars>
hsqldb.jar
+src
<Aquí va el fichero fuente y el de mapeo>
Además se creará un directorio data justo debajo del directorio de
trabajo, donde hsqldb almacenará sus ficheros.
Ahora se puede configurar Hibernate utilizando un fichero XML, que se
llamará hibernate.cfg.xml y que se situará directamente en el directorio src
del directorio de trabajo. Así queda el fichero:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//hibernate/hibernate Configuration DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
71
Análisis y Uso de Frameworks de Persistencia en Java
<hibernate-configuration>
<session-factory>
<property
name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</proper
ty>
<property
name="hibernate.connection.url">jdbc:hsqldb:data/test</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property
name="dialect">net.sf.hibernate.dialect.HSQLDialect</property>
<property name="show_sql">true</property>
<property name="transaction.factory_class">
net.sf.hibernate.transaction.JDBCTransactionFactory
</property>
<property name="hibernate.cache.provider_class">
net.sf.hibernate.cache.HashtableCacheProvider
</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping
resource="de/gloegl/road2hibernate/data/Event.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Los primeros cuatro elementos <property> contienen la configuración
necesaria para la Conexión JDBC que utilizará Hibernate. La propiedad dialect
especifica el SQLdialect que Hibernate deberá generar. Luego se especifica que
Hibernate delegará las transacciones a la conexión JDBC subyacente y se asigna
un proveedor de caché. La siguiente propiedad le dice a Hibernate que ajuste
automáticamente las tablas en la base de datos de acuerdo al mapeos. Finalmente
se le da el path al fichero de mapeo.
72
Análisis y Uso de Frameworks de Persistencia en Java
CONSTRUCCIÓN Y EJECUCIÓN DEL SISTEMA
1º Construcción
Por conveniencia, se crea un fichero batch en el directorio de trabajo que
contenga todos los comandos necesarios para la complicación. Bajo Windows,
este sería su contenido:
javac -classpath .\lib\hibernate2.jar -d bin
src\de\gloegl\road2hibernate\*.java
copy /Y src\hibernate.cfg.xml bin
copy /Y src\de\gloegl\road2hibernate\*.xml
bin\de\gloegl\road2hibernate
Este fichero se situará con el nombre de build.bat en nuestro directorio de
trabajo. Finalmente se crea el subdirectorio bin en nuestro directorio de trabajo
para situar ahí las clases compiladas.
2º Ejecución
El código que viene a continuación es una clase que arrancará Hibernate.
package de.gloegl.road2hibernate;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.cfg.Configuration;
public class EventManager {
private SessionFactory sessionFactory;
73
Análisis y Uso de Frameworks de Persistencia en Java
public EventManager() {
try {
System.out.println("Initializing Hibernate");
sessionFactory
=
Configuration().configure().buildSessionFactory();
System.out.println("Finished Initializing Hibernate");
} catch (HibernateException e) {
e.printStackTrace();
}
}
new
public static void main(String[] args) {
EventManager instance = new EventManager();
System.exit(0);
}
}
Esta clase simplemente crea un ejemplar de sí mismo, y crea un ejemplar
de SessionFactory en su constructor. El fichero EventManager.java debe
situarse en el directorio adecuado. La estructura de directorios sería la que figura
a continuación:
.
+lib
cglib2.jar
commons-logging.jar
hibernate2.jar
jta.jar
odmg.jar
commons-collections.jar
dom4j.jar
jdbc2_0-stdext.jar
log4j.jar
hsqldb.jar
+src
+de
+gloegl
+road2hibernate
Event.java
Event.hbm.xml
EventManager.java
hibernate.cfg.xml
+data
74
Análisis y Uso de Frameworks de Persistencia en Java
build.bat
Para ejecutar nuestra aplicación se crea otro fichero batch en el directorio
de trabajo bajo el nombre de run.bat, con el siguiente contenido (todo en una
línea):
java -classpath .\lib\hibernate2.jar;.\lib\jta.jar;.\lib\commonslogging.jar;.\lib\hsqldb.jar;
.\lib\cglib2.jar;.\lib\commonscollections.jar;.\lib\dom4j.jar;.\lib\odmg.jar;
.\lib\jdbc2_0-stdext.jar;.\bin de.gloegl.road2hibernate.EventManager
%1 %2 %3 %4 %5
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
75
Análisis y Uso de Frameworks de Persistencia en Java
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
76
Análisis y Uso de Frameworks de Persistencia en Java
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
77
Análisis y Uso de Frameworks de Persistencia en Java
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
78
Análisis y Uso de Frameworks de Persistencia en Java
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
79
Análisis y Uso de Frameworks de Persistencia en Java
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.
80
Análisis y Uso de Frameworks de Persistencia en Java
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.
81
Análisis y Uso de Frameworks de Persistencia en Java
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
82
Análisis y Uso de Frameworks de Persistencia en Java
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.
83
Análisis y Uso de Frameworks de Persistencia en Java
4- Diseño y Desarrollo
de la Aplicación
84
Análisis y Uso de Frameworks de Persistencia en Java
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
85
Análisis y Uso de Frameworks de Persistencia en Java
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
86
Análisis y Uso de Frameworks de Persistencia en Java
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):
87
Análisis y Uso de Frameworks de Persistencia en Java
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
88
Análisis y Uso de Frameworks de Persistencia en Java
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
89
Análisis y Uso de Frameworks de Persistencia en Java
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.
90
Análisis y Uso de Frameworks de Persistencia en Java
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.
91
Análisis y Uso de Frameworks de Persistencia en Java
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
92
Análisis y Uso de Frameworks de Persistencia en Java
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: -
93
Análisis y Uso de Frameworks de Persistencia en Java
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:
94
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
95
Análisis y Uso de Frameworks de Persistencia en Java
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
96
Análisis y Uso de Frameworks de Persistencia en Java
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
97
Análisis y Uso de Frameworks de Persistencia en Java
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.
98
Análisis y Uso de Frameworks de Persistencia en Java
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: 99
Análisis y Uso de Frameworks de Persistencia en Java
DIAGRAMAS DE LOS CASOS DE USO
•
Casos de uso del Personal Informático (INF):
100
Análisis y Uso de Frameworks de Persistencia en Java
•
Casos de uso del Personal Administrativo (ADM):
101
Análisis y Uso de Frameworks de Persistencia en Java
•
Casos de uso del Personal Médico (MED):
102
Análisis y Uso de Frameworks de Persistencia en Java
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.
103
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
104
Análisis y Uso de Frameworks de Persistencia en Java
•
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.
105
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
106
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
107
Análisis y Uso de Frameworks de Persistencia en Java
•
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.
108
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
109
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
110
Análisis y Uso de Frameworks de Persistencia en Java
•
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.
111
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
112
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
113
Análisis y Uso de Frameworks de Persistencia en Java
•
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”.
114
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
115
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
116
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
117
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
118
Análisis y Uso de Frameworks de Persistencia en Java
-
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.
119
Análisis y Uso de Frameworks de Persistencia en Java
•
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.
120
Análisis y Uso de Frameworks de Persistencia en Java
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.
121
Análisis y Uso de Frameworks de Persistencia en Java
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: -
122
Análisis y Uso de Frameworks de Persistencia en Java
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
123
Análisis y Uso de Frameworks de Persistencia en Java
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
124
Análisis y Uso de Frameworks de Persistencia en Java
-
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
125
Análisis y Uso de Frameworks de Persistencia en Java
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.
126
Análisis y Uso de Frameworks de Persistencia en Java
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:
127
Análisis y Uso de Frameworks de Persistencia en Java
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
128
Análisis y Uso de Frameworks de Persistencia en Java
Alergia.java
Noticia.java
129
Análisis y Uso de Frameworks de Persistencia en Java
Usuario.java
130
Análisis y Uso de Frameworks de Persistencia en Java
DIAGRAMAS UML DE CLASES DE ACCESO A LA BASE DE DATOS
DAO_paciente.java
DAO_alergia.java
131
Análisis y Uso de Frameworks de Persistencia en Java
DAO_noticia.java
DAO_usuario.java
132
Análisis y Uso de Frameworks de Persistencia en Java
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.
133
Análisis y Uso de Frameworks de Persistencia en Java
Tabla NOTICIAS
Tabla USUARIOS
134
Análisis y Uso de Frameworks de Persistencia en Java
5- La alternativa a
JDBC: Hibernate
135
Análisis y Uso de Frameworks de Persistencia en Java
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
136
Análisis y Uso de Frameworks de Persistencia en Java
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
private
private
private
private
private
private
private
private
int dni;
String user;
String pass;
String nombre;
String ap1;
String ap2;
String email;
String cod_perfil;
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
137
Análisis y Uso de Frameworks de Persistencia en Java
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) {
138
Análisis y Uso de Frameworks de Persistencia en Java
}
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\">";
}
139
Análisis y Uso de Frameworks de Persistencia en Java
else {
if
((this.cod_perfil).equals(Usuario.PERFIL_ADMINISTRATIVO)) {
iconoPerfil = "<img
src=\"Iconos/perfilAdmMini.jpg\" width=\"40\" height=\"15\">";
}
else {
iconoPerfil = "<img
src=\"Iconos/perfilInfMini.jpg\" width=\"40\" height=\"15\">";
}
}
// Asignación de actividad
if (this.activo == 1) {
iconoActividad = "<img
src=\"Iconos/cuentaActiva.jpg\" width=\"100\" height=\"15\">";
}
else {
iconoActividad = "<img
src=\"Iconos/cuentaInactiva.jpg\" width=\"100\" height=\"15\">";
}
return "<tr>" +
"<td width=\"9%\" align=\"center\" valign=\"middle\">"+
iconoPerfil +"</td>" +
"<td width=\"70%\" align=\"left\" valign=\"middle\">" +
"<div align=\"left\"><font face=\"Verdana, Arial,
Helvetica, sans-serif\" size=\"2\">"+ this.getNombreCompleto()
+"</font></div>" +
"</td>" +
"<td width=\"9%\" align=\"center\" valign=\"middle\">" +
"<div align=\"center\"><input type=\"radio\"
name=\"rbCuenta\" value=\""+ this.dni +"\"></div>" +
"</td>" +
"<td width=\"12%\" align=\"center\" valign=\"middle\">" +
"<div align=\"center\">"+ iconoActividad +"</div>" +
"</td>" +
"</tr>";
}
}
Cabe destacar que, entre los constructores se encuentra el constructor por
defecto, necesario para que Hibernate trabaje con los objetos “Usuario”. Como se
describe en el siguiente apartado (5.2- Los ficheros de mapeo), “dni” será la clave de la
tabla correspondiente a la hora de persistir esta clase.
140
Análisis y Uso de Frameworks de Persistencia en Java
-
Paciente.java
En la clase Paciente nos encontramos con el atributo “dni”, que
será la clave de la tabla correspondiente.
Este es el código final de la clase “Paciente.java”:
package obj;
public class Paciente {
// Atributos
private int dni;
private int dni_med;
private String nombre;
private String ap1;
private String ap2;
private String telefono;
// Constructores
public Paciente (){
}
public Paciente (int dni){
this.dni = dni;
}
public Paciente (int dni, int dni_med, String nombre, String
ap1, String ap2, String telefono){
this.dni = dni;
this.dni_med = dni_med;
this.nombre = nombre;
this.ap1 = ap1;
this.ap2 = ap2;
this.telefono = telefono;
}
// Getters y Setters
public String getAp1() {
return ap1;
}
public void setAp1(String ap1) {
this.ap1 = ap1;
}
141
Análisis y Uso de Frameworks de Persistencia en Java
public String getAp2() {
return ap2;
}
public void setAp2(String ap2) {
this.ap2 = ap2;
}
public int getDni() {
return dni;
}
public void setDni(int dni) {
this.dni = dni;
}
public int getDni_med() {
return dni_med;
}
public void setDni_med(int dni_med) {
this.dni_med = dni_med;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getTelefono() {
return telefono;
}
public void setTelefono(String telefono) {
this.telefono = telefono;
}
//------- Otros Métodos
public String getNombreCompleto() {
String res = this.getAp1() +" "+ this.getAp2()+", "+
this.getNombre();
return res;
}
}
142
Análisis y Uso de Frameworks de Persistencia en Java
-
Alergia.java
Esta clase es, aparentemente igual que las demás, pero en el
código se pueden observar algunos detalles interesantes:
package obj;
import java.io.Serializable;
public class Alergia implements Serializable{
// Atributos
private int dni;
private String tipo;
private String tratamiento;
private String notas;
// Constructores
public Alergia (int dni, String tipo, String tratamiento, String
notas){
this.dni = dni;
this.tipo = tipo;
this.tratamiento = tratamiento;
this.notas = notas;
}
public Alergia (){
}
// Getters y Setters
public String getTipo() {
return tipo;
}
public void setTipo(String tipo) {
this.tipo = tipo;
}
public int getDni() {
return dni;
}
public void setDni(int dni) {
this.dni = dni;
}
public String getNotas() {
143
Análisis y Uso de Frameworks de Persistencia en Java
}
return notas;
public void setNotas(String notas) {
this.notas = notas;
}
public String getTratamiento() {
return tratamiento;
}
public void setTratamiento(String tratamiento) {
this.tratamiento = tratamiento;
}
// OTROS MÉTODOS
public boolean equals(Object obj){
boolean res = false;
if (obj instanceof Alergia){
Alergia a = (Alergia)obj;
if (dni==a.getDni() && tipo.equals(a.getTipo())){
res = true;
}
}
System.out.println("Ejecuta EQUALS");
return res;
}
public int hashCode(){
System.out.println("Ejecuta HASHCODE");
return dni + tipo.hashCode();
}
}
La clase “Alergia.java” difiere del resto porque:

implementa el Interface “Serializable”

redefine los métodos “equals()” y “hashCode()”
Esto se debe a que la aplicación se encarga de que un paciente
determinado tenga un registro de “Alergia” por cada tipo de alergia que
padezca. Lógicamente esto quiere decir que los valores de “dni” y “tipo”
formarán una clave compuesta en la tabla correspondiente. Para manejar
144
Análisis y Uso de Frameworks de Persistencia en Java
clases con este tipo de clave, Hibernate necesita que se codifiquen dichas
requerimientos en la clase correspondiente.
-
Noticia.java
Esta es la clase más sencilla e independiente de la aplicación. Este
el código final de la clase:
package obj;
public class Noticia {
// Atributos
private String fecha;
private String titulo;
private String cuerpo;
private int codigo;
// Constructores
public Noticia (){
}
public Noticia (int codigo){
this.codigo = codigo;
}
public Noticia (String fecha, String titulo, String cuerpo, int
codigo){
this.fecha = fecha;
this.titulo = titulo;
this.cuerpo = cuerpo;
this.codigo = codigo;
}
// MÉTODOS
// Getters y Setters
public String getCuerpo() {
return cuerpo;
}
public void setCuerpo(String cuerpo) {
this.cuerpo = cuerpo;
}
145
Análisis y Uso de Frameworks de Persistencia en Java
public String getFecha() {
return fecha;
}
public void setFecha(String fecha) {
this.fecha = fecha;
}
public String getTitulo() {
return titulo;
}
public void setTitulo(String titulo) {
this.titulo = titulo;
}
public int getCodigo() {
return codigo;
}
public void setCodigo(int codigo) {
this.codigo = codigo;
}
// Otros Métodos
public String toHTML(){
return "<table width=\"75%\" border=\"0\" height=\"108\">"
+
"<tr>" +
"<td height=\"11\" bgcolor=\"#000000\"><font face=\"Verdana,
Arial, Helvetica, sans-serif\" color=\"#FFFFFF\">" +
"<font size=\"2\"><img src=\"Iconos/dot.gif\" width=\"12\"
height=\"12\"> - " + this.fecha +" - <b>"+ this.titulo
+"</b></font></font></td>" +
"</tr>" +
"<tr>" +
"<td valign=\"top\" align=\"left\" height=\"70\"><font
face=\"Verdana, Arial, Helvetica, sans-serif\" size=\"1\">" +
this.cuerpo +"</font></td>" +
"</tr>" +
"<tr>" +
"<img src=\"Iconos/separador.jpg\" width=\"600\"
height=\"6\">" +
"</tr>" +
"</table>";
}
public String getInfo() {
return " " + this.fecha + " - " + this.titulo;
}
}
146
Análisis y Uso de Frameworks de Persistencia en Java
5.2- LOS FICHEROS DE MAPEO
Hibernate necesita saber de qué forma ha de hacer corresponder una clase
con una tabla de la base de datos. Aquí entran en juego los ficheros de mapeo
XML. El ellos se especifica, entre otras cosas, el nombre de la tabla que se
quiere crear, el nombre de las columnas y los atributos que forman la clave. Con
esta información Hibernate es capaz de relacionar los atributos con las columnas
de la tabla, definiendo los tipos de datos basándose en el código de la clase
correspondiente.
A continuación figuran los ficheros de mapeo de las diferentes clases a
persistir.
147
Análisis y Uso de Frameworks de Persistencia en Java
-
Usuario.hbm.xml
Este es el código para mapear la clase “Usuario.java”:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//hibernate/hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="obj.Usuario" table="USUARIOS">
<id name="dni" column="dni">
<generator class="assigned"/>
</id>
<property
<property
<property
<property
<property
<property
<property
<property
name="user" column="user"/>
name="pass" column="pass"/>
name="nombre" column="nombre"/>
name="ap1" column="apellido1"/>
name="ap2" column="apellido2"/>
name="email" column="email"/>
name="cod_perfil" column="cod_perfil"/>
name="activo" column="activado"/>
</class>
</hibernate-mapping>
Entre otras cosas, el fichero le dice a Hibernate que persista la
clase “obj.Usuario” en la tabla “USUARIOS”. Además en la sección
<id> se define el atributo “dni” como clave de la tabla. Al elegir
“assigned” en el apartado <generator> se está indicando que no se use
ningún generador, que el valor que lleve el atributo “dni” se persista en la
base de datos.
148
Análisis y Uso de Frameworks de Persistencia en Java
-
Paciente.hbm.xml
Este es el código para mapear la clase “Paciente.java”:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//hibernate/hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="obj.Paciente" table="PACIENTES">
<id name="dni" column="dni">
<generator class="assigned"/>
</id>
<property
<property
<property
<property
<property
name="dni_med" column="dni_med"/>
name="nombre" column="nombre"/>
name="ap1" column="ap1"/>
name="ap2" column="ap2"/>
name="telefono" column="telefono"/>
</class>
</hibernate-mapping>
149
Análisis y Uso de Frameworks de Persistencia en Java
-
Alergia.hbm.xml
Este es el código para mapear la clase “Alergia.java”:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//hibernate/hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="obj.Alergia" table="ALERGIAS">
<!-- ID COMPUESTO: Requiere que obj.Alergia implemente Serializable-->
<composite-id >
<key-property name="dni" column="dni" />
<key-property name="tipo" column="tipo" />
</composite-id>
<property name="tratamiento" column="tratamiento"/>
<property name="notas" column="notas"/>
</class>
</hibernate-mapping>
Aquí se puede observar cómo se mapea una clave compuesta. Se
ha de utilizar la cláusula <composite-id> indicando qué atributos van a
formar la clave. En este caso “dni” y “tipo” serán la clave compuesta de
la tabla “ALERGIAS”.
150
Análisis y Uso de Frameworks de Persistencia en Java
-
Noticia.hbm.xml
Este es el código para mapear la clase “Noticia.java”:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//hibernate/hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="obj.Noticia" table="NOTICIAS">
<id name="codigo" column="codigo">
<generator class="assigned"/>
</id>
<property name="fecha" column="fecha"/>
<property name="titulo" column="titulo"/>
<property name="cuerpo" column="cuerpo"/>
</class>
</hibernate-mapping>
151
Análisis y Uso de Frameworks de Persistencia en Java
5.3- LAS CLASES GESTORAS DE OBJETOS
Al igual que en JDBC se trabaja con clases DAO para definir los
métodos necesarios para que la aplicación interaccione con la base de datos,
Hibernate utiliza unas clases similares, que denominamos Clases Gestoras.
En las clases gestoras figuran todos los métodos que usa el programador
para realizar transacciones con las tablas. Se debe crear una clase gestora por
cada clase que se desee persistir. De este modo se deberá crear una instancia de
la clase gestora siempre que se quiera realizar una transacción de cualquiera de
los objetos.
A continuación se muestran las clases gestoras que se han implementado
para utilizar Hibernate en la aplicación diseñada. Se pretende comparar estas
clases con las DAO equivalentes que se usan al trabajar con JDBC.
152
Análisis y Uso de Frameworks de Persistencia en Java
-
GestorUsuario.java
Tal y como se puede observar en el código, el constructor de
todas estas clases crea una instancia de “SessionFactory”, sobre la cual se
van a realizar todas y cada una de las transacciones.
package util;
import java.util.Iterator;
import obj.Usuario;
import
import
import
import
import
import
org.hibernate.HibernateException;
org.hibernate.Query;
org.hibernate.Session;
org.hibernate.SessionFactory;
org.hibernate.Transaction;
org.hibernate.cfg.Configuration;
public class GestorUsuario {
private SessionFactory sessionFactory;
public GestorUsuario() {
try {
System.out.println("Initializing Hibernate");
sessionFactory = new
Configuration().configure().buildSessionFactory();
System.out.println("Finished Initializing Hibernate");
} catch (HibernateException e) {
e.printStackTrace();
}
}
public Usuario getUsuario(int dni) {
Usuario res = null;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
/* Con .get() */
res = (Usuario)session.get(Usuario.class, new
Integer(dni));
/* Con QUERY: */
153
Análisis y Uso de Frameworks de Persistencia en Java
//
String dniString = String.valueOf(dni);
//
res = (Usuario)session.createQuery("from Usuario as
usuario where usuario.dni = ?")
//
.setString(0,dniString)
//
.uniqueResult();
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
return res;
}
public void insertarUsuario (Usuario u)
{
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(u);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
// Comprueba si existe el "User" para el login. La comprobación
// se realiza durante la solicitud de cuentas.
public boolean existeUsuario(String s) {
boolean res = false;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Usuario u_aux = (Usuario)session.createQuery("from Usuario
as usuario where usuario.user = ?")
.setString(0,s)
.uniqueResult();
if (u_aux != null){
res = true;
}
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
154
Análisis y Uso de Frameworks de Persistencia en Java
return res;
}
//
Comprueba si existe el "dni". La comprobación
// se realiza durante la solicitud de cuentas.
public boolean existeDni(String dni) {
boolean res = false;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Usuario u_aux = (Usuario)session.createQuery("from Usuario
as usuario where usuario.dni = ?")
.setString(0,dni)
.uniqueResult();
if (u_aux != null){
res = true;
}
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
return res;
}
public void borrarCuenta(int dni) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Usuario u = this.getUsuario(dni);
session.delete(u);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
public Iterator obtenerUsuarios(){
Iterator res = null;
try {
155
Análisis y Uso de Frameworks de Persistencia en Java
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
res = session.createQuery("from Usuario")
.list()
.iterator();
tx.commit();
session.close();
}
} catch (HibernateException e) {
e.printStackTrace();
}
return res;
public Iterator obtenerMedicos(){
Iterator res = null;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
res = session.createQuery("from Usuario as usuario where
usuario.cod_perfil=?")
.setString(0,"med")
.list()
.iterator();
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
return res;
}
public void cambiarActivado(int dni) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Usuario u_aux = this.getUsuario(dni);
int actividad = u_aux.getActivo();
if (actividad==0){
u_aux.setActivo(1);
}
else{
u_aux.setActivo(0);
}
session.update(u_aux);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
156
Análisis y Uso de Frameworks de Persistencia en Java
}
}
public void editarCuenta(Usuario u) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.update(u);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
public void cambiarPass(int dni, String nuevaPass) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Usuario u = this.getUsuario(dni);
u.setPass(nuevaPass);
session.update(u);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
// Validación del LOGIN
// Si los datos son válidos, devuelve el usuario con todos sus
datos.
public Usuario validarUsuario(String user, String pass) {
Usuario res = null;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
res = (Usuario)session.createQuery("from Usuario as
usuario where usuario.user = ? and usuario.pass= ?")
.setString(0,user)
.setString(1,pass)
.uniqueResult();
tx.commit();
157
Análisis y Uso de Frameworks de Persistencia en Java
session.close();
}
catch (HibernateException e){
e.printStackTrace();
}
}
return res;
}
Para hacerse una idea de cómo Hibernate evita las tareas de
encapsulamiento y desencapsulamiento, se puede observar el método
“editarCuenta(Usuario u)“ y compararlo con otro equivalente
de una clase DAO:
// Con HIBERNATE:
public void editarCuenta(Usuario u) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.update(u);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
// 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();
158
Análisis y Uso de Frameworks de Persistencia en Java
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
“session.update(u)”,
notable.
comprobando
Hibernate
el
se
campo
sirve
clave
con
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.
159
Análisis y Uso de Frameworks de Persistencia en Java
-
GestorPaciente.java
Para trabajar con la clase Paciente se usará esta clase gestora:
package util;
import java.util.Iterator;
import obj.Paciente;
import
import
import
import
import
import
org.hibernate.HibernateException;
org.hibernate.Query;
org.hibernate.Session;
org.hibernate.SessionFactory;
org.hibernate.Transaction;
org.hibernate.cfg.Configuration;
public class GestorPaciente {
private SessionFactory sessionFactory;
public GestorPaciente() {
try {
System.out.println("Initializing Hibernate");
sessionFactory = new
Configuration().configure().buildSessionFactory();
System.out.println("Finished Initializing Hibernate");
} catch (HibernateException e) {
e.printStackTrace();
}
}
public void insertarPaciente(Paciente p) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(p);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
public Paciente getPaciente(int dni) {
160
Análisis y Uso de Frameworks de Persistencia en Java
Paciente res = null;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
/* Con .get() */
res = (Paciente)session.get(Paciente.class, new
Integer(dni));
/* Con QUERY: */
//
String dniString = String.valueOf(dni);
//
res = (Paciente)session.createQuery("from Paciente as
paciente where paciente.dni = ?")
//
.setString(0,dniString)
//
.uniqueResult();
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
return res;
}
public void borrarPaciente(Paciente p) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.delete(p);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
public boolean existePaciente(int dni) {
boolean res = false;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Paciente p = (Paciente)session.get(Paciente.class, new
Integer(dni));
if (p != null){
res = true;
}
tx.commit();
session.close();
} catch (HibernateException e) {
161
Análisis y Uso de Frameworks de Persistencia en Java
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
return res;
}
public void editarPaciente(Paciente p) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.update(p);
// Otro método:
//
Paciente p_old = (Paciente)session.get(Paciente.class,
new Integer(p.getDni()));
//
//
p_old.setDni_med(p.getDni_med());
//
p_old.setNombre(p.getNombre());
//
p_old.setAp1(p.getAp1());
//
p_old.setAp2(p.getAp2());
//
p_old.setTelefono(p.getTelefono());
//
//
session.flush(); //Hibernate guarda los cambios en
"p_old"
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
public Iterator obtenerPacientes(){
Iterator res = null;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
res = session.createQuery("from Paciente")
.list()
.iterator();
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
return res;
}
162
Análisis y Uso de Frameworks de Persistencia en Java
public Iterator obtenerPacientesAsignados(int dni_med){
Iterator res = null;
String dniString = String.valueOf(dni_med);
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
res = session.createQuery("from Paciente as paciente where
paciente.dni_med= ?")
.setString(0,dniString)
.list()
.iterator();
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
return res;
}
}
163
Análisis y Uso de Frameworks de Persistencia en Java
-
GestorAlergia.java
Para trabajar con la clase Alergia se usará esta clase gestora:
package util;
import java.util.Iterator;
import obj.Alergia;
import
import
import
import
import
import
org.hibernate.HibernateException;
org.hibernate.Query;
org.hibernate.Session;
org.hibernate.SessionFactory;
org.hibernate.Transaction;
org.hibernate.cfg.Configuration;
public class GestorAlergia {
private SessionFactory sessionFactory;
public GestorAlergia() {
try {
System.out.println("Initializing Hibernate");
sessionFactory = new
Configuration().configure().buildSessionFactory();
System.out.println("Finished Initializing Hibernate");
} catch (HibernateException e) {
e.printStackTrace();
}
}
public void insertarAlergia(Alergia a) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(a);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
public Alergia getAlergia(int dni, String tipo) {
164
Análisis y Uso de Frameworks de Persistencia en Java
/* 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();
165
Análisis y Uso de Frameworks de Persistencia en Java
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();
166
Análisis y Uso de Frameworks de Persistencia en Java
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
return it;
}
}
167
Análisis y Uso de Frameworks de Persistencia en Java
-
GestorNoticia.java
Para trabajar con la clase Paciente se usará esta clase gestora:
package util;
import java.util.Iterator;
import java.util.ListIterator;
import obj.Alergia;
import obj.Noticia;
import obj.Paciente;
import
import
import
import
import
org.hibernate.HibernateException;
org.hibernate.Session;
org.hibernate.SessionFactory;
org.hibernate.Transaction;
org.hibernate.cfg.Configuration;
public class GestorNoticia {
private SessionFactory sessionFactory;
public GestorNoticia() {
try {
System.out.println("Initializing Hibernate");
sessionFactory = new
Configuration().configure().buildSessionFactory();
System.out.println("Finished Initializing Hibernate");
} catch (HibernateException e) {
e.printStackTrace();
}
}
public Noticia getNoticia(int codigo) {
Noticia res = null;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
/* Con .get() */
res = (Noticia)session.get(Noticia.class, new
Integer(codigo));
/* Con QUERY: */
//
String codigoString = String.valueOf(codigo);
//
res = (Noticia)session.createQuery("from Noticia as
noticia where noticia.codigo = ?")
//
.setString(0,codigoString)
168
Análisis y Uso de Frameworks de Persistencia en Java
//
tx.commit();
session.close();
.uniqueResult();
} catch (HibernateException e) {
e.printStackTrace();
}
return res;
}
public void nuevaNoticia(Noticia n) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(n);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
public void borrarNoticia(Noticia n) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.delete(n);
tx.commit();
session.close();
}
} catch (HibernateException e) {
e.printStackTrace();
}
public void editarNoticia(Noticia n) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.update(n);
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
169
Análisis y Uso de Frameworks de Persistencia en Java
public ListIterator obtenerNoticias(){
ListIterator res = null;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
res = session.createQuery("from Noticia")
.list()
.listIterator();
tx.commit();
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
return res;
}
// Vuelve a enumerar los códigos de las noticias:
// ... se utilizará despues de una operación de baja.
// Devuelve el número de noticias que hay.
public Integer recodificarNoticias() {
int cont = 1;
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
ListIterator noticias = this.obtenerNoticias();
if (noticias!=null) {
while (noticias.hasNext())
{
Noticia n = (Noticia)noticias.next();
int codigo_aux = n.getCodigo();
Noticia n_aux = this.getNoticia(codigo_aux);
n_aux.setCodigo(cont);
this.borrarNoticia(n);
this.nuevaNoticia(n_aux);
}
cont++;
}
tx.commit();
session.close();
} catch (HibernateException e) {
System.out.println("ERROR: hib exception en
recodificarNoticias()");
170
Análisis y Uso de Frameworks de Persistencia en Java
}
}
e.printStackTrace();
Integer res = new Integer(cont - 1);
return res;
}
171
Análisis y Uso de Frameworks de Persistencia en Java
5.4- IMPLANTACIÓN
5.4.1. Instalación y Configuración
Primero hay que bajarse Hibernate 3.0 de su página de descarga. Después
hay que extraerlo y colocar los .jar la carpeta lib del proyecto Web, así como el
conector de la base de datos MySQL.
La configuración de Hibernate se realiza a través de un archivo XML
llamado “hibernate.cfg.xml” que se situará en la carpeta “JavaSource”. En la
página siguiente se puede ver el código del archivo, con los datos necesarios
para adaptarlo a esta aplicación.
Como se puede apreciar, en las secciones <property> se especifica todo
lo necesario para realizar la conexión a la base de datos MySQL “clinica_paya”,
incluyendo el usuario y la contraseña. Posteriormente, con las etiquetas
<mapping> se está indicando a Hibernate que tiene cuatro objetos para persistir,
uno por cada uno de los ficheros de mapeo creados en el apartado anterior.
Hibernate tomará esta información y será capaz de crear las tablas especificadas
por los ficheros de mapeo.
172
Análisis y Uso de Frameworks de Persistencia en Java
Hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools.
<hibernate-configuration>
-->
<session-factory>
<property name="connection.username">anonimo</property>
<property
name="connection.url">jdbc:mysql://localhost:3306/clinica_paya</proper
ty>
<property
name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property
name="myeclipse.connection.profile">MySQL_personal</property>
<property name="connection.password">anonimo</property>
<property
name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping
<mapping
<mapping
<mapping
resource="obj/Alergia.hbm.xml"></mapping>
resource="obj/Noticia.hbm.xml"></mapping>
resource="obj/Usuario.hbm.xml"></mapping>
resource="obj/Paciente.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>
Cabe destacar que esta forma de configurar Hibernate permite una
sencillísima portabilidad entre diferentes entornos de bases de datos. Si se quiere
trasladar a otra base de datos con otro gestor, basta con editar algunas de las
propiedades de este fichero referentes a la base de datos.
Para no tener que trabajar con los XML existen asistentes para la edición
de este archivo y para la creación de ficheros de mapeo.
173
Análisis y Uso de Frameworks de Persistencia en Java
5.4.2. Requisitos del Sistema (Hibernate 3.0):
o JDK 1.3 o superior
o 128 Mb de RAM
o 50 Mb de espacio en disco
o 400 Mhz CPU
174
Análisis y Uso de Frameworks de Persistencia en Java
6- Presupuesto
175
Análisis y Uso de Frameworks de Persistencia en Java
6- PRESUPUESTO
Los costes establecidos se basan en que la empresa contratante dispone
del hardware requerido y que el autor del proyecto no tiene la condición de
ingeniero técnico titulado.
COSTES DE DESARROLLO
• Estudio......................................................................
80 horas x 26 €/h = 2.080 €
• Análisis.....................................................................
80 horas x 26 €/h = 2.080 €
• Programación..........................................................100
horas x 24 €/h = 2.400 €
COSTES DE IMPLANTACIÓN
•
Configuración y pruebas............................................. 40 horas x 20 €/h = 800 €
TOTAL..................................7.360 €
176
Análisis y Uso de Frameworks de Persistencia en Java
7- Conclusiones
177
Análisis y Uso de Frameworks de Persistencia en Java
7- CONCLUSIONES
Este trabajo ha hecho posible confirmar que el manejo de las bases de
datos es crítico para el comportamiento de una aplicación.
La aplicación Web se ha desarrollado utilizando Hibernate, pero
paralelamente se ha codificado el módulo equivalente en JDBC. Esto ha
permitido que percepción del contraste sea completa, haciendo posible reafirmar
las conclusiones obtenidas tras realizar el estudio teórico.
Tras la conclusión del desarrollo se ha comprobado que la programación
con Hibernate es mucho más sencilla y llevadera, ya que nos libera de tareas tan
ásperas como el encapsulamiento y desencapsulamiento de los objetos, y pone a
nuestra disposición una API completísima y fácil de usar. Sin embargo, después
de concluir con la implantación del portal, ha quedado patente que los accesos
con JDBC son siempre más rápidos que los gestionados por un framewok como
Hibernate, tal y como se había predecido en el estudio.
Estas conclusiones se corresponden perfectamente con las pretensiones
del proyecto. La intención del trabajo era confrontar y mostrar el funcionamiento
de las alternativas, creando finalmente una herramienta de trabajo sencilla y
versátil.
178
Análisis y Uso de Frameworks de Persistencia en Java
La realización de este proyecto me ha aportado una grandísima
experiencia personal y académica.
Este es un proyecto muy completo en muchos aspectos. Tiene gran
variedad de fases, las cuales se han abordado de formas distintas, lo que requiere
una planificación diferente para cada una de ellas. Por otra parte, el desarrollo de
la aplicación ha sido posible gracias al aprendizaje de múltiples herramientas
software, ampliando así mis conocimientos en un gran rango de materias.
El director del proyecto me ha sabido transmitir qué tipo de proyecto
tenía en mente. La filosofía seguida a lo largo del mismo ha conseguido que la
documentación tome continuidad entre sus capítulos y sea entretenida su lectura.
179
Análisis y Uso de Frameworks de Persistencia en Java
8- Bibliografía
180
Análisis y Uso de Frameworks de Persistencia en Java
8- BIBLIOGRAFÍA
Libros consultados:
[MONS04]
Monson-Haefel R. “Enterprise JavaBeans”, O’Reilly, 4ª
Edición, 2004.
[BERG03]
Bergsten H. “JavaServer Pages”, O’Reilly, 3ª Edición, 2003.
[SING02]
Singh I. “Designing Enterprise Applications with the J2EE
Platform”, Addison Wesley, 2ª Edición, 2002.
[HUNT01]
Hunter J. “Java Servlet Programming”, O’Reilly, 2ª Edición,
2001.
[BARR01]
Barranco J. “Metodología del análisis estructurado de
sistemas”, Publicaciones Universidad Pontificia de Comillas, 2ª
Edición, Madrid, 2001.
[FOWL99]
Fowler, M. “UML gota a gota”, Addison Wesley, México 1999.
[GOSL96]
Gosling, J. “The Java Programming Language”, Addison
Wesley, Massachusetts 1996.
181
Análisis y Uso de Frameworks de Persistencia en Java
Otras fuentes:
Página oficial de Hibernate: www.hibernate.org
Web sobre JDO: www.JDOcentral.com
Programación en castellano: www.programación.com
182