Download Estrategias de Persistencia en Java basadas en estándares
Document related concepts
no text concepts found
Transcript
Estrategias de Persistencia en Java basadas en estándares Ing. Yumar Sotolongo Rivero, Ing. Howard Egaña Marrero Resumen. La persistencia de los objetos resulta imprescindible para la inmensa mayoría de las aplicaciones que se desarrollan en la actualidad. En el entorno Java, existen varios estándares y técnicas disponibles para afrontar el problema de hacer persistir los objetos en el desarrollo de software. Sin embargo, no todos resuelven el problema de la misma forma, ni son ideales en los mismos casos. En este artículo se exponen un conjunto de estándares existentes en la industria de Java que van desde el más elemental, la serialización de objetos, hasta soluciones como Java Database Connectivity, Enterprise JavaBeans y el ultimo estándar del Java Community Process, Java Persistence API, dirigido a normalizar el Mapeo Objeto Relacional. El presente artículo está enfocado a conocer las principales características, funcionalidades, ventajas y desventajas de cada propuesta, con el objetivo de tener los elementos necesarios para decidir qué mecanismo de persistencia utilizar en una situación determinada. En el trabajo se realizan comparaciones de interés sobre los distintos estándares abordados. frameworks3 a merced de los desarrolladores, para el desarrollo de aplicaciones en el entorno de Java. La persistencia de la información es un factor crítico en cualquier aplicación. Persistencia es la capacidad que tiene un objeto de existir y funcionar fuera del tiempo de vida de la aplicación que lo creó [1]. En este sentido, el tiempo de vida de los objetos no depende del tiempo de ejecución de la aplicación, puesto que el objeto existe mientras pueda ser invocado en el contexto del programa [2]. El presente trabajo expone estándares que existen en la industria de Java para realizar la persistencia de la información. Se realiza una descripción de las principales clases que conforman estos estándares, así como las desventajas que presentan cada uno de ellos. El trabajo se enfoca en el uso de estándares, debido que la utilización de los mismos se considera una vía para lograr la interoperabilidad con otros entornos y aplicaciones legadas. Palabras Claves. Entity Beans, Estándares de Persistencia en Java, JDBC, JPA, Persistencia en Java, Serialización. II. SERIALIZACIÓN DE OBJETOS I. INTRODUCCIÓN Las plataformas de desarrollo Java Platform, Standard Edition1 (Java SE) y Java Platform, Enterprise Edition2 (Java EE) ambas de la compañía Sun Microsystems, Inc., brindan un marco de trabajo basado en estándares para la implementación de aplicaciones de escritorio y empresariales respectivamente. El éxito de estas plataformas, sustentado principalmente en la portabilidad, seguridad y reusabilidad que prometen, ha ocasionado que el mayor porciento de desarrolladores hoy en día se incline a utilizarlas, para construir aplicaciones con la mayor calidad posible. Asimismo, existen diversas compañías que entregan soluciones no-estándares propietarias o libres implementadas en Java, pero no obstante, con un alto grado de eficacia y rendimiento. Lo anterior ha dado lugar que existan disímiles EL API Java Serialization permite persistir la información de un modelo de datos representado por un grafo. Este mecanismo guarda el estado de todas las instancias de objetos al disco de almacenamiento, y reconstruye en memoria los objetos salvados del grafo [3]. Serializar una instancia de objeto es el proceso de escribir sus atributos miembros a disco a través de un flujo de bytes. De forma inversa, deserializar es la operación que posibilita reconstruir una instancia de objeto a partir del valor de sus atributos escritos en disco [3] [4]. La definición de serialización en Java ha sido abordada por diferentes fuentes mencionándose: • Según Bruce Eckel, “la serialización de objetos de Java permite tomar cualquier objeto que implemente la interfaz Serializable y convertirlo en una secuencia de 1 Anteriormente conocida como Java 2 Platform, Standard Edition (J2SE). Anteriormente conocida como Java 2 Platform, Enterprise Edition (J2EE) 2 3 Estructura de soporte definida sobre la cual otro proyecto de software puede ser organizado y desarrollado. CCIA’2008 bytes que puede después ser completamente restaurada para regenerar el objeto original” [2]. • Según William Grosso, “Serialización es el proceso de convertir un conjunto de instancias de objetos que contienen referencias unas a otras en una secuencia lineal de bytes, las cuales puedan ser enviadas a través de un socket, salvadas a un archivo, o simplemente manipuladas como una secuencia de datos” [5]. Los autores del presente trabajo encuentran que cualquiera de las definiciones anteriores puede ser tomada como válida. El mecanismo de serialización de Java también tiene validez entre sistemas operativos diferentes, siendo posible crear un objeto en un ordenador, serializarlo y enviarlo a través de la red a otro ordenador con una arquitectura diferente para que sea reconstruido. Esta característica contribuye a la portabilidad de las aplicaciones Java, puesto que la representación de los datos en arquitecturas heterogéneas, la ordenación de los bytes, entre otras cuestiones, se consideren abstractas [2]. La serialización permite implementar la persistencia en una aplicación, debido a que la información contenida en los objetos guardados se mantiene más allá del tiempo de ejecución. El estado de los objetos puede ser reconstruido en el programa original u otro a partir de esta información. El API Java Remote Method Invocation (Java RMI) utiliza la serialización como mecanismo para pasar objetos entre máquinas virtuales de Java, tanto como argumento en la invocación remota del cliente hacia el servidor, así como en el valor de retorno de la misma [5]. Java Serialization utiliza un formato especial de fichero binario específico para Java con el propósito de almacenar la información. Asimismo, este API oculta la mayor parte de la complejidad requerida para serializar grafos de objetos, haciendo que el desarrollador solo necesite tratar con dos clases y dos interfaces para utilizar las funcionalidades contenidas en este [3]. Las clases ObjectInputStream y ObjectOutputStream del paquete java.io posibilitan que los objetos serializados puedan ser enviados a través de la red o sencillamente almacenados en disco; mientras las interfaces Serializable y Externalizable pertenecientes al mismo paquete, permiten serializar las clases que las implementen. La función de las clases e interfaces que conforman el API Java Serialization se describe a continuación [3]: • Serializable: Interfaz para marcar que una clase soporta serialización. • ObjectInputStream: Clase que representa la secuencia de entrada usada para leer instancias de objetos que fueron escritos por un ObjectOutputStream. • ObjectOutputStream: Clase que representa la secuencia de salida usada para escribir instancias de objetos para ser leídos por un ObjectInputStream. • Externalizable: Interfaz que hereda de Serializable para proporcionar a una clase el control completo sobre como leer y escribir los flujos de bytes. Existen cuatro pasos para acometer la serialización de objetos: 1. Hacer que la clase tenga un constructor sin argumentos. 2 2. Implementar la interfaz Serializable o Externalizable para denotar que la clase soporta la serialización. 3. Usar ObjectOutputStream para serializar el objeto. 4. Usar ObjectInputStream para leer el objeto serializado y restaurarlo de en la memoria de la aplicación. El uso de un constructor sin argumentos es un requisito indispensable, debido que el API de serialización necesita crear instancias vacías de una clase al deserializar la información. Para ejecutar el proceso anterior y restablecer el valor de los miembros de la clase, Java Serialization emplea el API Java Reflection de forma implícita. La interfaz Serializable no contiene métodos, solo denota al API que la clase que la implementa es serializable, expresado de otra forma, indica comportamiento [6]. La serialización resulta un mecanismo de persistencia inadecuado para aplicaciones web y empresariales con alta concurrencia. Esto se debe a que un conjunto de objetos serializados debe ser accedido como un todo, siendo imposible recuperar la información sin deserializar el flujo de bytes en su totalidad. Además, el flujo de bytes después de la deserialización se considera inapropiado para realizar búsquedas arbitrarias, dado que no se puede acceder ni modificar objetos o conjunto de estos de forma independiente. La serialización proporciona un mecanismo de persistencia apropiado para aplicaciones de escritorio [7]. III. JAVA DATABASE CONNECTIVITY Java Database Connectivity (JDBC) es un API independiente de la Base de Datos (BD) y de la plataforma del sistema operativo, que permite establecer conexión a programas desarrollados en el lenguaje Java, con una gran variedad de gestores de BD. Este API define un conjunto de interfaces que encapsulan las principales funcionalidades de las BD, que son utilizadas en las aplicaciones Java sin comprometer las portabilidad de la misma [8] [9]. Según la Cía. Sun Microsystems Inc.: “El API JDBC es el estándar de la industria para la conectividad independiente de la base de datos entre el lenguaje de programación Java y una amplia variedad de base de datos – base de datos SQL4 y otras fuentes de datos tabulares, como hojas de cálculos o ficheros planos… JDBC proporciona un API a nivel de llamadas para el acceso a bases de datos basadas en SQL” [10]. La especificación de JDBC está basada a su vez en otra especificación, X/Open SQL Call Level Interface (CLI), la cual ofrece un método alterno para acceder BD mediante sentencias SQL codificadas dentro de una aplicación. CLI ha sido adoptado por la International Organization for Standardization (ISO) como estándar internacional [3]. JDBC le concede al programador una vía simple para ejecutar sentencias SQL con el objetivo de realizar consultas, procesar resultados y determinar información de configuración sobre disímiles fuentes de datos [9]. La característica más sobresaliente de este API, reside en su 4 Acrónimo de Structured Query Language, lenguaje estandarizado para definir y manipular datos en Bases de Datos Relacionales. CCIA’2008 diseño eficaz y flexible para trabajar indistintamente con cualquier Sistema Gestor de Base de Datos Relacional (RDBMS, de su nombre en inglés Relational DataBase Management System), lo cual confiere un alto grado de portabilidad a las aplicaciones que utilicen JDBC. La particularidad anterior de JDBC se justifica en que la misma proporciona una interfaz uniforme por encima de la gran variedad de módulos de conectividad a la BD [11]. El API JDBC incluye las clases e interfaces necesarias para realizar las operaciones más comunes asociadas a la BD [1] [11] [12]: • Establecer una conexión con una BD u otra fuente de datos, ya sea remota o local • Enviar sentencias SQL a la BD • Procesar los resultados JBDC es un API basado en una especificación brindando la posibilidad que cada proveedor de BD realice implementaciones específicas en forma de drivers [13] [14]. Un driver JDBC es una capa de software intermedia, responsable de traducir las llamadas vía JDBC a los APIs específicos del proveedor de BD [15]. Los drivers JDBC pueden ser clasificados en cuatro tipos y agrupados de acuerdo a su implementación [3] [9] [15] [16]: Parcial Java 1. Tipo 1 - Driver Puente JBDC-ODBC5 (JDBC-ODBC bridge driver): Traduce las llamadas JDBC a llamadas ODBC correspondientes. El proceso de la aplicación cliente comprende la invocación a las clases Java para el API JDBC y el puente JDBC-ODBC, mientras la capa ODBC se ejecuta en otro proceso. Esta solución ofrece como principales ventajas: la habilidad de conectarse a la mayoría de los gestores de BD en todas las plataformas soportadas por la Máquina Virtual de Java (JVM, de su nombre en inglés Java Virtual Machine) y puede ser la única vía para obtener acceso a BDs ligeras de tipo escritorio. El Puente JBDC-ODBC puede generar bajo rendimiento, debido a las múltiples capas implicadas en los procesos de invocar sentencias SQL desde la aplicación Java y devolver los resultados hacia la misma, representando su mayor desventaja. 2. Tipo 2 - Driver API Nativo/Parte Java (Native API/Part Java Driver): Convierte las llamadas JDBC a llamadas específicas de la BD a través de la comunicación directa con las librerías nativas del proveedor de BD. La utilización de drivers Tipo 2 proporciona un mayor rendimiento sobre los de Tipo 1, puesto que los primeros utilizan los protocolos específicos del fabricante para comunicarse con la BD de forma eficiente. Este tipo de driver requiere la presencia de código binario en el ordenador cliente, el cual es usualmente particular del sistema operativo pudiendo crear dependencia con el mismo. Total Java 5 Acrónimo de Open Database Connectivity, estándar desarrollado por la Cía. Microsoft que permite acceder datos desde cualquier aplicación independientemente del tipo de Sistema Gestor de Base de Datos utilizado. 3. 3 Tipo 3 - Servidor intermediario de acceso a BD (Netprotocol All-Java drivers): Utiliza un servidor intermedio con capacidad de conectar múltiples aplicaciones Java a distintos gestores de BD. Los drivers Tipo 3 siguen una estrategia de tres capas donde las peticiones JDBC son pasadas a través de la red mediante un protocolo genérico a un componente de software que reside en el servidor intermedio. El componente se encarga de completar la solicitud al Sistema Gestor de Base de Datos (DBMS, de su nombre en inglés Database Management System), pudiendo utilizar diferentes protocolos nativos y tipos de drivers para conectarse con los distintos DBMS. Las principales ventajas asociadas a los drivers Tipo 3 son: no requieren que ninguna librería específica del proveedor de BD esté presente en el ordenador cliente, soportan diferentes sistemas y protocolos de red y permiten optimizar la portabilidad, rendimiento y escalabilidad de la aplicación. La mayor desventaja de esta solución se centra en la seguridad. 4. Tipo 4 - Driver Protocolo Nativo puro Java (NativeProtocol Pure Java Driver): Traduce las peticiones JDBC al protocolo de red específico del proveedor del DBMS, con el objetivo de que las aplicaciones clientes puedan establecer conexiones de socket directas con el servidor de BD. Los drivers Tipo 4 son plenamente implementados en el lenguaje Java por los vendedores de DBMS, así como por terceras partes, alcanzando independencia de la plataforma. Puesto que los drivers Tipo 4 no necesitan traducir las solicitudes JDBC a un puente ODBC o al API nativo en código binario del proveedor del DBMS, ofrecen mayor rendimiento que los drivers Tipo 1 y Tipo 2. Esta solución es más fácil de desplegar, debido que no se necesitan librerías adicionales ni servidores intermedios que instalar. Las ventajas anteriores hacen que los drivers Tipo 4 sean los idóneos para el acceso a BD. Las soluciones Tipo 4 requieren el empleo de un driver diferente para cada DBMS, lo que se presenta como una desventaja. El API JDBC está conformado por dos paquetes, java.sql y javax.sql. El primero de ellos, java.sql, contiene el núcleo original del API y sus clases e interfaces pueden dividirse en grupos de acuerdo a su funcionalidad [15]: • Gestión de conexión • Acceso a base de datos • Tipos de datos • Metadatos de base de datos • Excepciones y advertencias Las principales clases e interfaces que constituyen el eje central del paquete java.sql son [8] [15]: • Driver Manager: Clase responsable por gestionar drivers JDBC cargados en memoria, y como factoría para crear objetos Connection a las distintas fuentes de datos que los drivers representan. • Driver: Interfaz que abstrae el protocolo de conexión específico del proveedor de BD. La implementación de CCIA’2008 esta interfaz es suministrada por el fabricante del DBMS, así como por terceras partes. • Connection: Interfaz que representa una conexión con una fuente de datos. Se utiliza para crear objetos de tipo Statement, PreparedStatement y CallableStatement. • DatabaseMetadata: Interfaz que se obtiene a partir de un objeto Connection con el objetivo de proporcionar información detallada de la BD. • Statement: Interfaz que representa una sentencia SQL estática. Se emplea para recuperar objetos ResultSet. • PreparedStatement: Interfaz que extiende de Statement y significa una sentencia SQL pre compilada. • CallableStatement: Interfaz que representa un procedimiento almacenado en el DBMS. • ResultSet: Interfaz que representa el conjunto de tuplas obtenidas de la BD a partir de sentencias SQL. Trata la información mediante un cursor que puede ser desplazado. • ResultSetMetaData: Interfaz que brinda información sobre los tipos y propiedades de las columnas en un objeto ResultSet. • SQLException: Clase de representa todas las condiciones de excepción relacionadas con JDBC. Para representar los tipos SQL más utilizados por los DBMS, JBDC define un conjunto genérico de tipos de datos SQL en la clase java.sql.Types. El API especifica además, una estrategia de mapeo estándar entre los tipos de datos JDBC y los tipos de datos Java. Esta característica de JDBC, permite que los desarrolladores de aplicaciones Java no se preocupen por los tipos SQL soportados por los diferentes proveedores de BD y las variaciones que puedan existir entre ellos [17]. El paquete javax.sql, es opcional y contiene funcionalidades que simplifican la programación JDBC en un paradigma distribuido como es la plataforma Java EE [15] [17]: • Búsqueda de base JNDI6 para acceder a BD. Permite que los clientes en lugar de cargar drivers JDBC en sus respectivas JVM, utilicen búsquedas de base JNDI para acceder a recursos de BD utilizando nombres lógicos asignados a estos recursos. • Reserva de conexiones. Este paquete especifica una capa intermedia adicional para implementar reserva de conexiones a BD, responsabilidad que es desempeñada por el proveedor de DBMS y el servidor de aplicaciones Java EE. • Transacciones distribuidas. Especifica un marco para el soporte de transacciones distribuidas de forma transparente bajo el paquete java.sql. • Conjunto de filas (RowSet). Un objeto RowSet representa un componente envoltorio alrededor de un objeto ResultSet que se ajusta a JavaBean7, encapsulando el acceso a la BD incluido el resultado. Los objetos RowSet poseen atributos que pueden ser 6 Acrónimo de Java Naming and Directory Interface, API que brinda un servicio de directorio que permite a las aplicaciones Java descubrir y buscar datos y objetos a través de nombres lógicos. 7 Modelo de componentes de software reusables para Java que se pueden manipular visualmente con una herramienta de desarrollo. 4 manipulados por los correspondientes métodos de acceso y una serie de eventos que pueden escuchar los objetos interesados. Figura 1. Aplicaciones Java usando drivers JDBC para conectarse a diferentes DBMS. Tomado de [8]. La última especificación de JDBC incluyó nuevas funcionalidades como soporte de anotaciones y de tipo de datos XML, y nuevas clases para el tratamiento de excepciones y la carga de drivers [3] [14]. Si bien JDBC facilita la conexión a disímiles fuentes de datos, envío de sentencias SQL para realizar cualquier tipo de operación sobre los datos y manejo de transacciones, también presenta inconvenientes: • Tiempo de codificación. El código se hace repetitivo (Insert, Select, Update, Delete) para cada objeto del modelo; el programador debe encargarse de cerrar las conexiones así como del manejo de las transacciones. • Portabilidad. Con frecuencia es necesario tratar con código SQL específico a un DBMS. • Mantenimiento del sistema. Tener código SQL embebido en la lógica de negocio, hace más difícil el mantenimiento y la detección de errores en un caso de uso determinado de la aplicación. IV. ENTERPRISE JAVABEANS La plataforma Java EE es el estándar para desarrollar aplicaciones Java del lado del servidor, portables, robustas, escalables y seguras. Establecida sobre las sólidas bases de Java SE, Java EE especifica los APIs para servicios Web, modelo de componentes, administración y comunicaciones, que lo convierten en el estándar de la industria para implementar una Arquitectura Orientada a Servicios (SOA, de su nombre en inglés Service-Oriented Architecture) y la nueva generación de aplicaciones Web [18]. Los Enterprise JavaBeans (EJB) encapsulan la lógica de negocio de una aplicación y constituyen la piedra angular de las especificaciones de Java EE [19] [20]. Un enterprise bean CCIA’2008 es un componente de software del lado del servidor que puede ser desplegado en un entorno multicapas distribuido. Independientemente de la composición del enterprise bean, los clientes siempre tratan con la interfaz que este expone. La interfaz y el componente deben cumplir con la especificación EJB, la cual dicta que el último exponga un conjunto de métodos requeridos para que el contenedor EJB gestione idénticamente el ciclo de vida del enterprise bean, sin importar en que contenedor este se esté ejecutando [21]. La especificaciones 2.x de Java EE definen tres tipos diferentes de enterprise beans [21] [22] [23] [24] [25]: • Session bean: Modela procesos del negocio describiendo interacciones entre otros enterprise beans e implementa tareas específicas. • Entity bean: Representa entidades de negocio que existen en un medio de almacenamiento. • Message-driven bean: Actúa como un oyente del API Java Message Service, procesando mensajes de forma asíncrona. Un componente entity bean representa un objeto de negocio en un RDBMS u otro medio de almacenamiento de información. Cuando el medio de almacenamiento es un RDBMS, el componente entity bean está asociado a una tabla en la BD subyacente y cada instancia del componente se corresponde a una fila o tupla de esa tabla. Los componentes de entidad difieren de los de sesión, en que los primeros son persistentes, permiten el acceso compartido, tiene llaves primarias que los identifican y pueden estar relacionados con otros componentes [21] [22]. Los servidores de aplicaciones de la plataforma Java EE proporcionan un período de ejecución, para gestionar los componentes de la aplicación desarrollados según las especificaciones de la tecnología [26]. Los servidores de aplicaciones tienen la responsabilidad de la gestión del ciclo de vida de los componentes de la aplicación y proporcionan al desarrollador el medio para acceder a los API de J2EE como si el contenedor subyacente los implementara. La especificación 1.4 de la plataforma Java EE define dos mecanismos de persistencia para los entity beans: • Persistencia administrada por el desarrollador (BMP, de su nombre en inglés Bean-Managed Persistence). • Persistencia administrada por el contenedor (CMP, de su nombre en inglés Container-Managed Persistence). Para los entity beans implementados con persistencia BMP, el desarrollador debe escribir el código para las llamadas de acceso a la BD. A pesar de que escribir este código es una responsabilidad adicional, el desarrollador tendrá más control sobre cómo el componente de entidad accede al mecanismo de almacenamiento [22]. Para implementar la persistencia BMP generalmente se emplea un API para el trabajo con BD como JDBC, o una herramienta para el mapear un modelo de datos a un RDBMS. La persistencia BMP generalmente se usa, cuando el mecanismo CMP proporcionado por el servidor de aplicaciones no satisface el rendimiento deseado. La principal desventaja de BMP es que puede comprometer la portabilidad de la aplicación [21]. El mecanismo de persistencia CMP significa que el contenedor EJB maneja todos los accesos a la BD requeridos 5 por el entity bean. Como resultado el componente no se encuentra ligado a ninguna BD en específico, debido a que el no contiene llamadas SQL explícitamente. Gracias a esta flexibilidad, se puede volver a desplegar los componentes entity beans en diferentes servidores de aplicaciones que usen distintos gestores de BD, sin necesidad de modificar o recompilar el código de la aplicación Java EE. Los componentes de entidad que utilizan persistencia CMP son más portables en relación a los diferentes gestores de BD que aquellos que utilizan BMP [21] [26]. La especificación 2.1 del estándar EJB presenta soporte para Relaciones administradas por el contenedor (CMR, de su nombre en inglés Container-Managed Relationships) como parte de la arquitectura CMP. CMR refiere la habilidad que múltiples componentes entity beans puedan tener relaciones entre ellos, igual que en la Programación Orientada a Objetos (POO). El contenedor EJB se encarga de administrar y mantener la integridad referencial en relaciones 1:1, 1:m y m:m [25] [27]. La especificación 2.0 de EJB introdujo Enterprise JavaBeans Query Language (EJB QL), con el objetivo de proporcionar un lenguaje de consulta portable entre contenedores EJB. EJB QL presenta una sintaxis parecida a SQL para ejecutar consultas sobre los entity beans con persistencia CMP. EJB QL define consultas para métodos de búsqueda y proyección [24] [27]. Anterior a la especificación 2.0 de EJB los servidores de aplicaciones decidían individualmente la forma y el lenguaje para realizar consultas. La mayoría de las veces los desarrolladores usaban SQL o un lenguaje propietario específico del servidor de aplicaciones [27]. EJB QL permite consultar o navegar a través de las relaciones de un entity bean, requiriendo que las relaciones del componente sean expresadas como relaciones CMR en el descriptor de despliegue. La principal ventaja de EJB QL sobre SQL, es la portabilidad que se logra entre contenedores EJB y la habilidad de navegar relaciones [27]. El descriptor de despliegue es un documento XML que contiene información declarativa sobre los componentes EJB que pertenecen a un despliegue. Un descriptor de despliegue puede ofrecer información sobre múltiples componentes EJB, que se encuentren ensamblados dentro de una aplicación [27]. EJB en su versión 1.4 brinda ventaja como servicios de forma transparente para las transacciones, seguridad y persistencia CMP; rendimiento a través de la cache del servidor de aplicaciones y soporte para objetos distribuidos, entre otros [21] [22]. Las principales desventajas la especificación 1.4 presenta son [28]: • El trabajo con entity beans se hace demasiado complejo, comprende bastante tiempo de programación y brinda un rendimiento pobre comparado con otras estrategias de persistencia. • Falta de portabilidad dado que en la definición del descriptor de despliegue no son especificadas todas las propiedades para el mapeo hacia RBDMS, además de que cada servidor de aplicaciones presenta un descriptor especifico. CCIA’2008 • No soporta la representación de la herencia del Modelo de Objetos al Modelo Relacional, complejidad para la carga perezosa de los componentes de entidad, limitaciones en el lenguaje EJB QL para soportar consultas anidadas y falta de un mecanismo de paginado en las consultas. • El mecanismo de persistencia se centra en componentes pesados en memoria que implementan interfaces. V. MAPEO OBJETO RELACIONAL Para la mayoría de las aplicaciones existentes hoy en día, almacenar y recuperar la información implica de alguna forma interactuar con un RDBMS. Esto ha representado un problema adicional para el desarrollo de Software Orientado a Objetos debido a las diferencias existentes entre el Modelo Relacional y el Modelo Orientado a Objetos. La naturaleza tabular de las BD relacionales está basada en conceptos matemáticos para guardar y recuperar datos. El diseño de una BD relacional tiene como objetivo principal normalizar la información para eliminar la redundancia de los datos. La meta del diseño Orientado a Objetos (OO) es modelar procesos de negocio dividiéndolo en objetos con identidad, estado, relaciones y comportamiento. Conceptos como clases, herencia, encapsulación y polimorfismo inherentes a la Programación Orientada a Objetos (POO), no tienen soporte en las BD relacionales [29] [30]. Las diferencias presentes entre el paradigma OO y el relacional se conocen como brecha objeto-relacional. Esta brecha en gran parte está ocasionada por la divergencia en la forma de representar los atributos en los dos modelos, teniendo una representación tabular y otra jerárquica. Las incompatibilidades entre las tecnologías de POO y los RDBMS impulsan a los desarrolladores a mapear atributos, asociaciones, relaciones y herencia del modelo de objetos a uno relacional. La utilización de Objetos de Valor (VO, de su nombre en inglés Value Object) que contienen información del estado de las entidades del negocio y sus relaciones, con el propósito de transferirlos a la capa de acceso a datos responsable de realizar el correspondiente mapeo hacia el RDBMS, puede ser una solución. Considerando negocios complejos y objetos con bastantes atributos y relaciones, el trabajo sería complejo y con desgaste para el desarrollador [7] . Existen estudios que indican que el treinta porciento del código escrito en una aplicación Java, se produce para manejar la incompatibilidad entre el paradigma OO y el relacional [7]. Como consecuencia de lo anterior, se han implementado varias tecnologías con la intención de brindar un puente entre el paradigma relacional y el OO. Ninguna ha incitado tanto interés como las que proponen el empleo de un mecanismo de Mapeo Objeto Relacional (ORM, de su nombre en inglés Object Relational Mapping). ORM es un mecanismo transparente para la persistencia de objetos del modelo de dominio a tablas en el Modelo Relacional, usando metadatos que describen el mapeo entre 6 los objetos y la BD. La transformación de los datos de una representación a otra ciertamente implica un declive en el rendimiento de la aplicación. No obstante, si el ORM es implementado como una pieza de software intermedia entre el Modelo de Objetos y el Relacional (ej. Hibernate y TopLink Essentials), existen posibilidades para la optimización, que no serían posibles con una implementación manual de la persistencia [7] [28]. La utilización de una implementación ORM permite obtener beneficios de mayor productividad en el proceso de desarrollo del software, puesto que el desarrollador puede enfocarse en el modelo del dominio, y dejar al proveedor del framework ORM la responsabilidad de la persistencia de los objetos. Esta propiedad de los mecanismos ORM, ahorra la necesidad de escribir código SQL y mantiene las ventajas de la POO, constituyendo sin dudas, un aspecto a favor del mantenimiento de la aplicación. Asimismo, el código de la aplicación no queda comprometido con ningún RDBMS en particular, pues el framework ORM se encarga de realizar el mapeo y la creación de consultas SQL específicas al proveedor de la BD [7] [28]. Las características básicas que debe brindar un proveedor ORM para elaborar la capa de persistencia de una aplicación, se resume en tres habilidades [31]: 1. Forma declarativa para ejecutar el Mapeo Objeto Relacional. Este método es conocido como metadatos para el ORM, y permite definir como será mapeado un objeto a una o más tablas de un RDBMS. Típicamente se realiza mediante la utilización de ficheros XML, que almacenan los datos de las transformaciones objetorelacional, o través de anotaciones embebidas en el código. 2. API para manipular las entidades. Este API se encarga de las operaciones Crear, Leer, Actualizar y Eliminar (CRUD, de su nombre en inglés Create, Read, Update and Delete) sobre los objetos persistentes. Basado en el API y en los metadatos de ORM, los proveedores de persistencia realizan las operaciones en la BD de forma transparente. El API evita el empleo de código JDBC o SQL para hacer persistir los objetos del dominio. 3. Lenguaje de consultas para recuperar objetos. Este es uno de los más importantes aspectos de la persistencia, pues permite recuperar los datos a través de un lenguaje de consulta genérico Orientado a Objetos sin la necesidad de escribir código SQL específico de ningún RBDMS. VI. JAVA PERSISTENCE API Java Persistence API (JPA) es una especificación de Java encargada de las cuestiones de persistencia para acceder, almacenar y manejar datos entre el Modelo de Objetos representado por instancias de clases Java con sus relaciones, comportamiento y atributos, y el Modelo Relacional representado por tablas y relaciones en un RDBMS. JPA fue definido como parte de otra especificación mayor, EJB 3.0, a modo de reemplazo a la persistencia CMP de las CCIA’2008 especificaciones EJB 2.x, siendo el estándar actual en la industria de Java para el Mapeo Objeto Relacional [24] [25] [32] [33]. JPA es una especificación que consiste en un grupo de interfaces que requieren implementación, para cuales existen soluciones tanto en los ámbitos open source8 como en el propietario. Igualmente, todos los servidores de aplicaciones que implementen la especificación Java EE 5 brindan soporte para la utilización de JPA como mecanismo de persistencia [20]. JPA estandariza el Mapeo Objeto Relacional a través de anotaciones de metadatos y/o descriptores XML, que especifican como los Objetos Planos de Java (POJO, de su nombre en inglés Plain Old Java Object) serán representados en tablas de un RDBMS [34]. Se definen además, los APIs EntityManager, responsable de ejecutar las operaciones CRUD y el manejo de transacciones sobre los objetos, y Java Persistence Query Language (JPQL), capaz de ofrecer un lenguaje de consultas orientado a objetos, con sintaxis parecida a SQL y habilidad de generar consultas dinámicas y estáticas [31] [32]. Figura 2. El EntityManager actúa como puente entre el Modelo OO y el Relacional. Tomado de [35]. En las especificaciones anteriores de EJB los componentes de entidad o entity beans son pesados en memoria, dependientes del servidor de aplicaciones y del entorno de ejecución de Java EE. JPA define que las entidades persistentes son gestionadas por el proveedor de persistencia, dado que este brinda una implementación de JPA, y a diferencia de EJB 2.x no es requerido que la entidades hereden de ninguna clase o implementen interfaces definidas en las especificación. Las especificaciones anteriores no detallaban como los entity beans debían ser mapeados a los RDBMS, por parte de los servidores de aplicaciones, lo cual determinaba que en la mayoría de los casos estos componentes no fueran portables entre los diferentes proveedores de Java EE. JPA sigue un criterio distinto, al definir un mecanismo ORM completo que incluye como serán mapeados los POJOs, asegurando la portabilidad entre los diferentes proveedores. El hecho que las entidades sean tratadas como POJOs en la especificación JPA, permite que estas puedan ser utilizadas en aplicaciones Java que se ejecutan fuera del contexto Java EE y empleadas como Objetos de Transferencia de Datos (DTO, de su nombre en inglés Data Transfer Object) entre el cliente y el servidor Java EE [28] [34] [36]. Las características más importantes de JPA comprenden: Persistencia basada en POJO. Un aspecto notable de JPA lo constituye que las entidades persistentes son POJOs, de forma que no existe ninguna diferencia con los objetos normalmente utilizados para construir una aplicación Java. El ORM con JPA es totalmente guiado por metadatos definidos 8 7 mediante anotaciones embebidas en el código o externalizado en ficheros XML. Los POJOs denotan que los objetos persistentes son livianos en memoria [34] [37]. Lenguaje de consultas Orientado a Objetos. JPA ofrece un potente lenguaje de consultas Java Persistence Query Language, con la habilidad de consultar a través de las entidades y sus relaciones. JPQL es derivado EJB QL y modelado con mayor cercanía a SQL, pero sin comprometerse con el esquema del RDBMS subyacente. Las consultas en JPQL emplean de forma similar que EJB QL, una abstracción del esquema basada en el estado de la entidad como opuesto a las columnas en las cuales la entidad se almacena. La creación de consultas no requiere conocer la información del mapeo en la BD, y estas pueden ser definidas de forma estática mediante anotaciones de metadatos o creadas dinámicamente pasando el criterio de consulta en el instante de construirla [35] [37]. JPQL presenta soporte para las siguientes funcionalidades: • Uno o varios tipos de valores como resultado de ejecutar una consulta. • Empleo de funciones de agregación, con cláusulas para agrupar y ordenar. • Sintaxis más natural para las uniones, incluyendo soporte para inner join y outer join. • Consultas de actualización y eliminación en lote. • Empleo de consultas SQL específicas al RDBMS subyacente. JPA se encarga de hacer la transformación de las consultas en JPQL al lenguaje específico de consulta del RDBMS utilizado [35] [37]. Configuración simple con anotaciones. Todas las características de la persistencia pueden ser configuradas mediante el uso de anotaciones introducidas en la versión 5 de Java SE, ficheros XML, o la combinación de estos. Las anotaciones pueden ser usadas para definir entidades, llaves primarias, nombres de columnas en un RDBMS, relaciones e inyección del contexto de persistencia, entre otros elementos [35] [37]. Utilización fuera del contenedor EJB. JPA a diferencia de EJB, puede ser utilizado en aplicaciones Java SE que se ejecutan fuera del contenedor EJB. Esto posibilita que desarrolladores empleen las ventajas de este API sin estar obligados a utilizar un servidor de aplicaciones Java EE [37]. Valores por defecto. JPA a diferencia de EJB 2.x, no requiere un descriptor de despliegue XML específico del proveedor del servidor de aplicaciones, para definir el mapeo entre los entity beans y la BD asociada. JPA utiliza metadatos para especificar el mapeo de las entidades. En la mayoría de los casos no es preciso definir las anotaciones, debido al potente diseño que utiliza metadatos por defecto presente en la especificación de JPA. Los metadatos por defecto son aplicables a la mayoría de las anotaciones, utilizándose en la definición del mapeo, generación de valor de llave primaria, definición de relaciones, estrategia de herencia y carga de entidades, entre otros elementos. Esta característica de JPA hace el proceso de desarrollo más simple, puesto que solo se necesita adicionar anotaciones cuando el valor por defecto no es adecuado [35] [36] [37]. Herencia y Polimorfismo. Una importante capacidad de CCIA’2008 JPA es el soporte para la herencia que no era posible en EJB 2.x. De esta manera es posible mapear la herencia de entidades a su correspondiente representación en el Modelo Relacional teniendo en cuenta tres criterios fundamentales de mapeo: • Tabla única por jerarquía de clases (single table per class hierarchy). • Tabla por clase concreta (table per concrete class). • Tabla por subclase (table per subclass). Se pueden realizar además, consultas polimórficas sobre una jerarquía de clases [36] [37]. El paquete javax.persistence contiene las principales clases e interfaces de Java Persistence API [7] [35] [36] [37]: • Persistence: Clase que proporciona un método estático para crear instancias de EntityMangerFactory. • EntityMangerFactory: Interfaz que representa en tiempo de ejecución una unidad de persistencia específica. Usualmente se maneja a través del patrón de 8 diseño Singleton, y proporciona una factoría para la creación de instancias de EntityManager, las cuales son configuradas para conectarse a la misma BD. • EntityManager: Interfaz utilizada para acceder a una BD en una unidad de trabajo particular. Proporciona métodos para gestionar el ciclo de vida de las instancias de entidad y para crear objetos Query. • Query: Interfaz que representa una consulta particular en el lenguaje JPQL o una consulta SQL nativa. Permite pasar parámetros de forma segura a la consulta, así como paginar el resultado, entre otras funciones. • EntityTransaction: Interfaz utilizada para la definición de transacciones sobre recursos locales en entornos Java SE. Figura 3. Principales clases del API Java Persistence. Tomado de [34]. Los objetos EntityManager pueden ser de dos tipos [35] [36]: • Administrado por el contenedor (container-managed): El contenedor EJB administra el ciclo de vida del objeto y Java Transaction API (JTA) lleva el control de las transacciones. • Administrado por la aplicación (application-managed): El desarrollador es responsable de administrar el ciclo de vida del objeto y las transacciones asociadas, las cuales involucran recursos locales. Los principales artefactos disponibles en JPA son [35] [36] [37]: • Contexto de persistencia (Persistence context): Define un conjunto de instancias de entidad, donde cada identidad de entidad persistente es asociada con una única instancia. Las instancias de entidades y sus ciclos de vida son gestionados por un objeto EntityManager dentro del contexto de persistencia. • Unidad de persistencia (Persistence unit): Especifica el conjunto de tipos de entidad que pueden ser gestionados por el administrador de entidad (representado por un objeto EntityManager) dado. Define el conjunto de clases que están relacionadas o agrupadas por la aplicación, las cuales que deben ser mapeadas al RDBMS asociado. VII. CONCLUSIONES En este artículo se han presentado un conjunto de estándares y propuestas a tener en cuenta en el entorno Java, para resolver el problema que implica la persistencia de los objetos en el proceso de desarrollo de software. Se muestran las características y funcionalidades principales de estas, de forma tal que se tengan elementos suficientes para decidir cual emplear según las necesidades y peculiaridades de la aplicación. Si bien se exponen los estándares de más importantes y ampliamente difundidos, existen otros como CCIA’2008 Java Data Objects (JDO) y Java Architecture for XML Binding (JAXB). JDO es una especificación de Java liberada en el año 2002, utilizada principalmente como mecanismo ORM, aunque no está aferrada a los RDBMS pudiéndose emplear como estándar para mapear objetos hacia Sistemas Gestores de Bases de Datos Orientadas a Objetos (OODBMS, de su nombre en inglés Object-Oriented Database Management System). JAXB especifica un mecanismo para la creación de clases Java basado en esquemas XML, con el propósito de serializar y deserializar grafos de objetos [3] [12]. Se recomienda un estudio de JDO en el caso de mapeo de objetos a OODBMS, y de JAXP, para la persistencia basada en archivos XML. Se sugiere realizar un conjunto de pruebas de rendimiento en el proceso de desarrollo y ejecución de aplicaciones, con la utilización de los estándares abordados. Se exhorta a efectuar un estudio de las principales implementaciones a los estándares tratados, así como la aplicación del paradigma Arquitectura Guiada por Modelos (MDA, de su nombre en inglés Model Driven Architecture) en consonancia a JPA, con el objetivo de elevar la calidad y productividad en el desarrollo de software. REFERENCES 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. Cadenhead, R. and L. Lemay, Sams Teach Yourself Java™ 6 in 21 Days. 2007: Sams Publishing. Eckel, B., Thinking in Java, Third Edition. 2003: Prentice Hall / Pearson Education, Inc. Richardson, W.C., et al., Professional Java, JDK 6 Edition. 2007: Wiley Publishing, Inc. Sun Microsystems Inc., Java Object Serialization Specification. 2005. Grosso, W., Java RMI. 2001: O'Reilly. Forman, I. and N. Forman, Java Reflection In Action. 2005: Manning Publications Co. Bauer, C. and G. King, Java Persistence with Hibernate. 2007: Manning Publications Co. Parsian, M., JDBC Metadata, MySQL, and Oracle Recipes: A ProblemSolution Approach. 2006: Apress. Crawford, W., J. Farley, and D. Flanagan. An Introduction to JDBC, Part 1. 2002 [cited 2008 Septiembre]; Available from: http://www.onjava.com/pub/a/onjava/excerpt/javaentnut_2/index1.html. Sun Microsystems Inc. Java SE Technologies - Database. 2008 [cited 2008 Octubre]; Available from: http://java.sun.com/javase/technologies/database/. O'Donahue, J., Java Database Programming Bible. 2002: John Wiley & Sons. Thomas, T.M., Java Data Access JDBC, JNDI, and JAXP. 2002: M&T Books. Java Community Process. JSR 54: JDBCTM 3.0 Specification. [cited 2008 Octubre]; Available from: http://jcp.org/en/jsr/detail?id=54. Java Community Process. JSR 221: JDBCTM 4.0 API Specification. [cited 2008 Octubre]; Available from: http://jcp.org/en/jsr/detail?id=221. Allamaraju, S., et al., Programación Java Server con J2EE Edición 1.3. 2003: WROX. Sun Microsystems Inc. JDBC Overview. 2008 [cited 2008 Septiembre]; Available from: http://java.sun.com/products/jdbc/overview.html. Sun Microsystems Inc. JDBC. 2008 [cited 2008 Octubre]; Available from: http://java.sun.com/javase/6/docs/technotes/guides/jdbc/index.html. Sun Microsystems Inc. Java EE. 2007 [cited 2007 Febrero]; Available from: http://java.sun.com/javaee. 9 19. Java Community Process. JSR 151: JavaTM 2 Platform, Enterprise Edition 1.4 (J2EE 1.4) Specification. [cited 2008 Octubre]; Available from: http://jcp.org/en/jsr/detail?id=151. 20. Java Community Process. JSR 244: JavaTM Platform, Enterprise Edition 5 (Java EE 5) Specification. [cited 2008 Octubre]; Available from: http://jcp.org/en/jsr/detail?id=244. 21. Roman, E., R.P. Sriganesh, and G. Brose, Mastering Enterprise JavaBeansTM. Third ed. 2005: Wiley Publishing, Inc. 22. Armstrong, E., et al., The J2EE™ 1.4 Tutorial. 2004, Sun Microsystems, Inc. 23. Burke, B., S. Labourey, and R. Monson-Haefel, Enterprise JavaBeans. Fourth ed. 2004: O'Reilly. 24. Java Community Process. JSR 19: Enterprise JavaBeansTM 2.0. [cited 2008 Octubre]; Available from: http://jcp.org/en/jsr/detail?id=19. 25. Java Community Process. JSR 153: Enterprise JavaBeansTM 2.1. [cited 2008 Octubre]; Available from: http://jcp.org/en/jsr/detail?id=153. 26. Allamaraju, S., et al., Programación Java Server con J2EE Edición 1.3. 2001: WROX. 27. Matena, V., et al., Applying Enterprise JavaBeansTM:Component-Based Development for the J2EETM Platform. Second ed. 2003: Addison Wesley. 28. Johnson, R. and J. Hoeller, Expert One-on-OneTM J2EETM Development without EJBTM, ed. WROX. 2004: Wiley Publishing, Inc.,. 29. Johnson, R., Expert One-on-One J2EE Design and Development, ed. WROX. 2003: Wiley Publishing, Inc. 30. Pizarro, P., ORM, Object-Relational Mapping. Mapeo del modelo de objetos al modelo relacional. 2005. 31. Panda, D. Standardizing Java Persistence with the EJB3 Java Persistence API. 2006 [cited 2008 Octubre]; Available from: http://www.onjava.com/pub/a/onjava/2006/05/17/standardizing-withejb3-java-persistence-api.html. 32. Sun Microsystems Inc. Java Persistence API FAQ. 2008 [cited 2008 Octubre]; Available from: http://java.sun.com/javaee/overview/faq/persistence.jsp. 33. Java Community Process. JSR 220: Enterprise JavaBeansTM 3.0. [cited 2008 Octubre]; Available from: http://jcp.org/en/jsr/detail?id=220. 34. Richardson, C., POJOs in Action. Developing Enterprise Applications with Lightweight Frameworks. 2006: Manning Publications Co. 35. Panda, D., R. Rahman, and D. Lane, EJB 3 in Action. 2007: Manning Publications Co. 36. Burke, B. and R. Monson-Haefel, Enterprise JavaBeans, 3.0. 2006: O'Reilly. 37. Keith, M. and M. Schincariol, Pro EJB 3 Java Persistence API. 2006: Apress.