Está en la página 1de 193

UNIVERSIDAD PONTIFICIA COMILLAS

ESCUELA TCNICA SUPERIOR DE INGENIERA (ICAI)


INGENIERO TCNICO EN INFORMTICA DE GESTIN INGENIERO TCNICO EN INFORMTICA DE SISTEMAS

PROYECTO FIN DE CARRERA

ANLISIS Y USO DE FRAMEWORKS DE PERSISTENCIA EN JAVA

Autor: Alfredo Pay Martn Director: Jos Miguel Ordax Cass

Anlisis 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 das de vacaciones.

A todos mis amigos y compaeros de clase, por haberme animado y apoyado durante todos los aos de carrera.

Anlisis y Uso de Frameworks de Persistencia en Java

Resumen

II

Anlisis y Uso de Frameworks de Persistencia en Java

RESUMEN

Este proyecto pretende realizar un anlisis completo de las diferentes alternativas que hay para conseguir la persistencia de datos en Java. A continuacin, se construir una aplicacin Web para la explotacin 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 terica y otra prctica.

La motivacin que inspira este proyecto es fcil de explicar. Lo ms importante para una empresa son los datos que maneja. Todos los elementos que conforman una empresa estn reflejados en datos, desde los empleados hasta los clientes, desde los recursos que posee hasta los productos que vende, etc. La informacin y caractersticas asociadas de estos elementos siempre pueden ser tiles y, en otros casos, indispensables para el funcionamiento de la empresa.

Qu sera 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 corazn de las empresas y, por esta razn, es crucial la forma de manejarlos.

Toda la informacin 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 informacin toman un papel importante en las operaciones rutinarias empresariales, es normal que la forma de explotar esos datos III

Anlisis y Uso de Frameworks de Persistencia en Java tenga una repercusin directa en la eficiencia de la empresa. Dada la trascendencia que toman los accesos a dicha informacin, se puede afirmar que la forma de realizar consultas a las bases de datos es tan importante como el diseo de sus tablas.

Hoy en da Java sigue siendo un lenguaje en pleno desarrollo. Su falta de sencillez a la hora de trabajar con bases de datos, ha provocado la aparicin de diferentes frameworks que facilitan estas tareas. Existen diversas alternativas que aportan mtodos diferentes: Hibernate, EJBs, 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 prcticas de esta tecnologa veremos que una gran forma de aprovechar estas tecnologas es la explotacin de tablas en un entorno Web. Por ejemplo, en una empresa sera de gran utilidad que, a travs de un portal comn, 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 servira a todos los componentes de la empresa. Todo el mundo tendra un acceso cmodo, rpido y sin intermediarios a la informacin que necesite en cada momento, dentro de una seleccin de los datos ms usados por los departamentos. A su vez, el departamento de informtica sera el encargado del mantenimiento del portal. Esto se puede realizar con tecnologa J2EE y una de las alternativas de persistencia de datos.

IV

Anlisis 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 companys efficiency. This means that the way used to get the information is as important as the data base design

Anlisis 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

Anlisis y Uso de Frameworks de Persistencia en Java

ndice

VII

Anlisis y Uso de Frameworks de Persistencia en Java

NDICE

1. Introduccin...1 2. Definicin del Problema3 3. Anlisis de las Tecnologas...6 3.1. 3.2. Objetivos7 Alternativas de Persistencia...9 3.2.1. Introduccin.9 El Mapeo Objeto-Relacional (ORM).9 JDBC: Componente indispensable para los ORM...12 3.2.2. Tecnologas basadas en el estndar15 Java Data Objects (JDO) Definicin.15 Enterprise Java Beans (EJB) de Entidad Definicin.18 3.2.3. Tecnologas Open Source: Hibernate Definicin...20 3.3. Funcionamiento de las Alternativas.21 3.3.1. Tecnologas basadas en el estndar21 Java Data Objects (JDO) Funcionamiento21 Crear un Objeto21 Crear un Gestor de Persistencia23 Crear un Descriptor JDO para el JDOEnhancer...30 Construir y Ejecutar la Aplicacin...31 El Lenguaje de Consulta JDOQL.35 Enterprise Java Beans (EJB) de Entidad Funcionamiento37 Persistencia Manejada por el Contenedor (CMP)37 VIII

Anlisis y Uso de Frameworks de Persistencia en Java La Clase Bean..38 Interface Home.43 Interface Remoto..46 Mtodos de Retrollamada.48 Persistencia Manejada por el Bean (BMP)..53 3.3.2. Tecnologas Open Source: Hibernate Funcionamiento..62 Creacin del Objeto..63 Persistencia...65 El Fichero de Mapeo67 Configuracin de la Base de Datos..71 Construccin y Ejecucin.73 3.4. Evaluacin...76 JDO vs. EJB.....................................76 JDO vs. JDBC/SQL.77 Hibernate vs. JDO79 3.5. Conclusiones80

4. Diseo y Desarrollo de la Aplicacin Web.84 4.1. 4.2. 4.3. Objetivos..85 Descripcin de la Aplicacin...86 Requisitos funcionales.87 Actores Participantes87 Casos de uso.88 Descripcin detallada de los Casos de Uso..90 Diagramas de Casos de Uso...100 4.4. Diseo Externo..103 IX

4.3.1. 4.3.2.

Anlisis y Uso de Frameworks de Persistencia en Java 4.4.1. Diseo del Interfaz del Usuario.103 Inicio...103 Navegacin Bsica.105 Gestin de Pacientes...108 Gestin de Alergias111 Gestin del Portal (Noticias y Cuentas de Usuario)...114 Cierre de Sesin..120 4.5. Diseo Interno121 JSP y Servlets.121 Diagrama de navegacin126 Diagramas de clases...127 Clases Objeto..128 Clases de Acceso a la Base de Datos.131 4.5.4. Modelo de datos.133

4.5.1. 4.5.2. 4.5.3.

5. La alternativa a JDBC: Hibernate..135 5.1. 5.2. 5.3. 5.4. Las clases a persistir..136 Los ficheros de mapeo...147 Las clases gestoras de objetos152 Implantacin..172 Instalacin y Configuracin...172 Requisitos del Sistema...174

5.4.1. 5.4.2.

6. Presupuesto175 7. Conclusiones..177 8. Bibliografa180

Anlisis y Uso de Frameworks de Persistencia en Java

1- Introduccin

Anlisis y Uso de Frameworks de Persistencia en Java

1- INTRODUCCIN

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 aplicacin real. Una forma de abordar el problema es realizar un anlisis de las alternativas ms importantes que estn a nuestra disposicin.

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 tecnologas tiene su propio origen y filosofa para alcanzar el mismo fin y, por esta razn, no ser fcil analizar sus ventajas y desventajas frente a las dems alternativas.

Una vez terminado el anlisis de las tecnologas, se proceder a disear una aplicacin Web que se caracterice por su necesidad de persistir objetos. Dicha aplicacin 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 aplicacin una de las tecnologas analizadas. Dicha tecnologa ser seleccionada por ser la ms adecuada, y se encargar de realizar la tarea de persistir objetos, sirviendo de enlace entre la lgica y la interaccin con una base de datos. La aplicacin ser construida en un principio con JDBC y sentencias SQL de forma que, al introducir la tecnologa, se podr ver claramente la gran funcin que es capaz de desempear un framework de persistencia.

Anlisis y Uso de Frameworks de Persistencia en Java

2- Definicin del Problema

Anlisis y Uso de Frameworks de Persistencia en Java

2- DEFINICIN DEL PROBLEMA

La

persistencia

de

datos en Java viene facilitada

por mapeadores

Objeto/Relacionales (O/R). Estas tecnologas conforman tcnicas de programacin para enlazar un lenguaje de programacin 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 solucin a la lgica de negocio, eliminando el obstculo que supone compatibilizar objetos con modelos relacionales. El framework para la persistencia de datos se ocupa de todos los detalles que conllevara desarrollar un mecanismo de mapeo personalizado.

Hoy en da, uno de los asuntos ms debatidos y discutidos ms apasionadamente en la industria del software es: cul de las tecnologas de persistencia (o frameworks para el mapeo Objeto/Relacional) merece ser la alternativa dominante? Esta discusin ha creado una divisin en la comunidad Java. Mientras esto siga as, dicho debate seguir en pie y los desarrolladores de software debern elegir la tecnologa 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.

Anlisis y Uso de Frameworks de Persistencia en Java

En la figura podemos observar la estructura bsica de una aplicacin Web desarrollada con Java empleando Servlets y JSP. La lgica de la aplicacin localizada en el servidor contiene, entre otros, un mdulo (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 aplicacin sobre las bases de datos dependern de la implementacin del mdulo en cuestin. Es en esa parte de la lgica del programa donde entran en escena los frameworks de persistencia.

Anlisis y Uso de Frameworks de Persistencia en Java

3- Anlisis de las Tecnologas

Anlisis y Uso de Frameworks de Persistencia en Java

3- ANLISIS DE LAS TECNOLOGAS

3.1.- OBJETIVOS

Definicin de las alternativas

Es necesario conocer qu alternativas de persistencia son las ms importantes actualmente. Se pretende definir cules son las se van a barajar y cules son sus orgenes. Se especificar cmo cada una de las alternativas est asociada a una organizacin o comunidad de desarrollo, as como su filosofa.

Descripcin 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 metodologa a seguir para conseguir la persistencia de los objetos, mostrando ejemplos y cdigo fuente.

Evaluacin: Caractersticas ms relevantes 7

Anlisis y Uso de Frameworks de Persistencia en Java

Antes de finalizar el anlisis, se pretende identificar las caractersticas ms relevantes de cada una de las alternativas estudiadas. De esta forma, enfrentando unas con otras se dar pie a obtener conclusiones.

Conclusiones

A continuacin, se obtendrn diversas conclusiones acerca de la informacin reunida en los puntos anteriores.

Por ltimo, para dar sentido al estudio, se elegir la alternativa de persistencia ms apropiada para suplir la codificacin JDBC empleada en la aplicacin que se desarrolle a continuacin, incorporndola al servidor.

Anlisis y Uso de Frameworks de Persistencia en Java

3.2- ALTERNATIVAS DE PERSISTENCIA

3.2.1. Introduccin

El Mapeo Objeto-Relacional (ORM)

Si se est trabajando con programacin orientada a objetos y bases de datos relacionales, es fcil observar que estos son dos paradigmas diferentes. El modelo relacional trata con relaciones y conjuntos, y es muy matemtico 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 tambin 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 aplicacin y se alcanza el punto donde es oportuno que sean persistentes. En este caso se debe abrir una conexin JDBC, crear una sentencia SQL y copiar todos los valores de las propiedades de los objetos sobre la seleccin. Esto

Anlisis y Uso de Frameworks de Persistencia en Java podra ser fcil para un objeto pequeo, pero si se considera para un objeto con muchas propiedades, la labor se convierte en un proceso incmodo.

Este no es el nico problema. Las asociaciones entre objetos tambin 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 coleccin asociada. A la hora de carga el objeto se cargar tambin la coleccin? Si se cargan tambin los elementos de la coleccin, se considerar que cada objeto elemento tiene una asociacin con todava ms objetos. En este caso, sera mejor cargar todo el rbol de objetos.

Por tanto, la diferencia objeto-relacional se amplia muy rpidamente cuando se est trabajando con grandes modelos de objetos. Y hay muchas ms 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 cdigo de una aplicacin se produce para mapear datos entre la aplicacin y la base de datos.

Para la mayora de las aplicaciones, almacenar y recuperar informacin implica alguna forma de interaccin con una base de datos relacional. Esto ha representado un problema fundamental para los desarrolladores porque algunas veces el diseo de datos relacionales y los ejemplares orientados a objetos 10

Anlisis y Uso de Frameworks de Persistencia en Java comparten estructuras de relaciones muy diferentes dentro de sus respectivos entornos.

Las bases de datos relacionales estn estructuradas en una configuracin tabular y los ejemplares orientados a objetos normalmente estn relacionados en forma de rbol. Esta 'diferencia de impedancia' ha llevado a los desarrolladores de varias tecnologas 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 mayora de estas herramientas permite a los desarrolladores instruir a los motores de persistencia de cmo convertir objetos Java a columnas/registros de la base de datos y al revs. 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

Anlisis y Uso de Frameworks de Persistencia en Java JDBC: Componente indispensable para los ORM

La mayora de las aplicaciones que son importantes en una empresa estn respaldadas por una arquitectura normalizada y optimizada de bases de datos relacionales. Tradicionalmente, dichas aplicaciones estn basadas en sentencias SQL con las cuales se gestionan todos los datos que manejan.

Este modelo contina teniendo una gran importancia estratgica 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 programacin en Java puesto que el desarrollador se puede concentrar en la construccin de la aplicacin mientras que delega los detalles de la persistencia de datos al framework de persistencia.

Hay mltiples alternativas para los programadores de Java cuando se pretende trabajar con mapeadores O/R. Hay tres organizaciones o comunidades que estn implicadas en el mundo de la persistencia O/R de Java de forma activa: organizaciones basadas en el estndar, comunidades open source y grupos comerciales.

Las comunidades open source incluyen importantes tecnologas, entre ellas Hibernate y el framework Spring. Las alternativas ms importantes basadas en el estndar, son EJB 3.0 y JDO. Entre las implementaciones comerciales se pueden 12

Anlisis y Uso de Frameworks de Persistencia en Java resaltar Oracles TopLink. Para este proyecto se analizarn las tecnologas open souce y las basadas en el estndar.

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 cdigo del programa hasta la fuente de datos) para asegurar que el diseo de persistencia O/R sea ptimo.

Tal y como se ver ms 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 comunicacin no es ptimo, la posible gran eficiencia de cualquier framework quedar debilitada. Por tanto, elegir el driver JDBC que mejor se adapte a la aplicacin es esencial a la hora de construir un sistema eficiente en el que participe un mecanismo de mapeo O/R.

13

Anlisis y Uso de Frameworks de Persistencia en Java

La figura muestra una representacin de los diferentes mecanismos de mapeo O/R y cmo se relacionan con el cdigo de la aplicacin y con los recursos de datos relacionados. Esto muestra claramente la funcin crtica que desempea 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 diseo de la API del framework que est expuesta al cdigo fuente de la aplicacin.

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

Anlisis y Uso de Frameworks de Persistencia en Java totalidad de eficiencia en una aplicacin siempre estar afectada por el nivel ms dbil del sistema.

Independientemente del cdigo JDBC generado, los mecanismos de mapeo O/R son incapaces de controlar cmo los drivers interactan con la base de datos. Al fin y al cabo la eficiencia de la aplicacin depende en gran parte de la habilidad que tenga el driver del nivel JDBC para mover todos los datos manejados entre la aplicacin y la base de datos.

Aunque hay mltiples factores que considerar a la hora de elegir un driver JDBC, seleccionar el mejor driver JDBC posible basndose en comportamiento, escalabilidad y fiabilidad es la clave para obtener el mximo beneficio de cualquier aplicacin basada en un framework O/R.

3.2.2. Definicin de las tecnologas basadas en el estndar

Java Data Objects (JDO) Definicin

Java Data Objects (JDO) es una especificacin 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 almacn

15

Anlisis y Uso de Frameworks de Persistencia en Java de datos transaccional (ficheros y bases de datos) siguiendo unos estndares predefinidos.

Esta API puede ser utilizada para acceder a datos en servidores o sistemas embebidos. Adems, las implementaciones de JDO pueden llegar a la telefona mvil, PDA y dems tecnologas wireless. Sin embargo, su funcin ms destacada es su capacidad para manejar como objetos cierta informacin perteneciente a una base de datos relacional.

JDO ha sido creado bajo la direccin de la comunidad de Java y documentado como una Especificacin Java (JSAR 12). Craig Russell de Sun Microsystems lider a un grupo de expertos de varias compaas para desarrollar la documentacin.

Como con otras muchas tecnologas de Java, Sun Microsystems ha lanzado una especificacin y una referencia para la implementacin. Adems, los vendedores estn desarrollando productos compatibles con JDO. La siguiente tabla muestra una lista de algunos vendedores:

16

Anlisis y Uso de Frameworks de Persistencia en Java

Vendedores de JDO Compaa SolarMetric Producto URL Asociada

Kodo JDO Enterprise Edition, Kodo www.solarmetric.com JDO Standard Edition

Poet Software Corporation LiBeLIS Hemisphere Technologies ObjectFrontier Inc. Versant Sun Microsystems, Inc. Object Industries GMBH

FastObjects

www.fastobjects.com

LiDO JDO Genie

www.libelis.com www.hemtech.co.za/jdo

FrontierSuite for JDO Versant enJin Reference Implementation

www.objectfrontier.com www.versant.com www.java.sun.com

JRelay

www.objectindustries.com

JDO ha sido diseado para poderse incorporar fcilmente a servidores de aplicacin. Esto permite que la tecnologa pueda asumir muchas funciones ofrecidas tambin por las Enterprise Java Beans (EJB) de Entidad, CMP. Dicha funcionalidad consiste en separar los objetos Java del cdigo JDBC con sus correspondientes sentencias SQL necesarios para acceder a las bases de datos.

17

Anlisis 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 Definicin

El bean de entidad es uno de los dos tipos de beans primarios: entidad y sesin. 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 seran accedidos mediante el JDBC u otro API. Ms que eso, los beans de entidad proporcionan un modelo de componentes que permite a los desarrolladores de beans enfocar su atencin en la lgica 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 caracterstica fundamental de la persistencia:

18

Anlisis 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 ningn cdigo de acceso a las bases de datos en la clase del bean. Con BMP, el bean de entidad contiene cdigo 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 actualizacin o leer su estado desde la base de datos. El contenedor tambin puede manejar cualquier bloqueo o transaccin, para que la base de datos se mantenga ntegra.

19

Anlisis y Uso de Frameworks de Persistencia en Java

3.2.3. Tecnologas Open Source: Hibernate - Definicin

Hibernate es un marco de trabajo de mapeo O/R Open Source que evita la necesidad de utilizar el API JDBC. Hibernate soporta la mayora de los sistemas de bases de datos SQL. El Hibernate Query Language, diseado como una extensin mnima, orientada a objetos, de SQL, proporciona un puente elegante entre los mundos objeto y relacional. Adems, ofrece facilidades para recuperacin y actualizacin de datos, control de transacciones, repositorios de conexiones a bases de datos, consultas programticas 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 programacin orientada a objetos, incluyendo asociacin, herencia,

polimorfismo, composicin 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 crtico del catlogo de productos de JBoss Enterprise Middleware System (JEMS). JBoss es una divisin de Red Hat, y ofrece servicios de mantenimiento, consulta y entrenamiento para asistir a sus usuarios.

20

Anlisis y Uso de Frameworks de Persistencia en Java

3.3- FUNCIONAMIENTO

3.3.1. Tecnologas basadas en el estndar

Java Data Objects (JDO) - Funcionamiento

Para comprender el funcionamiento de JDO se pretende describir los diversos pasos a seguir para construir una aplicacin que permita realizar el proceso de persistencia. Primero, se crear un objeto Persona (Person) para persistirlo en la base de datos. A continuacin, se crear el objeto PersistePersona (PersistPerson) que ser el encargado de gestionar el objeto persona en la base de datos. Despus 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: Creacin del objeto Persona (Person.java)

El objeto Person incluye los mtodos 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

Anlisis y Uso de Frameworks de Persistencia en Java 1. Sus atributos deben ser accesibles para las clases JDO (public o mtodos 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 podra 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; } // -- MTODOS 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

Anlisis 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: Creacin del objeto gestor de la persistencia (PersonPersist.java)

Una vez que se tiene un objeto Person con el cul podemos trabajar, necesitamos crear un objeto que se encargue de gestionar su persistencia. Este objeto ser el PersonPersist. Seguidamente, por pasos, se realizarn 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 mtodo main ( ).

23

Anlisis y Uso de Frameworks de Persistencia en Java

Paso 1: Inicializar el JDO Persistence Manager

Aqu figura el principio de la codificacin del objeto PersistPerson. Es necesario importar las clases estndar de JDO y la ManagedConnectionFactory desde la implementacin 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

Anlisis y Uso de Frameworks de Persistencia en Java La Connection Factory se crea en un mtodo esttico llamado createConnectionFactory(). Esta factora necesita la URL de JDBC, el driver JDBC, un nombre de usuario y la contrasea. OpenFusion JDO tambin 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 mtodo 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 travs del mtodo getPersistenceManager(). Despus se ha de crear una transaccin donde se har la operacin. Para persistir el array de personas llamamos al mtodo makePersistentAll() sobre el Persistence

25

Anlisis y Uso de Frameworks de Persistencia en Java Manager (pm). El bucle for{}sirve para obtener un identificador por cada persona persistida, guardndolos 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", "gary@segal.com", "(608) 294-0192", "(608) 029-4059"); people[1] = new Person("Michael Owen", "222 Bazza Lane, Liverpool, MN", "111-222-3333", "michael@owen.com", "(720) 111-2222", "(303) 222-3333"); people[2] = new Person("Roy Keane", "222 Trafford Ave, Manchester, MN", "234-235-3830", "roy@keane.com", "(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 mtodos que se pueden usar sobre el gestor de persistencia. Hay tres categoras:

Hace Instancias Persistentes. Persiste un objeto transitorio. Elimina Instancias Persistidas. Elimina informacin de la base de datos.

26

Anlisis y Uso de Frameworks de Persistencia en Java Hace Instancias Transitorias. Rompe la asociacin de las instancias con el gestor de persistencia. Sin embargo, la base de datos mantiene la informacin.

Hace Instancia Persitente


makePersistent(Object o) makePersistentAll(Obj ect[] os) makePersistentAll(Col lection os)

Elimina Instancia Persistida


deletePersistent(Object o)

Hace Instancia Transitoria


makeTransient(Object o)

deletePersistentAll(Obje makeTransientAll(Objec ct[] os) t[] os) deletePersistentAll(Coll makeTransientAll(Colle ection os) ction os)

Paso 3: Mostrar el contenido de la base de datos

El cdigo 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 travs del mtodo persistPeople(). Una vez devueltos los objetos, se puede ejecutar los mtodos 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

Anlisis 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 cdigo para cambiar informacin de una persona de la base de datos es muy similar al necesario para mostrar la informacin de las personas, sencillamente, se ha de ejecutar el mtodo setName() sobre la persona correspondiente. Sin embargo, hay una diferencia muy importante: en este caso se est realizando una transaccin, ya que la fila en la base de datos se ha de modificar. Por tanto, hay que utilizar el mtodo commit() para guardar los cambios, al igual que se ha hecho al crear las personas. La nica diferencia entre esta operacin y trabajar con objetos transitorios es que hay que verificar la transaccin.

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"); // VERIFICACIN DEL CAMBIO transaction.commit(); pm.close(); }

28

Anlisis 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 mtodo deletePersistent() sobre el mismo, tal y como se ha mencionado en el Paso 2. En este caso, tambin se est realizando una transaccin. Adems, el identificador del objeto tambin 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 mtodo main ( )

Por ltimo, el programa que contiene todo el cdigo anterior, tiene un mtodo 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

Anlisis 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 aplicacin. 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 implementacin JDO puede mejorar el bytecode de las clases a persistir manipulndolas, con el fin de aadir 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 mtodos del interface. Por tanto, despus de compilar el cdigo, se deber ejecutar el JDOEnhancer para que realice las manipulaciones oportunas.

Es necesario crear un fichero Descriptor para darle al Enhancer la informacin sobre las clases que se desean persistir. He aqu el descriptor: 30

Anlisis 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 ms 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>

CONSTRUCCIN: Pasos para construir y ejecutar la aplicacin

Estos son los pasos a seguir para construir el sistema que permitir ejecutar la aplicacin:

1. Compilar el Cdigo

31

Anlisis 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 aplicacin

Paso 1: Compilar el cdigo

La compilacin se realizar como en cualquier cdigo 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 cdigo 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

Anlisis 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 aplicacin compilada en el ejemplo, he aqu cmo se ejecutara 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 localizacin 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

Anlisis 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

Anlisis y Uso de Frameworks de Persistencia en Java Paso 4: Ejecutar la Aplicacin

% 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 mtodos para construir ejemplares de las clases de implementacin 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 expresin booleana que se parece algo a los operadores booleanos de SQL. El resultado de una consulta depende de si la expresin booleana se evala a true por las clases candidatas especificadas. El interface Query proporciona el siguiente mtodo para especificar un filtro:
void setFilter(String filter);

35

Anlisis y Uso de Frameworks de Persistencia en Java Las clases candidatas se pueden especificar utilizando uno de los siguientes mtodos del interface Query:
void setClass(Class candidateClass); void setCandidates(Collection candidates); void setCandidates(Extent candidates);

El interface Query proporciona mtodos para ejecutar una consulta. Los parmetros de la consulta se pueden pasar directamente a cualquiera de estos mtodos:
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 tambin proporciona un mtodo para declarar un grupo arbitrario de parmetros separados por comas:
void declareParameters(String paramStr);

Este grupo de parmetros debe formatearse como una definicin String de las parejas tipo-nombre. Por ejemplo, el siguiente fragmento ilustra un grupo de parmetros para un nombre y una cuenta de usuario:
query.declareParameters("String userName, int accountNumber");

36

Anlisis y Uso de Frameworks de Persistencia en Java El siguiente cdigo 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 ms simples para el desarrollador y los ms complicados para que los soporte el servidor EJB. Esto es porque toda la lgica de sincronizacin del estado del bean con la base de datos es manejada automticamente por el contenedor. Esto significa que el desarrollador del bean no necesita escribir ninguna lgica de acceso a datos, mientras que se supone que el servidor EJB tiene cuidado de toda la persistencia que necesita automticamente. La mayora de los vendedores EJB soportan la persistencia automtica a una base de datos relacional, pero el nivel

37

Anlisis y Uso de Frameworks de Persistencia en Java de soporte vara. Algunos proporcionan un mapeo O/R muy sofisticado, mientras que otros estn muy limitados.

La clase Bean Un bean enterprise es un componente completo que est compuesto de al menos dos interfaces y una clase de implementacin 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

Anlisis 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 lgica 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, podra 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 estn comprendidos por un int y unos sencillos

39

Anlisis 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

Anlisis 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 necesitaramos usar una herramienta de mapeado muy sofisticada. No todos los campos del bean son automticamente campos manejados por el contenedor; algunos de ellos son slo 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 travs de mapeo O/R. El CustomerBean podra, por ejemplo, mapear una tabla CUSTOMER en la base de datos que tenga la siguiente definicin.

CREATE TABLE CUSTOMER

41

Anlisis 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 especfica, 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 creaccin de registros, el borrado, la carga y la actualizacin de registros en la tabla CUSTOMER en respuesta a los mtodos invocados en los interfaces home y remoto del bean Customer.

Un subconjunto (uno o ms) 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

Anlisis 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 manifestarn como del tipo java.lang.Integer. Las claves primarias que se componen de varios campos, llamadas claves primarias compuestas, sern 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 mtodo create() del interface home del bean. He aqu la definicin 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

Anlisis y Uso de Frameworks de Persistencia en Java A continuacin est un ejemplo de cmo se usara el interface home en una aplicacin 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 podra declarar cero o ms mtodos create(), cada uno de los cuales debe tener sus correspondientes mtodos ejbCreate() y ejbPostCreate() en la clase del bean. Estos mtodos de creacin son enlazados en tiempo de ejecucin, para que cuando se llame a un mtodo create() del interface home, el contenedor delegue la invocacin a los correspondientes mtodos ejbCreate() y ejbPostCreate() de la clase Bean.

Cuando se invoca al mtodo create() de un interface home, el contenedor delega esta llamada al correspondiente mtodo ejbCreate() en el bean. Estos mtodos 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 mtodo 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

Anlisis y Uso de Frameworks de Persistencia en Java

En EJB un bean de entidad no existe tcnicamente hasta despus de que sus datos hayan sido insertados en la base de datos, lo que ocurre durante el mtodo 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 mtodo ejbCreate() y que los datos estn en la base de datos. Si el bean necesita acceder a su propia clave primaria o a una referencia remota despus de haber sido creado, pero antes de servir a cualquier mtodo de negocio, puede hacerlo en el mtodo ejbPostCreate(). Este mtodo permite al bean realizar cualquier proceso postcreaccin antes de empezar a servir peticiones de clientes. Por cada ejbCreate() debe haber un mtodo ejbPostCreate() correspondiente (con los mismos argumentos).

Los mtodos del interface home que empiezan con "find" son llamados mtodos de bsqueda. Se usan para consultar al servidor EJB sobre beans de entidad especficos, basndose en el nombre del mtodo y los argumentos pasados. Desafortunadamente, no hay un lenguaje de consultas estndard definido para los mtodos de bsqueda, por eso cada vendedor implementar estos mtodos de forma diferente. En los beans de entidad CMP, los mtodos de bsqueda no estn implementados con los mtodos correspondientes en la clase del bean; los contenedores los implementan cuando el bean se desarrolla de una forma especfica del vendedor. El desarrollador usar las herramientas

45

Anlisis y Uso de Frameworks de Persistencia en Java especficas del vendedor para decirle al contenedor cmo se debera comportar un mtodo de bsqueda particular. Algunos vendedores usaran herramientas de mapeo Objeto-Relacional para definir el comportamiento de un mtodo de bsqueda mientras que otros slo requerirn que el desarrollador introduzca el comando SQL apropiado.

Interface Remoto Cada bean de entidad debe definir una interface remoto en adicin del interface home. El interface remoto define los mtodos de negocio del bean de entidad. A continuacin est la definicin 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

Anlisis y Uso de Frameworks de Persistencia en Java Este es un ejemplo de cmo una aplicacin cliente podra 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 mtodos de negocio en el interface remoto se delegan a los correspondientes mtodos de negocio en el ejemplar del bean. En el bean Customer, los mtodos de negocios son todos simples accesores y modificadores, pero podran ser ms complicados. En otras palabras, los mtodos de negicio de una entidad no estn limitados a leer y escribir datos, tambin pueden realizar tareas de clculo.

Si, por ejemplo, los clientes tuvieran un programa de fidelidad que premiara el uso frecuente, podra haber un mtodo para mejorar los premios en el programa, basado en una acumulacin 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

Anlisis 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 mtodos addNights() y upgradeMembership() son ms sofisticados que los sencillos mtodos accesores. Aplican reglas de negocio para cambiar el nivel del premio y van ms all de leer y escribir datos.

Mtodos de RetroLlamada (CallBack Methods) La clase bean define mtodos create que corresponden con mtodos del interface home y mtodos de negocio que corresponden con mtodos del interface remoto. La clase bean tambin implementa un conjunto de mtodos callback que permiten al contenedor notificar al bean los eventos de su ciclo de vida. Los mtodos de retrollamada estn 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 definicin. Se puede observar que la clase del bean implementa estos mtodos.
public interface javax.ejb.EntityBean { public void setEntityContext(); public void unsetEntityContext(); public void ejbLoad(); public void ejbStore();

48

Anlisis y Uso de Frameworks de Persistencia en Java

public void ejbActivate(); public void ejbPassivate(); public void ejbRemove(); }

El mtodo setEntityContext() proporciona al bean un interface con el contenedor llamado el EntityContext. Este interface contiene mtodos para obtener informacin sobre el contexto bajo el que opera el bean en un momento particular. El interface EntityContext se usa para acceder a informacin de seguridad sobre su llamador; para determinar el estado de la transacin actual o para forzar a deshacer una transacin; o para obtener una referencia al propio bean, su interface home o su clave primaria. Este interface slo se configura una vez en la vida de un ejemplar de bean de entidad, por eso su referencia debera ponerse en uno de los campos de ejemplar del bean si la vamos a necesitar ms tarde.

El bean Customer de arriba no usa EntityContext, pero podra hacerlo. Por ejemplo, podra 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 crdito 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

Anlisis 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 mtodo 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 pequea tarea de limpieza.

50

Anlisis y Uso de Frameworks de Persistencia en Java Los mtodos 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 despus de que el contenedor haya refrescado los campos del bean manejados por contenedor con su estado desde la base de datos. El mtodo ejbStore() se invoca justo antes de que el contenedor escriba los campos del bean manejados por contenedor en la base de datos. Estos mtodos se usan para modificar datos que estn siendo sincronizados. Los mtodos podran 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 mtodos ejbLoad() y ejbStore() podran 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 podra 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

Anlisis 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 mtodos ejbPassivate() y ejbActivate() se invocan sobre el bean justo antes de que el bean sea "pasivizado" o justo despus 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 conservacin de recursos que emplea el contenedor para reducir el nmero de ejemplares en memoria. Un bean podra ser "pasivizado" si no ha sido utilizado durante un tiempo o como una operacin normal realizada por el contenedor para maximizar la reutilizacin del los recursos. Algunos contenedores eliminarn los beans de la memoria, mientras que otros reutilizarn ejemplares para otros interfaces remotos ms activos. Los mtodos ejbPassivate() y ejbActivate()

52

Anlisis y Uso de Frameworks de Persistencia en Java proporcionan al bean una notificacin 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 sincronizacin 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 operacin de sincronizacin y maneja las transacciones por el bean automticamente. 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 seccin, modificaremos la clase CustomerBean para crear un bean con persistencia manejada por el Bean (BMP). Esta modificacin no impactar en absoluto en los interfaces home o remoto. De hecho, no modificaremos directamente el CustomerBean original. En su lugar, lo

53

Anlisis 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 mayora de los casos, no extenderemos el bean para hacerlo BMP, slo 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 cdigo a mostrar. Abajo tenemos la definicin 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 mtodos ejbLoad() y ejbStore() los usa el contenedor de forma diferente a como lo haca con un bean CMP. En BMP, estos mtodos contienen cdigo para leer los datos de la base de datos y para escribir los cambios en la base de datos, respectivamente. Estos mtodos se llaman sobre el bean cuando el servidor EJB decide que es un buen momento para leer o escribir los datos.

54

Anlisis y Uso de Frameworks de Persistencia en Java El bean CustomerBean_BMP maneja su propia persistencia. En otras palabras, los mtodos ejbLoad() y ejbStore() deben incluir lgica 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 automtiamente los mtodos ejbLoad() y ejbStore() cuando crea apropiado.

El mtodo ejbLoad() se invoca normalmente al principio de una transacin, justo antes de que el contenedor delege un mtodo de negocio del bean. El cdigo mostrado abajo muestra cmo implementar el mtodo 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

Anlisis y Uso de Frameworks de Persistencia en Java

} } catch (SQLException sqle) { throw new EJBException(sqle); } finally { if (con!=null) con.close(); } } }

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");

El mtodo 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 mtodos heredados setEntityContext() y unsetEntityContext(). El mtodo ejbStore() es invocado sobre el bean, al final de la transacin, 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

Anlisis 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 mtodos ejbLoad() y ejbStore() el bean sincroniza su propio estado con la base de datos usando JDBC. El cdigo muestra que el bean obtiene sus conexiones a la base de datos desde una invocacin misteriosa al mtodo this.getConnection(). Un mtodo todava no implementado. El mtodo getConnection() no es un mtodo estndard EJB, slo una ayuda privada

57

Anlisis y Uso de Frameworks de Persistencia en Java implementada para ocultar los mecanismos de obtencin de conexiones a bases de datos. Este es del mtodo 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 travs de la factora de conexiones estndar, del tipo javax.sql.DataSource. En BMP, los mtodos 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 mtodos ejbCreate() y ejbRemove() con una lgica de acceso a bases de datos muy similar. Los mtodos ejbCreate() se implementan para insertar un nuevo registro 58

Anlisis y Uso de Frameworks de Persistencia en Java en la base de datos y los mtodos ejbRemove() para eliminar los datos de una entidad de la base de datos. Estos mtodos de una entidad son invocados por el contenedor en respuesta a invocaciones a sus correspondientes mtodos en los interface home y remoto. Estas son las implementaciones de estos mtodos.
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

Anlisis y Uso de Frameworks de Persistencia en Java En BMP, la clase bean es responsable de implementar los mtodos de bsqueda definidos en el interface home. Por cada mtodo de bsqueda definido en el interface home debe haber el correspondiente mtodo ejbFind() en la clase bean. Estos mtodos 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 implementacin del mtodo 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 mtodos de bsqueda de entidades simples como el de arriba devuelven una sola clave primara y lanza una ObjectNotFoundException si no se

60

Anlisis y Uso de Frameworks de Persistencia en Java localiza un registro correspondiente. Los mtodos de bsqueda multi-entidad devuelven una coleccin (java.util.Enumeration o java.util.Collection) de claves primarias. El contenedor convierte la coleccin de claves primarias en una coleccin de referencias remotas, que son devueltas al cliente. Abajo tenemos un ejemplo de cmo el mtodo ejbFindByZipCode() multi-entidad, que corresponde al mtodo findByZipCode() definido en el interface CustomerHome, sera 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 coleccin vaca al contenedor, que devuelve una coleccin vaca al cliente.

61

Anlisis y Uso de Frameworks de Persistencia en Java Con la implementacin de todos estos mtodos 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. Tecnologa Open Source: HIBERNATE Funcionamiento

Para comprender el funcionamiento de Hibernate se pretende describir los diversos pasos a seguir para construir una aplicacin que permita realizar el proceso de persistencia. Primero, se crear un objeto Evento (Event) para persistirlo en la base de datos. A continuacin, se ver cmo persistir el objeto Evento en la base de datos y realizar una transaccin para obtenerlo de nuevo. Despus se proceder a construir un archivo XML de mapeo para decirle a Hibernate qu es lo que deseamos persistir. A travs de otro archivo XML se configurarn 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 distribucin de Hibernate de su pgina de descarga. Extraer los jars necesarios desde el archivo de Hibernate. Los situaremos en un directorio lib

62

Anlisis y Uso de Frameworks de Persistencia en Java bajo el directorio de trabajo, tu despliegue de directorios debera 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: Definicin 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

Anlisis 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 necesitarn dicha id. Cuando se construyen aplicaciones Hibernate es recomendable mantener dichas ids nicas separadas de la lgica de la aplicacin. Esto impide manipular la id en nuestro cdigo, dejando que Hibernate se ocupe de ella. De ah viene porqu el mtodo set de la id es privado, permitiendo que Hibernate lo utilice (Hibernate podra acceder a los mtodos set y get de propiedades para todas las visibilidades), pero se asla del programador.

Este fichero se debe situar en un directorio llamado src en nuestro directorio de trabajo. El directorio debera aparecer de esta forma:

+lib <hibernate jars> +src +de +gloegl +road2hibernate Event.java

64

Anlisis y Uso de Frameworks de Persistencia en Java

PERSISTENCIA: 1 Creacin del Objeto El siguiente cdigo muestra cmo se crea un objeto Evento desde el mtodo 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 estn pasando parmetros desde la lnea de comandos y se podrn leer en args[]. Si el primer argumento de recibido por la aplicacin es store, se toma el segundo argumento como un ttulo, se crea un nuevo Date y se pasan los dos al mtodo store, donde se realiza la transaccin 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

Anlisis y Uso de Frameworks de Persistencia en Java

} }

e.printStackTrace();

2 Mostrar los objetos almacenados

Modificando el mtodo main, cuando el parmetro de entrada sea list, se mostrarn 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

Anlisis 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 cmo persistirla. Para ello es necesario construir un fichero de mapeo. El fichero de mapeo le dice a Hibernate qu debera almacenar en la base de datos y cmo. 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

Anlisis 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 debera mapear. La estructura interior del documento de mapeo se debera 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. Adems hay que especificar cmo 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

Anlisis y Uso de Frameworks de Persistencia en Java

El elemento <id> es la declaracin de la propiedad id. name="id" es el nombre de la propiedad. Hibernate usar los mtodos getId y setId para acceder a ella. El atributo column le dice a Hibernate que clumna 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 tcnica que se usar para la generacin 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

Anlisis 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 mtodos 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 sita en un fichero llamado Event.hbm.xml en el mismo directorio donde est la clase Event. As quedara la estructura del directorio de trabajo:

+lib <hibernate jars> +src +de +gloegl +road2hibernate Event.java Event.hbm.xml

70

Anlisis y Uso de Frameworks de Persistencia en Java

CONFIGURACIN DE LA BASE DE DATOS

Para configurar Hibernate se necesitan la informacin 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>

Adems 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

Anlisis 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 configuracin necesaria para la Conexin JDBC que utilizar Hibernate. La propiedad dialect especifica el SQLdialect que Hibernate deber generar. Luego se especifica que Hibernate delegar las transacciones a la conexin JDBC subyacente y se asigna un proveedor de cach. La siguiente propiedad le dice a Hibernate que ajuste automticamente las tablas en la base de datos de acuerdo al mapeos. Finalmente se le da el path al fichero de mapeo.

72

Anlisis y Uso de Frameworks de Persistencia en Java CONSTRUCCIN Y EJECUCIN DEL SISTEMA

1 Construccin Por conveniencia, se crea un fichero batch en el directorio de trabajo que contenga todos los comandos necesarios para la complicacin. Bajo Windows, este sera 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 Ejecucin El cdigo que viene a continuacin 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

Anlisis 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(); } } public static void main(String[] args) { EventManager instance = new EventManager(); System.exit(0); } }

new

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 sera la que figura a continuacin:

+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

Anlisis y Uso de Frameworks de Persistencia en Java

build.bat

Para ejecutar nuestra aplicacin se crea otro fichero batch en el directorio de trabajo bajo el nombre de run.bat, con el siguiente contenido (todo en una lnea):

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 sera 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

Anlisis y Uso de Frameworks de Persistencia en Java

3.4.- EVALUACIN

JDO vs. EJB

Desde la aparicin de JDO se ha especulado que esta tecnologa podra sustituir a las EJB de entidad. Para entender esta afirmacin se debe examinar que es exactamente un EJB de entidad. Como ya se ha explicado, los beans de entidad se dividen en dos categoras: persistencia manejada por contenedor (CMP) y persistencia manejada por bean (BMP). Los beans BMP contienen un cdigo que puede almacenar el contenido del bean en un almacn de datos permanente. Los BMP tienden a ser independientes y no forman relaciones directas con otros beans BMP. No sera correcto decir que los beans BMP pueden ser sustituidos por JDO, puesto que un bean BMP hace uso directo de cdigo JDBC. Esto viola uno de los principios de diseo de JDO ya que esta tecnologa 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 tambin pueden formar las tpicas relaciones [1 n] [n a m] con otros beans CMP.

La funcin de un bean CMP es muy similar a la de JDO. Ambas tecnologas permiten persistir datos con una perspectiva orientada a objetos ya

76

Anlisis y Uso de Frameworks de Persistencia en Java que siempre se persisten objetos y evitan tener que conocer los detalles de cmo los objetos estn almacenados. JDO y CMP tambin 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 tecnologas. Los beans CMP todava necesitan aumentar su aceptacin en la comunidad de programadores. La mayor parte de las mejoras y crecimiento en general de las EJBs ha sido en el rea de sesin. CMP y JDO padecen los mismos problemas a la hora de ser acogidos ya que ambas tecnologas 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 cmo generar dicha consulta equivalente a la sentencia SQL. En estos casos los programadores preferiran 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 podra hacerlo con CMP. JDO puede ser realmente una buena capa en el nivel superior a JDBC. En la mayora 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

Anlisis 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 debera 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 crticas 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 nmero de relaciones entre los objetos, es muy fcil que, como consecuencia, JDO haya accedido a muchos ms datos de los necesarios. Es evidente que JDBC siempre va a ser ms rpido que JDO ya que es ms directo. Ser eleccin 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

Anlisis y Uso de Frameworks de Persistencia en Java consultas basado en Java. Por una parte, JDOQL es mucho ms 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 mayora de los programadores dominan SQL, y adems son capaces de construir consultas SQL muy optimizadas a pesar de tener una gran complejidad.

Para muchos programadores, una herramienta que crea consultas automticamente no es de gran utilidad, sobre todo si nos referimos a JDOQL, que solamente acta en aplicaciones Java. Antes o despus SQL ser sustituido, pero para ello tendr que llevarlo a cabo una tecnologa ms 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 aadir sus libreras a la aplicacin y rellenar su archivo de

79

Anlisis y Uso de Frameworks de Persistencia en Java configuracin 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 librera 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 especfico de Hibernate, al igual que el JDOQL es el lenguaje a travs 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 ms complejas, un programador que domine SQL con un nivel alto seguramente eche de menos la alternativa estndar. Hibernate ofrece ambas posibilidades.

3.5.- CONCLUSIONES

Se han encontrado muchos puntos de inters a travs de la bsqueda de informacin para el anlisis de las diferentes tecnologas. Entre tantos, cabe destacar la cantidad de usuarios que defienden una tecnologa advirtiendo que es la que mejor se adapta a su sistema.

80

Anlisis 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 codificacin y portabilidad. Las tecnologas que se han propuesto brindan esa oportunidad a los usuarios, pero la clave a la hora de decidir sobre su implantacin 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 tecnologas se ha de escoger una de las alternativas estudiadas. Siendo coherentes con la reflexin precedente y con el apartado de evaluacin, Hibernate es la alternativa ms apropiada para ocuparse de la persistencia en la aplicacin que se va a desarrollar en el siguiente captulo.

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 orientacin orientada a objetos, incluyendo herencia,

polimorfismo, relaciones de asociacin y composicin, y colecciones.

81

Anlisis y Uso de Frameworks de Persistencia en Java o Mxima 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 cdigo para utilizar Hibernate ser Java puro, ya que existen cmodos asistentes para crear los archivos de configuracin y mapeo, que son XML. Adems, en ninguna fase de su utilizacin (instalacin, configuracin, desarrollo y ejecucin) ser necesario escribir una sola instruccin en lnea de comandos, como sucede con JDO a la hora de ejecutar el modificador de byte codes, el JDOEnhancer.

o Ofrece HQL pero tambin 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 clusulas. Sin embargo, para los programadores que lo prefieran, Hibernate permite el uso de sentencias SQL, con el fin de proporcionar libertad de eleccin, 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 implantacin, se encuentra el Mapping Editor. Esta herramienta para la creacin de los ficheros XML de mapeo proporciona auto-relleno de campos como el nombre de la 82

Anlisis 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 crtico del catlogo de productos de JBoss Enterprise Middleware System (JEMS). JBoss es una divisin de Red Hat, y ofrece servicios de mantenimiento, consulta y entrenamiento para asistir a sus usuarios.

83

Anlisis y Uso de Frameworks de Persistencia en Java

4- Diseo y Desarrollo de la Aplicacin

84

Anlisis y Uso de Frameworks de Persistencia en Java

4- DISEO Y DESARROLLO DE LA APLICACIN

4.1- OBJETIVOS

Se pretende disear una aplicacin que verifique la viabilidad de una de las alternativas de persistencia O/R. La aplicacin consistir en un portal Web que proporcione un interfaz mediante el cual se realicen mltiples accesos a una base de datos relacional. Dicho portal presentar los resultados solicitados de forma vistosa y ordenada. Con esto se pretende aplicar la tecnologa a las actividades cotidianas empresariales.

Puesto que el fin elemental del portal es la explotacin de tablas y la distribucin de su informacin por todos los departamentos interesados en una empresa, se pretende situar la aplicacin 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 debern 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 motivacin del proyecto, se deber conseguir que la aplicacin 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 aplicacin 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

Anlisis y Uso de Frameworks de Persistencia en Java varias conexiones simultneas, adems de ser Open Source. Adems, MySQL est acompaado 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- DESCRIPCIN DE LA APLICACIN

La aplicacin a desarrollar consiste en un portal Web para uso cotidiano, que ser accesible a travs de la intranet en una pequea empresa. Dado el carcter del proyecto, la aplicacin se basa en una empresa ficticia, pero gracias a un diseo sencillo y slido, aadiendo nuevas funcionalidades se podra adaptar a mltiples usos reales.

La empresa en cuestin consiste en una clnica privada de alergologa. El portal pretende servir de punto de encuentro entre todos los empleados, desde los mdicos hasta el personal informtico. Adems de ser una fuente de informacin para todos los usuarios (noticias, enlaces de inters, etc) el portal proporciona servicios a los empleados, convirtindose 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 informtico tomar un papel de

86

Anlisis y Uso de Frameworks de Persistencia en Java administrador del portal, al servicio de las funcionalidades que estn a disposicin del personal mdico y administrativo de la clnica.

Para realizar un sencillo diseo de la aplicacin Web se van a seguir las siguientes etapas:

Identificacin de los requisitos funcionales mediante la definicin de los Casos de Uso y su representacin mediante diagramas.

Diseo externo mediante la asociacin entre los Casos de Uso y los diseos de pginas Web correspondientes realizados con HTML.

Diseo 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 clnica, entre los que se distinguen tres grupos con perfiles diferentes:

a) Personal Informtico (INF):

87

Anlisis y Uso de Frameworks de Persistencia en Java Este grupo desempea el papel de administrador del portal, ocupndose principalmente de la gestin de las cuentas. Por otra parte, debe tener acceso a otras funcionalidades con el fin de supervisar la integridad de los datos.

b) Personal Mdico (MED): En este grupo se encuentran los mdicos de la clnica. stos tendrn acceso privilegiado a los datos de los pacientes que tengan asignados, as como a su historia mdica.

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 mdico determinado.

4.3.2. Casos de Uso Los requisitos funcionales de la aplicacin vienen definidos por los siguientes casos de uso: 1. Inicio 1.1. Solicitud de cuenta 1.2. Identificacin 2. Navegacin bsica 2.1. Consulta de noticias 2.2. Cambio de contrasea 2.3. Consulta de enlaces 3. Acceso a Tablas 88

Anlisis y Uso de Frameworks de Persistencia en Java 3.1. Gestin de pacientes 3.1.1. Creacin de paciente 3.1.2. Edicin de paciente 3.1.3. Eliminacin de paciente 4. Acceso a Pacientes 4.1. Gestin de alergias 4.1.1. Asignacin de alergia 4.1.2. Edicin de alergia 4.1.3. Eliminacin de alergia 5. Acceso a Portal 5.1. Gestin de noticias 5.1.1. Creacin de noticia 5.1.2. Edicin de noticia 5.1.3. Eliminacin de noticia 5.2. Gestin de cuentas 5.2.1. Activacin/Desactivacin de cuenta 5.2.2. Edicin de cuenta 5.2.3. Eliminacin de cuenta 6. Cierre de sesin 6.1. Cierre de Sesin

89

Anlisis y Uso de Frameworks de Persistencia en Java DESCRIPCIN DETALLADA DE LOS CASOS DE USO

1. Inicio

ESCENARIO: 1.1. Solicitud de cuenta ACTORES: INF, MED, ADM Precondicin: Seleccionar la opcin 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 enva 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 confirmacin de contraseas es incorrecta: El sistema advierte del error en la pantalla y vuelve a pedir los datos. El campo Dni est vaco o no se ha seleccionado ningn perfil: El sistema vuelve a pedir los datos.

ESCENARIO: 1.2. Identificacin ACTORES: INF, MED, ADM Precondicin: Flujo Primario: 1. El sistema pide los datos de identificacin: Usuario y Contrasea. 2. El usuario introduce sus datos y enva el formulario. 90

Anlisis y Uso de Frameworks de Persistencia en Java 3. El sistema valida los datos y da acceso al portal habilitando las opciones correspondientes segn su perfil. Flujo Secundario: Los datos introducidos son vlidos pero la cuenta no ha sido activada: El sistema advierte del error y vuelve a pedir los datos. Los datos introducidos no son vlidos: El sistema advierte del error y vuelve a pedir los datos.

2. Navegacin Bsica

ESCENARIO: 2.1. Consulta de noticias ACTORES: INF, MED, ADM Precondiciones: - El usuario acaba de acceder al portal. - El usuario ha seleccionado la opcin Noticias en la barra de navegacin. 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 contrasea ACTORES: INF, MED, ADM Precondicin: El usuario ha seleccionado la opcin Usuario en la barra de navegacin. 91

Anlisis y Uso de Frameworks de Persistencia en Java Flujo Primario: 1. El sistema pide la contrasea actual del usuario y la nueva contrasea. 2. El usuario introduce los datos y enva el formulario. 3. El sistema valida los datos y advierte que la contrasea ha cambiado. Flujo Secundario: La contrasea actual o la confirmacin de nueva contrasea es incorrecta: El sistema advierte del error y vuelve a pedir los datos.

ESCENARIO: 2.3. Consulta de enlaces ACTORES: INF, MED, ADM Precondicin: El usuario ha seleccionado la opcin Enlaces en la barra de navegacin. Flujo Primario: 1. El sistema muestra diversos enlaces de inters. 2. El usuario pulsa sobre un enlace, que se abrir en otra ventana o pestaa de su navegador. Flujo Secundario: -

3. Acceso a Tablas 3.1. Gestin de Pacientes

ESCENARIO: 3.1.1. Creacin de paciente ACTORES: INF, ADM

92

Anlisis y Uso de Frameworks de Persistencia en Java Precondicin: El usuario ha seleccionado la opcin Nuevo Paciente dentro de la seccin Tablas de la barra de navegacin. Flujo Primario: 1. El sistema pide los datos del nuevo paciente y muestra los mdicos disponibles en la base de datos. 2. El usuario introduce los datos del nuevo paciente, asignndole un mdico y enva 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 ningn mdico: El sistema advierte del error y vuelve a pedir los datos.

ESCENARIO: 3.1.2. Edicin de paciente ACTORES: INF, ADM Precondicin: El usuario ha seleccionado un paciente y pulsa sobre la opcin Editar dentro de la seccin Tablas de la barra de navegacin. Flujo Primario: 1. El sistema muestra los datos del paciente y da opcin a cambiarlos. 2. El usuario hace las modificaciones pertinentes y enva el formulario. 3. El sistema advierte que los datos del paciente se han actualizado. Flujo Secundario: -

93

Anlisis y Uso de Frameworks de Persistencia en Java ESCENARIO: 3.1.3. Eliminacin de paciente ACTORES: INF, ADM Precondicin: El usuario ha seleccionado un paciente y pulsa sobre la opcin Borrar dentro de la seccin Tablas de la barra de navegacin. Flujo Primario: 1. El sistema elimina el paciente seleccionado de la base de datos. Flujo Secundario: -

4. Acceso a Pacientes 4.1. Gestin de Alergias

ESCENARIO: 4.1.1. Asignacin de Alergia ACTORES: MED Precondicin: El usuario ha seleccionado la opcin Pacientes en la barra de navegacin. Flujo Primario: 1. El sistema muestra los pacientes que tiene asignados el usuario. 2. El usuario selecciona un paciente y elige la opcin Ver Alergias. 3. El sistema muestra las alergias que tiene asignadas el paciente. 4. El usuario elige la opcin Asignar Alergia. 5. El sistema pide los datos de la alergia. 6. El usuario introduce los datos de la alergia y enva el formulario. 7. El sistema valida los datos y advierte que se ha asignado una alergia. Flujo Secundario: 94

Anlisis 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. Edicin de Alergia ACTORES: MED Precondicin: El usuario ha seleccionado la opcin Pacientes en la barra de navegacin. Flujo Primario: 1. El sistema muestra los pacientes que tiene asignados el usuario. 2. El usuario selecciona un paciente y elige la opcin Ver Alergias. 3. El sistema muestra las alergias que tiene asignadas el paciente. 4. El usuario selecciona un tipo de alergia y elige la opcin Ver Detalles. 5. El sistema muestra los datos de la alergia. 6. El usuario modifica los datos de la alergia y enva el formulario. 7. El sistema valida los datos y advierte que se han modificado los detalles. Flujo Secundario: -

ESCENARIO: 4.1.3. Eliminacin de Alergia ACTORES: MED Desencadenante: El usuario ha seleccionado la opcin Pacientes en la barra de navegacin. Flujo Primario: 1. El sistema muestra los pacientes que tiene asignados el usuario. 95

Anlisis y Uso de Frameworks de Persistencia en Java 2. El usuario selecciona un paciente y elige la opcin Ver Alergias. 3. El sistema muestra las alergias que tiene asignadas el paciente. 4. El usuario selecciona un tipo de alergia y elige la opcin Borrar. 5. El sistema elimina la alergia asignada y vuelve a mostrar la lista. Flujo Secundario: -

5. Acceso a Portal 5.1. Gestin de Noticias

ESCENARIO: 5.1.1. Creacin de noticia ACTORES: INF Precondicin: El usuario ha seleccionado la opcin Portal en la barra de navegacin. Flujo Primario: 1. El sistema muestra las opciones de gestin del portal. 2. El usuario selecciona la opcin Gestin de Noticias. 3. El sistema muestra las noticias existentes. 4. El usuario selecciona la opcin Nueva Noticia. 5. El sistema pide los datos de la nueva noticia. 6. El usuario introduce los datos y enva el formulario. 7. El sistema crea la noticia. Flujo Secundario: -

ESCENARIO: 5.1.2. Edicin de noticia ACTORES: INF 96

Anlisis y Uso de Frameworks de Persistencia en Java Precondicin: El usuario ha seleccionado la opcin Portal en la barra de navegacin. Flujo Primario: 1. El sistema muestra las opciones de gestin del portal. 2. El usuario elige la opcin Gestin de Noticias. 3. El sistema muestra las noticias existentes. 4. El usuario selecciona una noticia y elige la opcin Editar. 5. El muestra los datos de la noticia seleccionada y permite su modificacin. 6. El usuario modifica los datos de la noticia y enva el formulario. 7. El sistema actualiza los datos y advierte que la noticia ha sido modificada. Flujo Secundario: -

ESCENARIO: 5.1.3. Eliminacin de noticia ACTORES: INF Precondicin: El usuario ha seleccionado la opcin Portal en la barra de navegacin. Flujo Primario: 1. El sistema muestra las opciones de gestin del portal. 2. El usuario elige la opcin Gestin de Noticias. 3. El sistema muestra las noticias existentes. 4. El usuario selecciona una noticia y elige la opcin Borrar. 5. El sistema elimina la noticia y vuelve a mostrar la lista. Flujo Secundario: -

5.2. Gestin de Cuentas de Usuario

97

Anlisis y Uso de Frameworks de Persistencia en Java ESCENARIO: 5.2.1. Activacin / Desactivacin de cuenta ACTORES: INF Precondicin: El usuario ha seleccionado la opcin Portal en la barra de navegacin. Flujo Primario: 1. El sistema muestra las opciones de gestin del portal. 2. El usuario elige la opcin Gestin de Cuentas. 3. El sistema muestra las cuentas existentes, incluyendo las que estn desactivadas. 4. El usuario selecciona una cuenta y elige la opcin 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. Edicin de cuenta ACTORES: INF Precondicin: El usuario ha seleccionado la opcin Portal en la barra de navegacin. Flujo Primario: 1. El sistema muestra las opciones de gestin del portal. 2. El usuario elige la opcin Gestin de Cuentas. 3. El sistema muestra las cuentas existentes, incluyendo las que estn desactivadas. 4. El usuario selecciona una cuenta y elige la opcin Editar. 5. El sistema muestra los datos de la cuenta y permite su modificacin, exceptuando el perfil. 6. El usuario modifica los datos pertinentes y enva el formulario. 98

Anlisis 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. Eliminacin de cuenta ACTORES: INF Precondicin: El usuario ha seleccionado la opcin Portal en la barra de navegacin. Flujo Primario: 1. El sistema muestra las opciones de gestin del portal. 2. El usuario elige la opcin Gestin de Cuentas. 3. El sistema muestra las cuentas existentes, incluyendo las que estn desactivadas. 4. El usuario selecciona una cuenta y elige la opcin Borrar. 5. El sistema elimina la cuenta y vuelve a mostrar la lista. Flujo Secundario: -

6. Cierre de Sesin

ESCENARIO: 6.1. Cierre de Sesin ACTORES: INF, MED, ADM Precondicin: El usuario ha seleccionado la opcin Cerrar Sesin en la barra de navegacin. Flujo Primario: 1. El sistema muestra la pantalla inicial pidiendo los datos de identificacin. Flujo Secundario: 99

Anlisis y Uso de Frameworks de Persistencia en Java

DIAGRAMAS DE LOS CASOS DE USO

Casos de uso del Personal Informtico (INF):

100

Anlisis y Uso de Frameworks de Persistencia en Java

Casos de uso del Personal Administrativo (ADM):

101

Anlisis y Uso de Frameworks de Persistencia en Java

Casos de uso del Personal Mdico (MED):

102

Anlisis y Uso de Frameworks de Persistencia en Java

4.4- DISEO EXTERNO

4.4.1. Diseo del Interfaz del Usuario

Inicio Identificacin

Caso de uso: 1.2. Login de Acceso

Esta es la pantalla de inicio de la aplicacin. A travs del botn 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

Anlisis y Uso de Frameworks de Persistencia en Java

Solicitud de Cuenta

Caso de uso: 1.1. Solicitud de Cuenta

Despus de realizar la solicitud el sistema conducir de nuevo al inicio de la aplicacin, donde se pedirn otra vez los datos de identificacin.

104

Anlisis y Uso de Frameworks de Persistencia en Java Navegacin bsica 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 travs de la barra de navegacin situada en el lateral izquierdo. En la parte superior derecha, el sistema muestra el perfil y el nombre del usuario que ha iniciado la sesin.

La aplicacin da la bienvenida con las ltimas noticias ordenadas por fecha descendentemente. Esta informacin ser accesible en cualquier momento desde la opcin Noticias que aparece en la barra de navegacin.

105

Anlisis y Uso de Frameworks de Persistencia en Java

Cambio de contrasea

Caso de uso: 2.2. Cambio de Contrasea

Esta funcionalidad se ubicar en el apartado Usuario de la barra de navegacin. Como se aprecia en la imagen, el sistema pedir que el usuario introduzca de nuevo su contrasea actual por cuestiones de seguridad.

106

Anlisis 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 tendrn acceso a diversos enlaces de utilidad para su uso cotidiano. Al pulsar sobre uno de ellos, la pgina Web correspondiente se abrir en una nueva ventana o pestaa del navegador.

107

Anlisis y Uso de Frameworks de Persistencia en Java

Gestin de pacientes Creacin de paciente

Caso de uso: 3.1.1. Creacin de Paciente

Este es el formulario que presentar el sistema al usuario para recibir los datos de un nuevo paciente. Los mdicos que figuren en la base de datos aparecern en la casilla Mdico para realizar la asignacin del paciente.

108

Anlisis y Uso de Frameworks de Persistencia en Java

Edicin de paciente

Caso de uso: 3.1.2. Edicin de Paciente

Este formulario muestra los datos del paciente correspondiente, as como el mdico que tiene asignado. Se permitir el cambio de mdico entre otras cosas.

109

Anlisis y Uso de Frameworks de Persistencia en Java

Eliminacin de paciente

Caso de uso: 3.1.3. Eliminacin 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 creacin y edicin de los pacientes.

Para eliminar un paciente, se debe seleccionar uno de ellos y pulsar el botn Borrar situado en la parte superior de la lista.

110

Anlisis y Uso de Frameworks de Persistencia en Java

Gestin de alergias Asignacin de alergia

Caso de uso: 4.1.1. Asignacin de Alergia

Mediante este formulario el mdico 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

Anlisis y Uso de Frameworks de Persistencia en Java

Edicin de alergia

Caso de uso: 4.1.2. Edicin de Alergia

A travs de este formulario el mdico podr ver los detalles de la alergia correspondiente, as como cambiar el tratamiento.

112

Anlisis y Uso de Frameworks de Persistencia en Java

Eliminacin de alergia

Caso de uso: 4.1.3. Eliminacin 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 asignacin y edicin de las alergias.

Para eliminar una alergia, se debe seleccionar una de ellas y pulsar el botn Borrar situado en la parte superior de la lista.

113

Anlisis y Uso de Frameworks de Persistencia en Java

Gestin del Portal (Noticias y Cuentas de Usuario)

Esta es la pantalla que presenta el sistema al informtico para gestionar el portal. Desde aqu se acceder a la Gestin de Noticias y a la Gestin de Cuentas.

114

Anlisis y Uso de Frameworks de Persistencia en Java

Creacin de noticia

Caso de uso: 5.1.1. Creacin de Noticia

Este es el formulario que presentar el sistema al informtico para recibir los datos de una nueva noticia.

115

Anlisis y Uso de Frameworks de Persistencia en Java

Edicin de noticia

Caso de uso: 5.1.2. Edicin de Noticia

A travs de este formulario el informtico podr ver los detalles de la noticia correspondiente y modificar cualquiera de sus datos.

116

Anlisis y Uso de Frameworks de Persistencia en Java

Eliminacin de noticia

Caso de uso: 5.1.3. Eliminacin 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 creacin y edicin de las noticias.

Para eliminar una noticia, se debe seleccionar una de ellas y pulsar el botn Borrar situado en la parte superior de la lista.

117

Anlisis y Uso de Frameworks de Persistencia en Java

Activacin/Desactivacin de cuenta y Eliminacin de cuenta

Casos de uso: 5.2.1. Activacin / Desactivacin de Cuenta 5.2.3. Eliminacin 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 estn activas. Desde aqu se acceder al formulario para la edicin de las cuentas.

Para eliminar una noticia o cambiar su estado de actividad, se debe seleccionar una de ellas y pulsar el botn Borrar o Activar / Desactivar respectivamente.

118

Anlisis y Uso de Frameworks de Persistencia en Java

Edicin de cuenta

Caso de uso: 5.2.2. Edicin de Cuenta

A travs de este formulario el informtico podr ver los detalles de la cuenta de usuario correspondiente y modificar cualquiera de sus. Adems, 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

Anlisis y Uso de Frameworks de Persistencia en Java

Cierre de Sesin

Caso de uso: 6.1. Cierre de Sesin

Con el fin de abandonar el portal el usuario deber elegir la opcin Cerrar Sesin situada en la parte inferior de la barra de navegacin. El sistema volver a pedir los datos de identificacin en la pgina de inicio de la aplicacin.

120

Anlisis y Uso de Frameworks de Persistencia en Java

4.5- DISEO INTERNO

4.5.1- JSP y Servlets

Para hacer posible el desarrollo de la aplicacin Web se va a disear una estructura unida de pginas dinmicas JSP. Las pginas JSP permiten ejecutar cdigo Java con el fin de generar HTML dinmicamente. 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 recepcin de los formularios y la validacin de sus datos se utilizarn Servlets. Mediante algoritmos de validacin y accesos a las bases de datos, los diversos Servlets se encargarn de ejecutar un cdigo u otro dependiendo de los datos introducidos en los formularios. Posteriormente devuelven el control a las pginas JSP.

Para realizar el diseo se analizarn los diferentes subsistemas de casos de uso y se definirn las pginas JSP y Servlets necesarios para su viabilidad. Los subsistemas son: Inicio, Navegacin Bsica, Gestin de Pacientes, Gestin de Tablas, Gestin de Alergias, Gestin de Noticias y Gestin de Cuentas.

121

Anlisis 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. Identificacin JSP: index.jsp Servlet asociado: ValidaUsuario.java

Subsistema: NAVEGACIN BSICA

Caso de Uso: 2.1. Consulta de Noticias JSP: home.jsp Servlet asociado: -

Caso de Uso: 2.2. Cambio de Contrasea JSP: usuario.jsp Servlet asociado: CambiaPass.java

Caso de Uso: 2.3. Consulta de Enlaces JSP: enlaces.jsp Servlet asociado: -

122

Anlisis y Uso de Frameworks de Persistencia en Java

Subsistema: GESTIN DE PACIENTES

Caso de Uso: 3.1.1. Creacin de Paciente JSP: creacionPaciente.jsp Servlet asociado: CreaPaciente.java

Caso de Uso: 3.1.2. Edicin de Paciente JSP: edicionPaciente.jsp Servlet asociado: EditaPaciente.java

Caso de Uso: 3.1.3. Eliminacin de Paciente JSP: tablas.jsp Servlet asociado: GestionaPaciente.java

Subsistema: GESTIN DE ALERGIAS

Caso de Uso: 4.1.1. Asignacin de Alergia JSP: creacionAlergia.jsp Servlet asociado: CreaAlergia.java

Caso de Uso: 4.1.2. Edicin de Alergia JSP: edicionAlergia.jsp Servlet asociado: EditaAlergia.java 123

Anlisis y Uso de Frameworks de Persistencia en Java

Caso de Uso: 4.1.3. Eliminacin de Alergia JSP: pacientesAlergias.jsp Servlet asociado: GestionaEnfermedad.java

Subsistema: GESTIN DE NOTICIAS

Caso de Uso: 5.1.1. Creacin de Noticia JSP: creacionNoticia.jsp Servlet asociado: CreaNoticia.java

Caso de Uso: 5.1.2. Edicin de Noticia JSP: edicionNoticia.jsp Servlet asociado: EditaNoticia.java

Caso de Uso: 5.1.3. Eliminacin de Noticia JSP: portalNoticias.jsp Servlet asociado: GestionaNoticia.java

Subsistema: GESTIN DE CUENTAS

Caso de Uso: 5.2.1. Activacin / Desactivacin de Cuenta JSP: portalCuentas.jsp 124

Anlisis y Uso de Frameworks de Persistencia en Java Servlet asociado: GestionaCuenta.java

Caso de Uso: 5.2.2. Edicin de Cuenta JSP: edicionCuenta.jsp Servlet asociado: EditaCuenta.java

Caso de Uso: 5.2.3. Eliminacin de Cuenta JSP: portalCuentas.jsp Servlet asociado: GestionaCuenta.java

125

Anlisis y Uso de Frameworks de Persistencia en Java

4.5.2- Diagrama de Navegacin

En el siguiente diagrama viene reflejada la intaraccin entre todas las pginas JSP que forman el sistema. Todas las lneas de conexin implican navegacin bidireccional, exceptuando aquellas que terminan con punta de flecha. Las pginas JSP situadas dentro del recuadro gris slo son accesibles despus de realizar la identificacin.

126

Anlisis y Uso de Frameworks de Persistencia en Java

4.5.3- Diagramas de clases

La aplicacin 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 gestin, debiendo crear una clase por cada uno de ellos:

GESTIN DE PACIENTES GESTIN DE ALERGIAS GESTIN DE NOTICIAS GESTIN DE CUENTAS DE USUARIO

Paciente.java Alergia.java Noticia.java 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 versin del portal, utilizaremos clases DAO para trabajar con JDBC. En el captulo 5 se ver cmo se va a sustituir JDBC por un framework de persistencia. Hasta entonces se construir la aplicacin con JDBC, y stas sern sus clases DAO:

127

Anlisis y Uso de Frameworks de Persistencia en Java

Paciente.java Alergia.java Noticia.java Usuario.java

DAO_paciente.java DAO_alergia.java DAO_noticia.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

Anlisis y Uso de Frameworks de Persistencia en Java

Alergia.java

Noticia.java

129

Anlisis y Uso de Frameworks de Persistencia en Java

Usuario.java

130

Anlisis 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

Anlisis y Uso de Frameworks de Persistencia en Java

DAO_noticia.java

DAO_usuario.java

132

Anlisis y Uso de Frameworks de Persistencia en Java

4.5.4- El modelo de datos

En esta aplicacin 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 cmodamente la tecnologa que va a sustituir a JDBC.

Las clases estn 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 definirn por la lgica de la aplicacin.

Tabla PACIENTES

Tabla ALERGIAS En el caso de las Alergias, la clave debe ser compuesta, ya que la aplicacin no permite tener ms de un registro de un tipo de alergia para un mismo paciente.

133

Anlisis y Uso de Frameworks de Persistencia en Java

Tabla NOTICIAS

Tabla USUARIOS

134

Anlisis y Uso de Frameworks de Persistencia en Java

5- La alternativa a JDBC: Hibernate

135

Anlisis y Uso de Frameworks de Persistencia en Java

5- LA ALTERNATIVA A JDBC: HIBERNATE

Despus de haber diseado la aplicacin, se pueden identificar varias entidades que, a la hora de persistirlas en su base de datos, se van a corresponder con tablas. En este captulo se pretende describir cmo Hibernate abstrae al programador de la persistencia, creando las tablas a partir de las clases con las que se trabaja en la aplicacin.

La correspondencia entre clases y tablas es fundamental para mantener esa perspectiva orientada a objetos. Adems, se van a enfrentar las clases gestoras de objetos de Hibernate con las DAO equivalentes de JDBC, con el fin de observar cmo Hibernate evita el proceso de encapsulamiento y desencapsulamiento. Por ltimo se ver cmo es el proceso de implantacin, echando un vistazo a los requisitos del sistema y a la configuracin de la tecnologa.

5.1- LAS CLASES A PERSISTIR

Usuario.java

La clase Usuario es la ms extensa de todas las que se van a persistir. La aplicacin se encarga de que los valores correspondientes a

136

Anlisis 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 cdigo 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 validacin de usuarios public Usuario (String user, String pass){ this.user = user; this.pass = pass; } // Constructor por defecto: necesario para Hibernate

137

Anlisis 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

Anlisis 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 mtodos // Devuelve un String con el nombre completo del usuario public String getNombreCompleto() { String res = this.getAp1() +" "+ this.getAp2()+", "+ this.getNombre(); return res; } // Devuelve el cdigo 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 cdigo HTML para mostrar una fila de tabla // con la informacin de la cuenta. public String toListaHTML(){ String iconoPerfil; String iconoActividad; // Asignacin de perfil if ((this.cod_perfil).equals(Usuario.PERFIL_MEDICO)) { iconoPerfil = "<img src=\"Iconos/perfilMedMini.jpg\"width=\"40\" height=\"15\">"; }

139

Anlisis 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\">"; } } // Asignacin 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

Anlisis 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 cdigo 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

Anlisis 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 Mtodos public String getNombreCompleto() { String res = this.getAp1() +" "+ this.getAp2()+", "+ this.getNombre(); return res; } }

142

Anlisis y Uso de Frameworks de Persistencia en Java

Alergia.java

Esta clase es, aparentemente igual que las dems, pero en el cdigo 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

Anlisis 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 MTODOS 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 mtodos equals() y hashCode()

Esto se debe a que la aplicacin se encarga de que un paciente determinado tenga un registro de Alergia por cada tipo de alergia que padezca. Lgicamente esto quiere decir que los valores de dni y tipo formarn una clave compuesta en la tabla correspondiente. Para manejar

144

Anlisis 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 ms sencilla e independiente de la aplicacin. Este el cdigo 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; } // MTODOS // Getters y Setters public String getCuerpo() { return cuerpo; } public void setCuerpo(String cuerpo) { this.cuerpo = cuerpo; }

145

Anlisis 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 Mtodos 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

Anlisis 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 informacin Hibernate es capaz de relacionar los atributos con las columnas de la tabla, definiendo los tipos de datos basndose en el cdigo de la clase correspondiente.

A continuacin figuran los ficheros de mapeo de las diferentes clases a persistir.

147

Anlisis y Uso de Frameworks de Persistencia en Java

Usuario.hbm.xml

Este es el cdigo 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 </class> </hibernate-mapping> 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"/>

Entre otras cosas, el fichero le dice a Hibernate que persista la clase obj.Usuario en la tabla USUARIOS. Adems en la seccin <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 ningn generador, que el valor que lleve el atributo dni se persista en la base de datos.

148

Anlisis y Uso de Frameworks de Persistencia en Java

Paciente.hbm.xml

Este es el cdigo 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 </class> </hibernate-mapping> name="dni_med" column="dni_med"/> name="nombre" column="nombre"/> name="ap1" column="ap1"/> name="ap2" column="ap2"/> name="telefono" column="telefono"/>

149

Anlisis y Uso de Frameworks de Persistencia en Java

Alergia.hbm.xml

Este es el cdigo 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 cmo se mapea una clave compuesta. Se ha de utilizar la clusula <composite-id> indicando qu atributos van a formar la clave. En este caso dni y tipo sern la clave compuesta de la tabla ALERGIAS.

150

Anlisis y Uso de Frameworks de Persistencia en Java

Noticia.hbm.xml

Este es el cdigo 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

Anlisis 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 mtodos necesarios para que la aplicacin interaccione con la base de datos, Hibernate utiliza unas clases similares, que denominamos Clases Gestoras.

En las clases gestoras figuran todos los mtodos 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 transaccin de cualquiera de los objetos.

A continuacin se muestran las clases gestoras que se han implementado para utilizar Hibernate en la aplicacin diseada. Se pretende comparar estas clases con las DAO equivalentes que se usan al trabajar con JDBC.

152

Anlisis y Uso de Frameworks de Persistencia en Java

GestorUsuario.java

Tal y como se puede observar en el cdigo, 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

Anlisis 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 comprobacin // 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

Anlisis y Uso de Frameworks de Persistencia en Java

return res; } // Comprueba si existe el "dni". La comprobacin // 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

Anlisis 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

Anlisis 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(); } } // Validacin del LOGIN // Si los datos son vlidos, 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

Anlisis y Uso de Frameworks de Persistencia en Java

session.close(); } catch (HibernateException e){ e.printStackTrace(); } } } return res;

Para hacerse una idea de cmo Hibernate evita las tareas de encapsulamiento y desencapsulamiento, se puede observar el mtodo 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

Anlisis 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 fcil comprobar que la diferencia en cuanto a cantidad de lneas de cdigo es muy notable. Hibernate el se sirve clave con para

session.update(u),

comprobando

campo

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 insercin y borrado, respectivamente.

Otro punto interesante es que la clase Query de Hibernate redefine el mtodo List(), de forma que facilita el uso del resultado y no hay que recorrer el ResultSet como ocurre cuando se trabaja con JDBC.

159

Anlisis 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

Anlisis 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

Anlisis 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 mtodo: // 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

Anlisis 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

Anlisis 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

Anlisis y Uso de Frameworks de Persistencia en Java

/* Al tener una clave compuesta, para ejecutar el mtodo 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

Anlisis 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

Anlisis y Uso de Frameworks de Persistencia en Java

session.close(); } catch (HibernateException e) { e.printStackTrace(); } return it; } }

167

Anlisis 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

Anlisis 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

Anlisis 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 cdigos de las noticias: // ... se utilizar despues de una operacin de baja. // Devuelve el nmero 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); } } tx.commit(); session.close(); } catch (HibernateException e) { System.out.println("ERROR: hib exception en recodificarNoticias()"); cont++;

170

Anlisis y Uso de Frameworks de Persistencia en Java

e.printStackTrace(); Integer res = new Integer(cont - 1); return res;

} }

171

Anlisis y Uso de Frameworks de Persistencia en Java

5.4- IMPLANTACIN

5.4.1. Instalacin y Configuracin

Primero hay que bajarse Hibernate 3.0 de su pgina de descarga. Despus hay que extraerlo y colocar los .jar la carpeta lib del proyecto Web, as como el conector de la base de datos MySQL.

La configuracin de Hibernate se realiza a travs de un archivo XML llamado hibernate.cfg.xml que se situar en la carpeta JavaSource. En la pgina siguiente se puede ver el cdigo del archivo, con los datos necesarios para adaptarlo a esta aplicacin.

Como se puede apreciar, en las secciones <property> se especifica todo lo necesario para realizar la conexin a la base de datos MySQL clinica_paya, incluyendo el usuario y la contrasea. 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 informacin y ser capaz de crear las tablas especificadas por los ficheros de mapeo.

172

Anlisis 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 sencillsima 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 edicin de este archivo y para la creacin de ficheros de mapeo.

173

Anlisis 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

Anlisis y Uso de Frameworks de Persistencia en Java

6- Presupuesto

175

Anlisis 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 condicin de ingeniero tcnico titulado.

COSTES DE DESARROLLO
Estudio......................................................................

80 horas x 26 /h = 2.080 80 horas x 26 /h = 2.080 horas x 24 /h = 2.400

Anlisis.....................................................................

Programacin..........................................................100

COSTES DE IMPLANTACIN Configuracin y pruebas............................................. 40 horas x 20 /h = 800

TOTAL..................................7.360

176

Anlisis y Uso de Frameworks de Persistencia en Java

7- Conclusiones

177

Anlisis 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 crtico para el comportamiento de una aplicacin.

La aplicacin Web se ha desarrollado utilizando Hibernate, pero paralelamente se ha codificado el mdulo equivalente en JDBC. Esto ha permitido que percepcin del contraste sea completa, haciendo posible reafirmar las conclusiones obtenidas tras realizar el estudio terico.

Tras la conclusin del desarrollo se ha comprobado que la programacin con Hibernate es mucho ms sencilla y llevadera, ya que nos libera de tareas tan speras como el encapsulamiento y desencapsulamiento de los objetos, y pone a nuestra disposicin una API completsima y fcil de usar. Sin embargo, despus de concluir con la implantacin del portal, ha quedado patente que los accesos con JDBC son siempre ms rpidos que los gestionados por un framewok como Hibernate, tal y como se haba predecido en el estudio.

Estas conclusiones se corresponden perfectamente con las pretensiones del proyecto. La intencin del trabajo era confrontar y mostrar el funcionamiento de las alternativas, creando finalmente una herramienta de trabajo sencilla y verstil.

178

Anlisis y Uso de Frameworks de Persistencia en Java

La realizacin de este proyecto me ha aportado una grandsima experiencia personal y acadmica.

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 planificacin diferente para cada una de ellas. Por otra parte, el desarrollo de la aplicacin ha sido posible gracias al aprendizaje de mltiples herramientas software, ampliando as mis conocimientos en un gran rango de materias.

El director del proyecto me ha sabido transmitir qu tipo de proyecto tena en mente. La filosofa seguida a lo largo del mismo ha conseguido que la documentacin tome continuidad entre sus captulos y sea entretenida su lectura.

179

Anlisis y Uso de Frameworks de Persistencia en Java

8- Bibliografa

180

Anlisis y Uso de Frameworks de Persistencia en Java

8- BIBLIOGRAFA

Libros consultados:

[MONS04]

Monson-Haefel R. Enterprise JavaBeans, OReilly, 4

Edicin, 2004.

[BERG03]

Bergsten H. JavaServer Pages, OReilly, 3 Edicin, 2003.

[SING02]

Singh I. Designing Enterprise Applications with the J2EE

Platform, Addison Wesley, 2 Edicin, 2002.

[HUNT01] 2001.

Hunter J. Java Servlet Programming, OReilly, 2 Edicin,

[BARR01]

Barranco J. Metodologa del anlisis estructurado de

sistemas, Publicaciones Universidad Pontificia de Comillas, 2 Edicin, Madrid, 2001.

[FOWL99]

Fowler, M. UML gota a gota, Addison Wesley, Mxico 1999.

[GOSL96]

Gosling, J. The Java Programming Language, Addison

Wesley, Massachusetts 1996. 181

Anlisis y Uso de Frameworks de Persistencia en Java

Otras fuentes:

Pgina oficial de Hibernate: www.hibernate.org Web sobre JDO: www.JDOcentral.com Programacin en castellano: www.programacin.com

182

También podría gustarte