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.