Está en la página 1de 81

ACCESO A DATOS

Ciclo DAM

IRENE CALDELAS
2º CURSO
Camino de la Miranda
Tema 1. Introducción al acceso a
datos
1.Introducción 2.Acceso a datos
Iniciamos esta primera unidad del módulo Acceso a datos, en el
que veremos la gran variedad de métodos de acceso a datos que
tenemos en el panorama actual.

Los contenidos del módulo son eminentemente prácticos, y los


ejemplos estarán basados en Java. Utilizaremos como entorno de
programación NetBeans, por coherencia con otros módulos del
ciclo y por ser ambos gratuitos. Además, NetBeans es un entorno
muy potente y fácil de usar, si lo comparamos con otros entornos
de desarrollo.

Pero, ¿a qué nos referimos cuando hablamos de acceso a datos en Hay diversas estrategias de acceso a datos para gestionar la
una aplicación informática? persistencia de los datos:

Podemos afirmar que en la inmensa mayoría de aplicaciones  Mediante ficheros.


informáticas se pueden diferenciar, a grandes rasgos, en dos partes:  Bases de datos, que pueden ser:
o Relacionales,
 Por un lado, el programa propiamente dicho, que realiza
o Orientadas a objetos,
las operaciones deseadas con los datos necesarios.
o Objeto-relacionales.
 Por otro lado, los datos con los que opera le programa.
Esos datos pueden ser obtenidos por el programa  Mapeo objeto relacional (ORM).
mediante diversos métodos: leídos mediante teclado,  Bases de datos XML (eXtensible Markup Language).
escaneados, leídos de algún soporte de almacenamiento  Componentes.
secundario, etc.
Al principio, en los primeros tiempos de la informática, los datos se
En la mayoría de los casos, cuando programamos, nos interesa que guardaban en ficheros convencionales. Con el tiempo, y la
el programa guarde los datos que le hemos introducido, o los experiencia de trabajar con dichos ficheros, se observaron los
resultados que dicho programa haya obtenido, de manera que si el inconvenientes de los ficheros, y para intentar solucionar los
programa termina su ejecución, los datos no se pierdan y puedan inconvenientes que se observaron surgieron las bases de datos, que
ser recuperados posteriormente, es decir, persistan. Una forma entre otras ventajas permitían:
tradicional de hacer esto es mediante la utilización de ficheros o de
 Eliminar el problema de la información redundante.
bases de datos que se guardarán en un dispositivo de memoria no
 Eliminar información inconsistente.
volátil (normalmente un disco).
 Globalizar o centralizar la información.
Te habrás dado cuenta de que el almacenamiento en memoria  Garantizar el mantenimiento de la integridad en la
RAM, mediante variables o vectores, es temporal, los datos se información. Únicamente se almacena la información
pierden cuando el programa termina. Quizás te habrá pasado correcta. Independencia de datos. La
alguna vez que, debido a un apagón eléctrico, has perdido el  independencia de datos implica una separación entre
trabajo que estabas haciendo, que todavía no habías grabado. Los programas y datos, es decir, se pueden hacer cambios en
datos que se guardan en almacenamiento secundario, como la información que contiene la base de datos, o tener
ficheros o bases de datos, se denominan datos persistentes, porque acceso a la base de datos de diferente manera, sin tener
existen, o persisten más allá de la ejecución de la aplicación. que hacer cambios en las aplicaciones o en los
programas.
Ese almacenamiento secundario de datos que acabamos de
mencionar, habitualmente suele consistir en una base de datos
relacional, si bien, a veces, hay otros métodos de almacenamiento, 3. Qué estrategia o método de
y por tanto, métodos de acceso a esos datos

De conocer esos tipos de almacenamiento y cómo acceder a ellos


acceso usar
Posteriormente, con la aparición y expansión de la programación
es de lo que trata este módulo.
orientada a objetos, empezaron a surgir las bases de datos
En esta unidad inicial, vas a ver una panorámica de los diversos orientadas a objetos, y también se ampliaron algunas bases de datos
métodos de persistencia que encontramos en el mercado. relacionales, añadiéndoles extensiones de orientación a objetos.
Entonces ¿qué método de acceso a datos es mejor? ¿Cuál deberías De especial interés y uso cada vez más extendido, son los ficheros
utilizar en la próxima aplicación que construyas? XML. Éstos son archivos de texto que por consiguiente no
necesitan un software propietario para ser interpretados, como
Pues..., no hay una respuesta fácil para esas preguntas, no se puede ocurre con la mayoría de los archivos binarios, y tienen
afirmar que haya un método que sea el mejor de manera absoluta. normalmente la extensión xml.
Más bien, la cuestión es tener claro qué tipo de aplicación hay que
construir y, según eso, estudiar qué tipo de sistema de También debemos tener en cuenta, que las bases de datos
almacenamiento será mejor usar: si una base de datos orientada a relativamente modernas, como son las bases de datos XML,
objetos, o una base de datos XML, etc. guardan sus datos empleando ficheros xml.

Conociendo el funcionamiento de las diferentes alternativas Por eso, en muchas ocasiones se recurre a utilizar este tipo de
podemos comparar sus prestaciones al problema de la persistencia soluciones, el uso de ficheros en vez de bases de datos, y en
concreto que se nos presente. Cada una de las tecnologías tiene su particular de ficheros XML cuando se necesita intercambiar
propio origen y filosofía para alcanzar el mismo fin y, por esta información a través de varias plataformas de hardware o de
razón, no es fácil analizar sus ventajas y desventajas frente a las software, o de varias aplicaciones. A veces se exporta de una base
demás alternativas. de datos a ficheros XML para trasladar la información a otra base
de datos que leerá esos ficheros XML.
Por poner un ejemplo, lo más sencillo posible: si voy a crear una
base de datos para guardar mi colección de vídeos, probablemente Por esta razón se emplea XML en tecnologías de comunicación
no me va a interesar utilizar una base de datos Oracle, sino un como, por ejemplo, en WML (lenguaje de formato inalámbrico) y
producto mucho más barato, y sencillo de instalar y mantener. WAP (protocolo de aplicaciones inalámbricas).

La fácil estructuración de la información en los ficheros XML ha


4.Ficheros permitido que surjan muchas librerías de conversión de la
información almacenada a otros formatos como a PDF, texto, hojas
En las antiguas aplicaciones informáticas, antes de que surgieran
las bases de datos, la información se guardaba en ficheros. de cálculo, etc. Hay muchos productos propietarios y de código
abierto.
Así, por ejemplo, una aplicación que guardaba los datos de
personas almacenaba dichos datos en un fichero convencional cuyo
contenido bien podía ser este: 5.Bases de datos
Quizás hayas estudiado ya el módulo de bases de datos. Tanto si es
Antonio Pérez Pérez 30 C/ Morales nº 11 Madrid Madrid así como si no, recordamos aquí qué es un sistema de bases de
datos. Es:
Feliciano Gómez Sander 25 C/ Terreros nº 121 Vitoria Vitoria
 Un sistema de información orientado hacia los datos, que
Arturo Bueno Hernández 46 C/ Cocoliso nº 43 Murcia Murcia pretende recuperar y almacenar la información de manera
eficiente y cómoda.
...
 Surge en un intento de resolver las dificultades del
procesamiento tradicional de datos, teniendo en cuenta
Esto tenía como efecto, que el programador de las aplicaciones que
que los datos suelen ser independientes de las
usaran ese fichero tuviera que construir el programa conociendo
aplicaciones.
detalladamente las posiciones de los datos, para saber desde qué
posición hasta qué otra posición, se guardaba el nombre y
apellidos, etc. Además, tendría que controlar si se guardan filas de
datos duplicadas, y así un montón de inconvenientes. Por eso,
5.1. Introducción
cuando surgieron las bases de datos, se empezó a dejar de usar los
ficheros convencionales.

Pero bien es cierto, que aún en las más modernas aplicaciones, a


veces necesitamos un simple fichero para guardar información,
como por ejemplo un fichero de configuración, o un fichero log. Es
decir, no siempre nos hace falta una base de datos para almacenar
la información.

En Java, como en otros lenguajes de programación, hay diversas


clases para el manejo de ficheros, pues, como hemos dicho, a veces
son muy útiles. Para guardar poca información, es mejor usarlos Las ventajas que aportan los sistemas de bases de datos respecto a
que usar otro método. los sistemas de archivos convencionales son:

 Independencia de los datos respecto de los


4.1. Uso ficheros en la procedimientos. El usuario tiene una visión abstracta de
los datos, sin necesidad de ningún conocimiento sobre la
actualidad implementación de los ficheros de datos, índices, etc.
Hay que tener en cuenta, que los ficheros en sí, para grabar la Esto supone un gran ahorro en los costes de
información del modo que poníamos como ejemplo anteriormente, programación, de forma que la modificación de la
en el ejemplo de las personas, ya no se usan. Pero, sí que se usan estructura de los datos no suponga un cambio en los
ficheros que guardan datos siguiendo un patrón o estructura bien programas y viceversa. Sin ella, el mantenimiento de la
definida, en otros métodos de almacenamiento, como por ejemplo base de datos ocuparía el 50% de los recursos humanos
en ficheros y en bases de datos XML. dedicados al desarrollo de cualquier aplicación.
 Disminución de las redundancias y en consecuencia,
 Disminución de la posibilidad de que se produzca supondría migrar a sistemas que utilizaran otro modelo como el
inconsistencia de datos. relacional.
 Mayor integridad de los datos.
El modelo relacional fue el primer modelo de bases de datos
 Mayor disponibilidad de los datos.
definido de manera formal. Posteriormente, se formularon modelos
 Mayor seguridad de los datos.
informales para describir bases de datos jerárquicas (el modelo
 Mayor privacidad de los datos. jerárquico) y bases de datos en red (el modelo en red). Ambas, las
 Mayor eficiencia en la recogida, codificación y entrada bases de datos jerárquicas y en red existían antes que las bases de
en el sistema. datos relacionales, pero fueron descritas como modelo después
 Lo que se suele denominar interfaz con el pasado y de que el modelo relacional fuera definido.
futuro: una base de datos debe estar abierta a reconocer
información organizada físicamente por otro software.
 Compartición de los datos. Los datos deben poder ser 5.3. Bases de datos orientadas a
accedidos por varios usuarios simultáneamente, teniendo
previstos procedimientos para salvaguardar la integridad objetos (i)
de los mismos. El origen de las Bases de datos orientadas a objetos (en adelante:
BDOO) se debe básicamente a las siguientes razones:
Podemos afirmar generalizando, que se usa un sistema de ficheros
convencional cuando la cantidad de datos a guardar es tan  La existencia de problemas al representar cierta
reducida que no justifica las desventajas del uso de los sistemas de información y modelar ciertos aspectos del mundo real.
bases de datos. Por ejemplo, para guardar los datos del resultado de Los modelos clásicos permiten representar gran cantidad
la instalación de un programa, usamos un fichero de texto, no se de datos, pero las operaciones y representaciones que se
guardan los datos en una base de datos. pueden realizar sobre ellos son bastante simples.
 Pasar del modelo de objetos al modelo relacional, para
5.2. Bases de datos relacionales almacenar la información, genera dificultades que en el
caso de las BDOO no surgen, ya que el modelo es el
mismo. Es decir, los datos de los programas escritos en
lenguaje orientado a objetos se pueden almacenar
directamente, sin conversión alguna, en las BDOO.
Probablemente habrás cursado ya el módulo de bases de datos, si es
así, e incluso si no lo es, quizás sepas que el modelo de bases de Los sistemas de bases de datos orientadas a objetos soportan un
datos relacional fue propuesto en 1969 por Edgar Codd. modelo de objetos puro, ya que no están basados en extensiones
de otros modelos más clásicos como el relacional.
El propósito del modelo relacional es proporcionar un método
declarativo para especificar datos y consultas. Así, en el diseño de Por ello, una característica general es que el lenguaje de
la base de datos establecemos qué información contendrá dicha programación y el esquema de la base de datos utilizan las
base de datos, luego recuperaremos la información que queramos, mismas definiciones de tipos.
y dejamos al software del sistema gestor de la base de datos que se
ocupe de: describir las estructuras de datos para almacenarlos, y 5.3.1. Bases de datos orientadas a
gestionar los procedimientos de recuperación para obtener las
consultas deseadas. objetos (ii)
El acceso a los datos puede ser más rápido con las bases de datos
Las bases de datos relacionales son adecuadas para manejar orientadas a objetos que con las bases de datos tradicionales porque
grandes cantidades de datos, compartir datos entre programas, no hay necesidad de utilizar las uniones o joins, que sí se necesitan
realizar búsquedas rápidas, etc. Pero tienen como desventaja en los esquemas relacionales tabulares. Esto se debe a que un
fundamental que no presentan un buen modelo de las relaciones objeto puede recuperarse directamente sin una búsqueda,
entre los datos, ya que todo se representa como tablas simplemente siguiendo punteros.
bidimensionales, o sea, en filas y columnas.
Cada vez más, las necesidades de las aplicaciones actuales con
Podemos decir de las bases de datos relacionales que: respecto a las bases de datos son:
 Están muy extendidas.  Soporte para objetos complejos y datos multimedia.
 Son muy robustas.  Jerarquías de objetos o tipos y herencia.
 Permiten interoperabilidad entre aplicaciones.  Gestión de versiones.
 Permiten una forma de compartir datos entre  Modelos extensibles mediante tipos de datos definidos
aplicaciones. por el usuario.
 Son el común denominador de muchos sistemas y  Integración de los datos con sus procedimientos
tecnologías. Una base de datos puede ser utilizada en asociados.
programas realizados en Java, o en C++, etc.  Manipulación navegacional (en vez de declarativa) y de
conjunto de registros.
 Interconexión e interoperabilidad.
Otros modelos tradicionales
Como ejemplos de Sistemas Gestores de Bases de datos Orientados
Cuando se estudian las bases de datos relacionales, se suelen a Objetos podemos señalar:
mencionar también los modelos jerárquico y en red. Algunos
sistemas antiguos utilizan todavía estas arquitecturas, en centros de  Jasmine
datos donde se manejan grandes volúmenes de información y la  ObjectStore
complejidad de los sistemas hace prohibitivo el coste que  GemStone
datos como el procesamiento de transacciones en línea
5.4. Comparativa entre bases (OLTP).
 Reglas de acceso. En las bases de datos relacionales, a
de datos relaciones y los atributos se accede y se modifican a través de
operadores relacionales predefinidos. En las orientadas a
orientadas a objetos objetos se procede mediante las interfaces que se creen a
En numerosos bancos de pruebas realizados para comparar los tal efecto de las clases. Desde este punto de vista, los
sistemas de bases de datos orientados a objetos (ODBMS) y los sistemas orientados a objetos dan independencia a cada
sistemas de bases de datos relacionales (RDBMS), se ha mostrado objeto que el sistema relacional no permite.
que los ODBMS pueden ser superiores para ciertos tipos de tareas.  Clave. En el modelo relacional, las claves primarias
generalmente tienen una forma representable en texto, sin
La explicación a esto es que muchas operaciones se realizan embargo, los objetos no necesitan una representación
utilizando interfaces navegacionales más que declarativos, y el visible del identificador.
acceso a datos navegacional es normalmente implementado muy
eficientemente.
5.4.1. Desventajas de las bases de
Un buen argumento a favor de las bases de datos orientadas a
objetos es la transparencia (no ensucia la construcción de una datos orientadas a objetos
aplicación). El desarrollador así se debe preocupar de los objetos
de su aplicación, en lugar de cómo los debe almacenar y recuperar frente a las relaciones
de un medio físico. Como desventajas o puntos débiles de las BBDDOO respecto a las
relacionales podemos mencionar:
Podemos decir que las ventajas de un SGBDOO frente a las
relacionales son:  La reticencia del mercado, tanto para desarrolladores
como usuarios, a este tipo de bases de datos.
 Permiten mayor capacidad de modelado. El modelado  Carencia de un modelo de datos universal. No hay
de datos orientado a objetos permite modelar el mundo ningún modelo de datos que esté universalmente
real de una manera mucho más fiel. Esto se debe a: aceptado para los SGBDOO y la mayoría de los modelos
o un objeto permite encapsular tanto un estado carecen de una base teórica. El modelo de objetos aún no
como un comportamiento tiene una teoría matemática coherente que le sirva de
o un objeto puede almacenar todas las relaciones base.
que tenga con otros objetos  Carencia de experiencia. Al ser una tecnología
o los objetos pueden agruparse para formar relativamente nueva, todavía no se dispone del nivel de
objetos complejos (herencia). experiencia del que se dispone para los sistemas
 Extensibilidad, debido a que: relacionales.
o Se pueden construir nuevos tipos de datos a  Panorama actual. Tanto los sistemas gestores de bases de
partir de los ya existentes. datos como los sistemas gestores de bases de datos
o Podemos agrupar propiedades comunes de objeto-relacionales están muy extendidos. SQL es un
diversas clases e incluirlas en una superclase, estándar aprobado y ODBC y JDBC son estándares de
lo que reduce la redundancia. facto. Además, el modelo relacional tiene una sólida base
o Tenemos reusabilidad de clases, lo que teórica y los productos relacionales disponen de muchas
repercute en una mayor facilidad de herramientas de soporte que sirven tanto para
mantenimiento y un menor tiempo de desarrolladores como para usuarios finales.
desarrollo.  Dificultades en optimización. La optimización de
 Disposición de un lenguaje de consulta más expresivo. consultas necesita realizar una compresión de la
El acceso navegacional desde un objeto al siguiente es la implementación de los objetos, para poder acceder a la
forma más común de acceso a datos en un sistema gestor base de datos de manera eficiente. Sin embargo, esto
orientado a objetos. Mientras que SQL utiliza el acceso compromete el concepto de encapsulación.
declarativo. El acceso navegacional es más adecuado
para gestionar operaciones tales como consultas
recursivas, etc.
5.5. Bases de datos objeto-
 Adaptación a aplicaciones avanzadas de base de datos.
Hay muchas áreas en las que las bases de datos
relacionales
Entendemos Base de Datos Objeto Relacional (BDOR), una base
relacionales no han tenido excesivo éxito, como es el
de datos que ha evolucionado desde el modelo relacional a otro
caso de en sistemas de diseño CAD, CASE, sistemas
extendido que incorpora conceptos del paradigma orientado a
multimedia, etc. en los que las capacidades de modelado
objetos. Por tanto, un Sistema de Gestión ObjetoRelacional
de los SGBDOO han hecho que esos sistemas sí resulten
(SGBDOR) contiene ambas tecnologías: relacional y de objetos.
efectivos para este tipo de aplicaciones.
 Prestaciones. Los sistemas gestores de bases de datos En una Base de Datos Objeto Relacional el diseñador puede crear
orientadas a objetos proporcionan mejoras significativas sus propios tipos de datos y crear métodos para esos tipos de datos.
de rendimiento con respecto a los SGBD relacionales.
Aunque hay autores, que han argumentado que los Por ejemplo, podríamos definir un tipo de la siguiente manera:
bancos de prueba, usados en dichas pruebas, están
dirigidos a aplicaciones de ingeniería donde los CREATE TYPE persona_t AS OBJECT (
SGBDOO son más adecuados. También está demostrado, nif VARCHAR2(9),
que los SGBDR tienen un rendimiento mejor que los nombre VARCHAR2(30),
SGBDOO en las aplicaciones tradicionales de bases de direccion VARCHAR2(40),
telefono VARCHAR2(15),
fecha_nac DATE); Para gestionar la información de las bases de datos hay unos
estándares que facilitan a los programas informáticos manipular la
Por poner un ejemplo, si consideramos la base de datos Oracle, información almacenada en ellas.
debido a los requerimientos de las nuevas aplicaciones, el sistema
En Java existe un API basado en estos estándares que permite al
de gestión de bases de datos relacional desde versión 8i fue
desarrollar aplicaciones, que se pueda acceder a bases de datos
extendido con conceptos del modelo de bases de datos orientadas a
relacionales: JDBC (Java Database Connectivity, conectividad de
objetos. De esta manera, aunque las estructuras de datos que se
bases de datos de Java).
utilizan para almacenar la información siguen siendo tablas, los
diseñadores pueden utilizar muchos de los mecanismos de La mayoría de las aplicaciones importantes de una empresa están
orientación a objetos para definir y acceder a los datos. Se reconoce respaldadas por una arquitectura normalizada y optimizada de
el concepto de objetos, de tal manera que un objeto tiene un tipo, se bases de datos relacionales. Tradicionalmente, dichas aplicaciones
almacena en cierta fila de cierta tabla y tiene un identificador único están basadas en sentencias SQL con las cuales se gestionan todos
(OID). Estos identificadores se pueden utilizar para referenciar a los datos que manejan.
otros objetos y así representar relaciones de asociación y de
agregación. Este modelo continúa teniendo una gran importancia estratégica y
es la base para el continuo crecimiento del mapeo Objeto-
La ventaja de este tipo de base de datos es que los usuarios pueden Relacional (O/R) y está asociado a los mecanismos de persistencia.
pasar sus aplicaciones actuales sobre bases de datos relaciones este
nuevo modelo sin tener que reescribirlas. Más tarde, se pueden ir Un driver JDBC es un componente software que posibilita a una
adaptando las aplicaciones y bases de datos para que utilicen las aplicación Java interaccionar con una base de datos.
funciones orientadas a objetos.
El API JDBC define interfaces y clases para escribir aplicaciones
Con las Bases de Datos Objeto-Relacional se amplía el modelo de bases de datos en Java realizando conexiones de base de datos.
relacional destacando las siguientes aportaciones:
Mediante JDBC el programador puede enviar sentencias SQL, y
 Se aumentan la variedad en los tipos de datos, PL/SQL a una base de datos relacional. JDBC permite embeber
o se pueden crear nuevos tipos de datos que SQL dentro de código Java.
permitan construir aplicaciones complejas con
La ilustración muestra una representación de los diferentes
una gran riqueza de dominios. Se soportan
mecanismos de mapeo O/R y cómo se relacionan con el código de
tipos complejos como: registros, conjuntos,
la aplicación y con los recursos de datos relacionados. Se observa
referencias, listas, pilas, colas y vectores.
claramente la función crítica que desempeña el driver JDBC puesto
 Hay extensiones en el control de la Semántica de datos que está situado en la base de cada uno de los marcos de trabajo.
Objeto-Relacionales:
o Se pueden crear procedimientos almacenados y La ventaja de usar conectores JDBC es que independiza de la base
funciones que tengan un código en algún de datos que utilice.
lenguaje de programación, como por ejemplo:
SQL, Java, C, etc. No obstante hay un trabajo de traducción para mapear los campos
 Se pueden compartir varias librerías de clases ya devueltos por cada consulta a la colección de objetos
existentes, esto es lo que conocemos como reusabilidad. correspondiente. Y hay que trabajar las sentencias de actualización,
inserción y eliminación para cada uno de los campos. Esto
Como productos comerciales de bases de Datos Objeto-Relacional constituye una razón para tratar de buscar alternativas menos
podemos destacar: costosas en tiempo de desarrollo.


7.Mapeo objeto relacional
DB2 Universal Database de IBM (International Business
Machines).
 Universal Server de Informix (ahora de IBM),


INGRES II, de Computer Associates.
ORACLE de Oracle Corporation,
(ORM)
 SyBASE

Como productos de código abierto, destacamos PostGreSQL.

6.Acceso a bases de datos


mediante conectores. En los inicios de la programación, los programas se desarrollaban
con la llamada programación imperativa. De hecho, y como sabes,
la programación orientada a objetos surgió unos años después.

Con la expansión de la programación orientada a objetos, se da la


circunstancia de que las bases de datos relacionales se siguen
utilizando hoy en día de manera masiva, por lo que muchas
aplicaciones se desarrollan con POO pero los datos, no se
almacenan en bases de datos orientadas a objetos, sino en las bases
de datos relacionales.

El sistema más extendido en las empresas hoy en día para guardar


la información de sus aplicaciones es el uso de una base de datos
relacional. Tradicionalmente, dichas aplicaciones están basadas en
sentencias SQL con las cuales se gestionan todos los datos que
manejan. Este sistema es la base para el continuo crecimiento del recupera registros como si el programa estuviera dirigiéndose a ella
mapeo Objeto-Relacional (O/R) y está asociado a los mecanismos de forma relacional.
de persistencia.
Dispones de múltiples alternativas como desarrollador en Java
Cuando se programan sistemas orientados a objetos, utilizando una cuando pretendas trabajar con mapeadores O/R. Hay tres
base de datos relacional, los programadores invierten gran cantidad comunidades que están implicadas en el mundo de la persistencia
de tiempo en desarrollar los objetos persistentes, o sea, convertir O/R de Java de forma activa:
los objetos del lenguaje de programación a registros de la base de
datos. Igualmente, también pasan bastante tiempo implementando  Organizaciones basadas en el estándar,
la operación inversa, es decir, convirtiendo los registros en objetos.  Comunidades código abierto (open source) y
 Grupos comerciales.
El mapeo objeto-relacional (Object-Relational Mapping, o ORM)
consisten en una técnica de programación para convertir datos Las comunidades open source incluyen importantes tecnologías,
entre el sistema de tipos utilizado en un lenguaje de programación entre ellas Hibernate y el Spring framework.
orientado a objetos y el sistema utilizado en una base de datos
relacional. Hibernate es una herramienta de Mapeo objeto-relacional (ORM)
para la plataforma Java (y disponible también para .Net con el
Cuando se trabaja con programación orientada a objetos y con nombre de NHibernate) que facilita el mapeo de atributos entre una
bases de datos relacionales, es fácil observar que estos son dos base de datos relacional tradicional y el modelo de objetos de una
paradigmas diferentes. El modelo relacional trata con relaciones y aplicación, mediante archivos declarativos (XML) o anotaciones en
conjuntos, es de naturaleza matemática. Por el contrario, el los beans de las entidades que permiten establecer estas relaciones.
paradigma orientado a objetos trata con objetos, atributos y
asociaciones de unos con otros. Spring es un framework para el desarrollo de aplicaciones y
contenedor de inversión de control, de código abierto para la
Cuando se requiere almacenar la información de los objetos plataforma Java.
utilizando una base de datos relacional se comprueba que hay un
problema de compatibilidad entre estos dos paradigmas, el llamado Las alternativas más importantes basadas en el estándar, son EJB
desfase objeto-relacional. 3.2 y JDO 3.1.

Por ello, para ahorrar trabajo al programador, se puede utilizar un Entre las implementaciones comerciales se puede resaltar TopLink
framework que se encargue de realizar estas tareas de modo que es un paquete de Mapeo objeto-relacional (ORM) para
transparente, de modo que el programador no tenga por qué usar desarrolladores Java. Provee un marco de trabajo para almacenar
JDBC ni SQL y la gestión del acceso a base de datos esté objetos Java en una base de datos relacional, o convertir objetos
centralizada en un componente único permitiendo su reutilización. Java a archivos XML.

Cada uno de los mecanismos de mapeo O/R tiene una


7.1. Capa de persistencia y dependencia particular en el conector JDBC para poder
comunicarse con la base de datos de una forma eficiente. Si el
framework de mapeo conector JDBC que participa en la comunicación no es óptimo, la
posible gran eficiencia de cualquier framework quedará debilitada.
Por tanto, seleccionar el driver JDBC que mejor se adapte a la
aplicación es esencial a la hora de construir un sistema eficiente en
el que intervenga un mecanismo de mapeo O/R.

*Insertar imagen

8.Bases de datos XML


Se define XML como: eXtensible Markup Language (lenguaje de
marcado extensible).

Es una especificación del World Wide Web Consortium (W3C).


La capa de persistencia de una aplicación es la pieza que permite
Debido a las limitaciones de la tecnología de bases de datos
almacenar, recuperar, actualizar y eliminar el estado de los objetos
relacionales están surgiendo nuevas clases de bases de datos como
que necesitan persistir en un sistema gestor de datos.
son las bases de datos XML.
En el caso del mapeo objeto-relacional, un ORM es una capa que
Estas bases de datos almacenan los datos estructurados como XML
permite relacionar objetos con un modelo de datos relacional,
sin la necesidad de traducir los datos a una estructura relacional o
ocultando todo el mecanismo de conexión al motor de base de
de objeto.
datos, y también no teniendo que escribir las sentencias SQL
necesarias para la gestión de los datos.

La capa de persistencia traduce entre los dos modelos de datos:


desde objetos a registros y desde registros a objetos. Así, si el
programa quiere grabar un objeto, entonces llama al motor de
persistencia, el motor de persistencia traduce el objeto a registros
y llama a la base de datos para que guarde estos registros.

De este modo el programa sólo ve que puede guardar y recuperar


objetos, como si estuviera programado para una base de datos
Podemos distinguir entre:
orientada a objetos. Y la base de datos sólo ve que guarda y
 Bases de datos nativas XML: consiste en un modelo Por tanto, así el software se hace cada vez más rápido, de mejor
lógico para documentos XML. El Sistema Gestor de calidad y a menor coste incluso de mantenimiento.
Base de Datos correspondiente almacena y recupera
documentos de acuerdo a dicho modelo. Un componente software también debe especificar sus necesidades
o Productos ejemplo de esa filosofía son: eXist, para funcionar correctamente, lo que se denominan las
dependencias de contexto:
Apache Xindice, Berkeley dbXML....
 Bases de datos compatibles con XML (XML-  Interfaces requeridas.
enabled): son bases de datos, generalmente objeto-  Entorno de ejecución: máquina necesaria, sistema
relacionales, que admiten entradas de datos en forma de operativo a utilizar, etc.
XML y proporcionan salidas en este mismo formato.
o Podemos citar productos como: Oracle, DB2 En el entorno Java, contamos con los JavaBeans.
(Viper),...
Los JavaBeans son un modelo de componentes creado por Sun
Las bases de datos XML nativas permiten trabajar con XQL Microsystems para la construcción de aplicaciones en Java.
(eXtensible Query Language), el cuál sirve un propósito similar a
SQL en una base de datos relacional.

El trabajo con bases de datos XML nativas involucra dos pasos


básicos: 9.2. JavaBeans
El origen de los JavaBeans lo podemos encontrar en un par de
 Describir los datos mediante Definiciones de Tipos de necesidades que Java tenía:
Datos (Document Type Definitions, DTD) o esquemas
XML y  Disponer de una tecnología de objetos y componentes
 Definir un nuevo esquema de base de datos XML nativa reutilizables.
o Mapa de Datos a usar para almacenar y obtener datos.  Mejorar el proceso para crear interfaces de usuario,
acercándose a la facilidad de uso que otros productos

9.Desarrollo de
permitían como Visual Basic de Microsoft.

Un JavaBean es un componente software reutilizable basado en la


componentes especificación JavaBean de Sun (ahora Oracle) que se puede
manipular visualmente con una herramienta de desarrollo.
La expansión, en los últimos años, de Internet y el comercio
electrónico ha llevado a la necesidad de adoptar nuevas tecnologías Hay una serie de propiedades que presenta un JavaBean:
y nuevos requisitos de desarrollo en las aplicaciones informáticas.
 Portabilidad: uno de los principales objetivos de los
Al principio de la informática, los ordenadores eran caros y la JavaBeans es proporcionar una arquitectura neutral de
mano de obra de los programadores asequible. Con el paso del componentes, es decir, que los beans puedan utilizarse en
tiempo los ordenadores son baratos y la mano de obra de los otras plataformas y entornos.
programadores suele ser cara. Además, los requisitos de las  Reusabilidad: son componentes reutilizables, la filosofía
aplicaciones informáticas son cada vez más complejos. Por ello, es que estos componentes puedan usarse como bloques
aparecieron las técnicas orientadas a objetos, para, entre otras en la construcción de aplicaciones complejas.
cosas, intentar programar de manera que el código que se  Introspección: los IDE reconocen ciertas pautas de
desarrolle pueda ser reutilizable. diseño, nombres de las funciones miembros o métodos y
definiciones de las clases, permitiendo a la herramienta
9.1. Definición de componente de programación mirar dentro del bean y conocer sus
propiedades y comportamiento.
Un componente es una unidad de software que realiza una función
 Personalización: en tiempo de diseño, con el IDE que se
bien definida y posee una interfaz bien definida.
utilice, se pueden modificar las características de
Un componente software posee interfaces especificadas apariencia y comportamiento de un bean.
contractualmente, pudiendo ser desplegado independientemente y  Persistencia: un bean puede guardar su estado y
puede interaccionar con otros componentes para formar un sistema. recuperarlo posteriormente. Esta capacidad se logra
mediante la serialización. Cuando un ejemplar de bean se
Un interfaz es un punto de acceso a los componentes: permite a los serializa se convierte en un flujo de datos que se
clientes acceder a los servicios proporcionados por un componente. almacenará en algún sitio, probablemente en un fichero.
Cualquier applet, aplicación o herramienta que utilice el
La idea de dividir u organizar en trozos el software, o sea, dividirlo bean puede restaurarlo mediante la deserialización.
en componentes surge para reducir la complejidad del software.
 Comunicación entre eventos: Los eventos constituyen
Así se permite la reutilización y se acelera el proceso de
un mecanismo de notificación entre objeto fuente y
ensamblaje del software.
objeto(s) receptor(es). Las herramientas de desarrollo
Los creadores de componentes pueden especializarse creando pueden examinar un bean para determinar qué eventos
objetos cada vez mas complejos y de mayor calidad. puede enviar y cuáles puede recibir.

La interoperabilidad entre componentes de distintos fabricantes:

 Aumenta la competencia.
 Reduce los costes.
 Facilita la construcción de estándares.
Tema 2. Manejo de ficheros
o Muchos métodos no lanzaban excepciones por
1.Introducción lo que era muy complicado detectar y resolver
errores
Si estás estudiando este módulo, es probable que ya hayas o No permitía manejar enlaces simbólicos
estudiado el de programación, por lo que no te serán desconocidos o Presenta problemas de escalabilidad.
muchos conceptos que se tratan en este tema. Directorios largos provocaban problemas de
memoria e incluso de denegación de servicio
Ya sabes que cuando apagas el ordenador, los datos de la memoria
 El paquete java.nio.file incorporado a partir de JSE7
RAM se pierden. Un ordenador utiliza ficheros para guardar los
resuelve estos problemas. 
datos. Piensa que los datos de las canciones que oyes en mp3, las
películas que ves en formato avi, o mp4, etc., están, al fin y al cabo,  Es el que debemos usar para trabajar con archivos
almacenadas en ficheros, los cuales están grabados en un soporte independientemente de si realizamos I/O con streams
como son los discos duros, DVD, pendrives, etc. (java.io) ó con buffers y channels (java.nio)

Se llama a los datos que se guardan en ficheros datos persistentes,


porque persisten más allá de la ejecución de la aplicación que los
trata. Los ordenadores almacenan los ficheros en unidades de 2.Clases asociadas a las
almacenamiento secundario como discos duros, discos ópticos, etc.
En esta unidad veremos, entre otras cosas, cómo hacer con Java las
operaciones de crear, actualizar y procesar ficheros.
operaciones de gestión
A las operaciones, que constituyen un flujo de información del de ficheros y directorios
programa con el exterior, se les conoce como Entrada/Salida (E/S).
En efecto, tal y como dicen Ana y Antonio, hay bastantes métodos
Las operaciones de E/S en Java las proporciona el paquete estándar involucrados en las clases que en Java nos permiten manipular
de la API de Java denominado java.io que incorpora interfaces, ficheros y carpetas o directorios.
clases y excepciones para acceder a todo tipo de ficheros.
Vamos a ver la clase File que nos permite hacer unas cuantas
La librería java.io contiene las clases necesarias para gestionar las operaciones con ficheros, también veremos cómo filtrar ficheros, o
operaciones de entrada y salida con Java. Estas clases de E/S las sea, obtener aquellos con una característica determinada, como
podemos agrupar fundamentalmente en: puede ser que tengan la extensión .odt, o la que nos interese, y por
último, en este apartado también veremos como crear y eliminar
 Clases para leer entradas desde un flujo de datos.
ficheros y directorios.
 Clases para escribir entradas a un flujo de datos.
 Clases para operar con ficheros en el sistema de ficheros
local.
 Clases para gestionar la serialización de objetos.
2.1. Clase File
java.nio (Non- Blocking I/O) fue introducido en el API de Java
desde la versión 1.4 como extensión eficiente a los La clase File proporciona una representación abstracta de ficheros
paquetes java.io y java.net. Java NIO ofrece una forma diferente de y directorios.
trabajar con IO que las API de IO estándar. Se basa en el “Buffer”
y el “Channel”. Esta clase, permite examinar y manipular archivos y directorios,
independientemente de la plataforma en la que se esté trabajando:
java.io vs java.nio Linux, Windows, etc.

 Depende de lo que necesitemos pueden ser Las instancias de la clase File representan nombres de archivo, no
complementarios y utilizaremos conjuntamente ambos los archivos en sí mismos.
paquetes.
El archivo correspondiente a un nombre puede ser que no exista,
 java.nio permite manejar múltiples canales (archivos o
por esta razón habrá que controlar las posibles excepciones.
conexiones de red) con uno o unos pocos hilos. 
 En java.nio el procesamiento de datos es más complicado Un objeto de clase File permite examinar el nombre del archivo,
que usar los streams bloqueantes de java.io descomponerlo en su rama de directorios o crear el archivo si no
 java.nio es la opción si necesito manejar cientos de existe, pasando el objeto de tipo File a un constructor adecuado
conexiones (canales) abiertas y en cada una manejar una como FileWriter(File f), que recibe como parámetro un objeto File.
pequeña cantidad de datos. 
Para archivos que existen, a través del objeto File, un programa
 java.io es la opción si voy a manejar pocas conexiones puede examinar los atributos del archivo, cambiar su nombre,
con un alto ancho de banda (envío mucha información a borrarlo o cambiar sus permisos. Dado un objeto File, podemos
la vez) hacer las siguientes operaciones con él:
 Hasta JSE7 java.io.File era la clase utilizada para realizar
operaciones I/O con archivos  Renombrar el archivo, con el método renameTo(). El
  Esta clase tenía limitaciones como: objeto File dejará de referirse al archivo renombrado, ya
que el String con el nombre del archivo en el objeto File no  File f = new File("ficheros/personas.dat");
cambia. Crea un Objeto File asociado al fichero personas.dat que
 Borrar el archivo, con el método delete(). También, con se encuentra en el directorio ficheros dentro del
deleteOnExit() se borra cuando finaliza la ejecución de la directorio actual.  En este caso se indica la ruta relativa
máquina virtual Java. tomando como base el directorio actual de trabajo. Se
 Crear un nuevo fichero con un nombre único. El método supone que el fichero personas.dat se encuentra en el
estático createTempFile() crea un fichero temporal y directorio ficheros. A su vez el directorio ficheros se
devuelve un objeto File que apunta a él. Es útil para crear encuentra dentro del directorio actual de trabajo.
archivos temporales, que luego se borran, asegurándonos  File f = new File("c:/ficheros/personas.dat"); 
tener un nombre de archivo no repetido. Crea un Objeto File asociado al fichero personas.dat
 Establecer la fecha y la hora de modificación del archivo dando la ruta absoluta:
con setLastModified(). Por ejemplo, se podría hacer: new
File("prueba.txt").setLastModified(new Date().getTime()); para Ejemplos utilizando el segundo constructor:
establecerle la fecha actual al fichero que se le pasa como
parámetro, en este caso prueba.txt. En este caso se crea un objeto File cuya ruta (absoluta o relativa) se
 Crear un directorio, mediante el método mkdir(). También indica en el primer String.
existe mkdirs(), que crea los directorios superiores si no
existen.  File f = new File("ficheros", "personas.dat" ); 
 Listar el contenido de un directorio. Los métodos list() y Crea un Objeto File asociado al fichero personas.dat que
listFiles() listan el contenido de un directorio. list() devuelve
se encuentra en el directorio ficheros dentro del
un vector de String con los nombres de los archivos, directorio actual. En este caso se indica la ruta relativa
listFiles() devuelve un vector de objetos File.
tomando como base el directorio actual de trabajo.
 Listar los nombres de archivo de la raíz del sistema de Ejemplos utilizando el tercer constructor:
archivos, mediante el método estático listRoots().
Este constructor permite crear un objeto File cuya ruta se indica a
La clase proporciona los siguientes constructores para crear través de otro objeto File.
objetos File:
 File ruta = new File("ficheros");
 public File(String nombreFichero|path); File f = new File(ruta, "personas.dat" );
 public File(String path, String nombreFichero|path); Crea un Objeto File asociado al fichero personas.dat que
 public File(File path, String nombreFichero|path); se encuentra en el directorio ficheros dentro del
directorio actual.
La ruta o path puede ser absoluta o relativa.
Debemos tener en cuenta que crear un objeto File no significa que
Ejemplos utilizando el primer constructor: deba existir el fichero o el directorio o que el path sea correcto.

 File f = new File("personas.dat"); Si no existen no se lanzará ningún tipo de excepción ni tampoco


Crea un Objeto File asociado al fichero personas.dat que serán creados.
se encuentra en el directorio de trabajo. En este caso no
Métodos
se indica path. Se supone que el fichero se encuentra en el
directorio actual de trabajo. Alguno de los métodos de la clase File son los siguientes:

Método Descripción
boolean canRead() Devuelve true si se puede leer el fichero
boolean canWrite() Devuelve true si se puede escribir en el fichero
boolean createNewFile() Crea el fichero asociado al objeto File. Devuelve true si se ha podido crear. Para poder crearlo el fichero no debe existir.
Lanza una excepción del tipo IOException.
boolean delete() Elimina el fichero o directorio. Si es un directorio debe estar vacío. Devuelve true si se ha podido eliminar.
boolean exists() Devuelve true si el fichero o directorio existe
String getName() Devuelve el nombre del fichero o directorio
String getAbsolutePath() Devuelve la ruta absoluta asociada al objeto File.
String getCanonicalPath() Devuelve la ruta única absoluta asociada al objeto File. Puede haber varias rutas absolutas asociadas a un File pero solo
una única ruta canónica. Lanza una excepción del tipo IOException.
String getPath() Devuelve la ruta con la que se creó el objeto File. Puede ser relativa o no.
String getParent() Devuelve un String conteniendo el directorio padre del File. Devuelve null si no tiene directorio padre.

File getParentFile() Devuelve un objeto File conteniendo el directorio padre del File. Devuelve null si no tiene directorio padre.

boolean isAbsolute() Devuelve true si es una ruta absoluta


boolean isDirectory() Devuelve true si es un directorio válido
boolean isFile() Devuelve true si es un fichero válido
long lastModified() Devuelve un valor en milisegundos que representa la última vez que se ha modificado (medido desde las 00:00:00 GMT,
del 1 de Enero de 1970). Devuelve 0 si el fichero no existe o ha ocurrido un error.
long length() Devuelve el tamaño en bytes del fichero. Devuelve 0 si no existe. Devuelve un valor indeterminado si es un directorio.
String[] list() Devuelve un array de String con el nombre de los archivos y directorios que contiene el directorio indicado en el objeto
File. Si no es un directorio devuelve null. Si el directorio está vacío devuelve un array vacío.
String[] list(FilenameFilter Similar al anterior. Devuelve un array de String con el nombre de los archivos y directorios que contiene el directorio
filtro) indicado en el objeto File que cumplen con el filtro indicado.
boolean mkdir() Crea el directorio. Devuelve true si se ha podido crear.
boolean mkdirs() Crea el directorio incluyendo los directorios no existentes especificados en la ruta padre del directorio a crear. Devuelve
true si se ha creado el directorio y los directorios no existentes de la ruta padre.
boolean renameTo(File Cambia el nombre del fichero por el indicado en el parámetro dest. Devuelve true si se ha realizado el cambio.
dest)

String directorio = "C:\\prueba";


String varios = "carpeta1/carpeta2/carpeta3";
1.1.1. Existencia y listado de // Crear un directorio
boolean exito = (new File(directorio)).mkdir();
ficheros y carpetas if (exito)
Mediante la clase File, podemos ver si un fichero cualquiera, System.out.println("Directorio: " + directorio + " creado");
digamos por ejemplo texto.txt, existe o no. Para ello, nos valemos
// Crear varios directorios
del método exists() de la clase File. Hacemos referencia a ese fichero
en concreto con el código siguiente: exito = (new File(varios)).mkdirs();
if (exito)
File f = new File("C:\texto.txt"); System.out.println("Directorios: " + varios + " creados");
}catch (Exception e){
File.
como verás, permite listar el contenido de la carpeta que
System.err.println("Error: " + e.getMessage());
pongas en un campo de texto, introduciendo el resultado en un
JList. }

Pero ¿qué pasa si nos interesa copiar un fichero, ¿cómo lo


haríamos? Para borrar un directorio con Java, tendremos que borrar cada
uno de los ficheros y directorios que este contenga. Al poder
Con la clase File no es suficiente, necesitamos saber más, en almacenar otros directorios, se podría recorrer recursivamente el
concreto, necesitamos hablar de los flujos, como vamos a ver más directorio para ir borrando todos los ficheros.
adelante.
Podemos listar el contenido de un directorio e ir borrando con:

File [] ficheros = directorio.listFiles ();


1.1.2. Creación y eliminación Si el elemento es un directorio, lo sabemos mediante el
de ficheros y directorios método isDirectory ().

Cuando queramos crear un fichero, podemos proceder del Después de vaciar el directorio, este, se puede borrar importando la
siguiente modo: librería FileUtils y después
escribir FileUtils.deleteDirectory(newFile(destination));
try {
// Creamos el objeto que encapsula el fichero
File fichero = new File("c:\\prueba\\miFichero.txt");
1.2. Interface FilenameFilter
Hemos visto cómo obtener la lista de ficheros de una carpeta o
// A partir del objeto File creamos el fichero físicamenteif
directorio. A veces, nos interesa ver no la lista completa, sino los
(fichero.createNewFile())
archivos que encajan con un determinado criterio.
System.out.println("El fichero se ha creado correctamente");
else Por ejemplo, nos puede interesar un filtro para ver los ficheros
System.out.println("No ha podido ser creado el fichero"); modificados después de una fecha, o los que tienen un tamaño
} catch (Exception ioe) { mayor del que el que indiquemos, etc.
ioe.getMessage(); El interface FilenameFilter se puede usar para crear filtros que
} establezcan criterios de filtrado relativos al nombre de los ficheros.
Una clase que lo implemente debe definir e implementar el
Para borrar un fichero podemos usar la clase File, comprobando método:
previamente si existe el fichero, del siguiente modo:
boolean accept(File dir, String nombre)
// Borrar fichero
File fichero = new File("c:\\prueba\\miFichero.txt"); Este método devolverá verdadero en el caso de que el fichero cuyo
nombre se indica en el parámetro nombre aparezca en la lista de los
if (fichero.exists ())
ficheros del directorio indicado por el parámetro dir..
fichero.delete();
En el siguiente ejemplo vemos cómo se listan los ficheros de la
carpeta c:\datos que tengan la extensión .txt. Usamos try y catch para
Para crear un directorio, lo realizaremos del siguiente modo: capturar las posibles excepciones, como que no exista dicha
carpeta.
Try {
// Declaración de variables import java.io.File;
import java.io.FilenameFilter; 

public class Filtrar implements FilenameFilter {


String extension;
// Constructor
Filtrar(String extension){
this.extension = extension;
}
public boolean accept(File dir, String name){
return name.endsWith(extension);
}
public static void main(String[] args) {
try { 3.Flujos
// Obtendremos el listado de los archivos de ese directorio
File fichero=new File("c:\\datos\\.");
String[] listadeArchivos = fichero.list();
// Filtraremos por los de extension .txt
listadeArchivos = fichero.list(new Filtrar(".txt"));
// Comprobamos el número de archivos en el listado
int numarchivos = listadeArchivos.length ;
// Si no hay ninguno lo avisamos por consola
if (numarchivos < 1)
Un programa en Java, que necesita realizar una operación de
System.out.println("No hay archivos que listar"); entrada/salida (en adelante E/S), lo hace a través de un flujo o
// Y si hay, escribimos su nombre por consola. stream.
else
{ Un flujo es una abstracción de todo aquello que produce o
consume información.
for(int conta = 0; conta < listadeArchivos.length; conta++)
System.out.println(listadeArchivos[conta]); La vinculación de este flujo al dispositivo físico la hace el
} sistema de entrada y salida de Java.
}
Las clases y métodos de E/S que necesitamos emplear son las
catch (Exception ex) { mismas independientemente del dispositivo con el que estemos
System.out.println("Error al buscar en la ruta indicada"); } actuando. Luego, el núcleo de Java sabrá si tiene que tratar con el
} teclado, el monitor, un sistema de archivos o un socket de red;
liberando al programador de tener que saber con quién está
 En el ejemplo anterior se utiliza la función endsWith. interactuando.

Java define dos tipos de flujos en el paquete java.io:


1.3. Rutas de los ficheros  Byte streams (8 bits): proporciona lo necesario para la
En los ejemplos que vemos en el tema, estamos usando la ruta de
los ficheros tal y como se usan en MS-DOS, o Windows, es decir, gestión de entradas y salidas de bytes y su uso está
por ejemplo: orientado a la lectura y escritura de datos binarios. El
tratamiento del flujo de bytes viene determinado por dos
C:\\datos\Programacion\fichero.txt clases abstractas que son InputStream y OutputStream Estas
dos clases definen los métodos que sus subclases tendrán
Cuando operamos con rutas de ficheros, el carácter separador entre implementados y, de entre todos, destacan read() y write()
directorios o carpetas suele cambiar dependiendo del sistema que leen y escriben bytes de datos respectivamente.
operativo en el que se esté ejecutando el programa.  Character streams (16 bits): de manera similar a los
flujos de bytes, los flujos de caracteres están
Para evitar problemas en la ejecución de los programas cuando se determinados por dos clases abstractas, en este caso:
ejecuten en uno u otro sistema operativo y, por tanto, persiguiendo Reader y Writer. Dichas clases manejan flujos de caracteres
que nuestras aplicaciones sean lo más portables posibles, se Unicode. Y también de ellas derivan subclases concretas
recomienda usar en Java: File.separator. que implementan los métodos definidos en ellas siendo
Podríamos hacer una función que, al pasarle una ruta, nos los más destacados los métodos read() y write() que leen y
devolviera la adecuada según el separador del sistema actual, del escriben caracteres de datos respectivamente.
siguiente modo:
1.4. Flujos basados en bytes
Para el tratamiento de los flujos de bytes, hemos dicho que Java
tiene dos clases abstractas que son InputStream y OutputStream.

Los archivos binarios guardan una representación de los datos en el


archivo, es decir, cuando guardamos texto no guardan el texto en
sí, sino que guardan su representación en un código llamado UTF-
8.
Las clases principales que heredan de OutputStream, para la escritura en el disco duro. Si se leen o escriben pocos caracteres cada vez, el
de ficheros binarios son: proceso se hace costoso y lento por los muchos accesos a disco
duro.
 FileOutputStream: escribe bytes en un fichero. Si el
archivo existe, cuando vayamos a escribir sobre él, se Los BufferedReader, BufferedInputStream, BufferedWriter y
borrará. Por tanto, si queremos añadir los datos al final de añaden un buffer intermedio. Cuando se lee o
BufferedOutputStream
éste, habrá que usar el constructor FileOutputStream(String escribe, esta clase controla los accesos a disco. Así, si vamos
filePath, boolean append), poniendo append a true. escribiendo, se guardarán los datos hasta que haya bastantes datos
 ObjectOutputStream: convierte objetos y variables en como para hacer una escritura eficiente.
vectores de bytes que pueden ser escritos en un
Al leer, la clase leerá más datos de los que se hayan pedido. En las
OutputStream.
siguientes lecturas nos dará lo que tiene almacenado, hasta que
 DataOutputStream, que da formato a los tipos
necesite leer otra vez físicamente. Esta forma de trabajar hace los
primitivos y objetos String, convirtiéndolos en un flujo de
accesos a disco más eficientes y el programa se ejecuta más rápido.
forma que cualquier DataInputStream, de cualquier máquina,
los pueda leer. Todos los métodos empiezan por " write", Además FileReader no contiene métodos que nos permitan leer líneas
como writeByte(), writefloat(), etc. completas, pero sí BufferedReader. Afortunadamente, podemos
construir un BufferedReader a partir del FileReader de la siguiente
De InputStream, para lectura de ficheros binarios, destacamos:
manera:
 FileInputStream: lee bytes de un fichero. File archivo = new File ("C:\\archivo.txt");
 ObjectInputStream: convierte en objetos y variables los
vectores de bytes leídos de un InputStream.: FileReader fr = new FileReader (archivo);

BufferedReader br = new BufferedReader(fr);


Ejemplo: escritura a fichero.
...
En el siguiente ejemplo se puede ver cómo se escribe a un archivo
binario con DataOutputStream: String linea = br.readLine();

Ejemplo: lectura de un fichero


import java.io.File;
import java.io.FileInputStream; En este ejemplo leemos caracteres hasta llegar al fin de archivo
import java.io.FileOutputStream; (EOF o End Of File) del flujo.
import java.io.IOException;
import java.io.InputStream; import java.io.BufferedReader;
import java.io.OutputStream; import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CopiaFicheros { public class LeerFichEOF {
public static void main(String args[]) { public static void main (String args[]) throws
IOException {
// Copiar ficheros
BufferedReader br = new
File origen = new File("origen.txt");
BufferedReader(new FileReader("origen.txt")) ;
File destino = new File("destino.txt");
int codigo = br.read();//lee el primer caracter
try {
char caracter;
InputStream in = new FileInputStream(origen);
//mientras el código no sea -1 (EOF) continuo leyendo
OutputStream out = new FileOutputStream(destino);
while (codigo != -1) {
byte[] buf = new byte[1024];
caracter = (char) codigo; //casting
int len;
System.out.print(caracter);
while ((len = in.read(buf)) > 0) {
codigo = br.read(); //lee un caracter
out.write(buf, 0, len);
}
}
}
in.close();
}
out.close();
} catch (IOException ioe) {
ioe.printStackTrace();
4.Formas de acceso a un
}
}
fichero
}
Hemos visto que en Java puedes utilizar dos tipos de ficheros (de

1.5. Flujos basados en texto o binarios) y dos tipos de acceso a los ficheros (secuencial
o aleatorio). Si bien, y según la literatura que consultemos, a veces

caracteres se distingue una tercera forma de acceso denominada


concatenación, tuberías o pipes.
Para los flujos de caracteres, Java dispone de dos clases abstractas:
Reader y Writer.  Acceso aleatorio: los archivos de acceso aleatorio, al
igual que lo que sucede usualmente con la memoria
Si se usan sólo FileInputStream, FileOuputStream, FileReader o FileWriter, (RAM=Random Access Memory), permiten acceder a
cada vez que se efectúa una lectura o escritura, se hace físicamente los datos en forma no secuencial, desordenada. Esto
implica que el archivo debe estar disponible en su Cuando se trabaja con ficheros de texto se recomienda usar las
totalidad al momento de ser accedido, algo que no clases Reader, para entrada o lectura de caracteres, y Writer para
siempre es posible. salida o escritura de caracteres. Estas dos clases están optimizadas
 Acceso secuencial: En este caso los datos se leen de para trabajar con caracteres y con texto en general, debido a que
manera secuencial, desde el comienzo del archivo hasta tienen en cuenta que cada carácter Unicode está representado por
el final (el cual muchas veces no se conoce a priori). Este dos bytes.
es el caso de la lectura del teclado o la escritura en una
consola de texto, no se sabe cuándo el operador terminará Las subclases de Writer y Reader que permiten trabajar con ficheros
de escribir. de texto son:
 Concatenación (tuberías o "pipes"): Muchas veces es  FileReader, para lectura desde un fichero de texto. Crea un
útil hacer conexiones entre programas que se ejecutan flujo de entrada que trabaja con caracteres en vez de con
simultáneamente dentro de una misma máquina, de modo bytes.
que lo que uno produce se envía por un "tubo" para ser
 FileWriter, para escritura hacia un fichero de texto. Crea un
recibido por el otro, que está esperando a la salida del
flujo de salida que trabaja con caracteres en vez de con
tubo. Las tuberías cumplen esta función
bytes.

1.6. Operaciones básicas También se puede montar un buffer sobre cualquiera de los flujos
que definen estas clases:
sobre ficheros de acceso  BufferedWriterse usa para montar un buffer sobre un flujo

secuencial 
de salida de tipo FileWriter.
BufferedReader se usa para montar un buffer sobre un flujo
Como operaciones más comunes en ficheros de acceso secuencial, de entrada de tipo FileReader.
tenemos el acceso para:

 Crear un fichero o abrirlo para grabar datos. 1.7. Operaciones básicas


 Leer datos del fichero.
 Borrar información de un fichero. sobre ficheros de acceso
 Copiar datos de un fichero a otro.
 Búsqueda de información en un fichero. aleatorio
 Cerrar un fichero. A menudo, no necesitas leer un fichero de principio a fin, sino
simplemente acceder al fichero como si fuera una base de datos,
Ahora vamos a ver como buscar en un archivo secuencial. La idea donde se salta de un registro a otro; cada uno en diferentes partes
es que al ser un fichero secuencial tenemos que abrirlo e ir leyendo del fichero. Java proporciona una clase RandomAccessFile para este
hasta encontrar el dato que buscamos, si es que lo encontramos. tipo de entrada/salida.
Esto se muestra a continuación:
Esta clase:
String busqueda = jTexField1.getText();
try {  Permite leer y escribir sobre el fichero, no es necesario
dos clases diferentes.
// Declarar variable
 Necesita que le especifiquemos el modo de acceso al
DataInputStream archivo = null;
construir un objeto de esta clase: sólo lectura o bien
// Abrir el archivo lectura y escritura.
archivo = new DataInputStream ( new FileInputStream  Posee métodos específicos de desplazamiento como
("c:\\secuencial.dar") ); seek(long posicion) o skipBytes(int desplazamiento) para poder
// Leer archivo movernos de un registro a otro del fichero, o
while (seguir) { posicionarnos directamente en una posición concreta del
// Leer el nombre fichero.
nombre = archivo.readUTF();
Por esas características que presenta la clase, un archivo de acceso
// Si el nombre es el que buscamos directo tiene sus registros de un tamaño fijo o predeterminado de
if (busqueda.equals (nombre) { antemano.
System.out.println ("encontrado");
seguir = false; La clase posee dos constructores:
jLabel2.setText ("¡¡Registro encontrado!!");  RandomAccessFile(File file, String mode).
}  RandomAccessFile(String name, String mode).

// Leer los otros campos En el primer caso se pasa un objeto File como primer parámetro,
apellidos = archivo.readUTF (); mientras que en el segundo caso es un String. El modo es: "r" si se
edad = archivo.readInt (); abre en modo lectura o "rw" si se abre en modo lectura y escritura.
}
A continuación puedes ver una presentación en la que se muestra
// Cerrar fichero
cómo abrir y escribir en un fichero de acceso aleatorio. También,
archivo.close (); en el segundo código descargable, se presenta el código
} correspondiente a la escritura y localización de registros en
catch (FileNotFoundException fne) { / * Archivo no encontrado * / ficheros de acceso aleatorio.
}
catch (IOException ioe) { / * Error al escribir * / } Ejemplo:
Vamos a ver un pequeño ejemplo, Log.java, que añade una cadena conexión abierta, datos recibidos, etc.).  Un Selector permite que
a un fichero existente, lo crea en caso de que no exista. un solo hilo maneje múltiples canales.

import java.io.IOException; El estudio de la  API  NIO completa, excede el modulo, por lo que
import java.io.RandomAccessFile; veremos lo mas básico.  Vamos a estudiar en los subcapítulos
siguiente  las interfaces  Path y Files que son las clases básicas para
public class RandomEjemplo {
acceder a los ficheros. 
public static void main( String args[] ) throws IOException {
En la imagen puedes ver las clases de las que se dispone en
RandomAccessFile miRAFile; java.nio. 
String s = "linea a añadir al final del fichero";
// Abrimos el fichero de acceso aleatorio
miRAFile = new RandomAccessFile( "java.log","rw" );
// Nos vamos al final del fichero
miRAFile.seek( miRAFile.length() );
// Incorporamos la cadena al fichero
miRAFile.writeBytes( s );
// Cerramos el fichero
miRAFile.close();
}
}

5.Java NIO  La interfaz java.nio.file.Path representa un path y las clases


que implementen esta interfaz puede utilizarse para
Una de las tareas más importante que realizan algunas aplicaciones localizar ficheros en el sistema de ficheros. Nos permite
es el manejo de la entrada y salida ya sea al sistema de ficheros o a manejar rutas al estilo GNU/Linux y rutas al estilo
la red. Windows dependiendo del SO en el que estemos
trabajando.
Una de las tareas más importante que realizan algunas aplicaciones
es el manejo de la entrada y salida ya sea al sistema de ficheros o a  La clase java.nio.file.Files es el otro punto de entrada a la
la red. Desde las versiones iniciales de Java se ha mejorado soporte librería de ficheros de Java. Es la que nos permite
añadiendo programación asíncrona de E/S, permitir obtener manejar ficheros reales del disco desde Java.+
información de atributos propios del sistema de archivos,
reconocimiento de enlaces simbólicos y facilitado de algunas
operaciones básicas. 5.1. Java NIO Path
Hemos usado durante muchos años java.io para trabajar con La interfaz java.nio.file.Path representa un path y las clases que
ficheros en el mundo Java . Se trata de un API muy potente y implementen esta interfaz puede utilizarse para localizar
flexible que nos permite realizar casi cualquier tipo de operación. ficheros en el sistema de ficheros.
Sin embargo es un API complicada de entender. Java NIO (New IO)
es un nuevo API disponible desde Java7 que nos permite mejorar el La interfaz java.nio.file.Path representa un path y las clases que
rendimiento así como simplificar el manejo de muchas cosas.  implementen esta interfaz puede utilizarse para localizar
ficheros en el sistema de ficheros.
Java.nio defineinterfaces y clases para que la máquina virtual
Java tenga acceso a archivos, atributos de archivos y sistemas
de archivos. Aunque dicho API comprende numerosas clases, solo Una ruta puede señalar a un archivo o un directorio. Un camino
existen unas pocas de ellas que sirven de puntos de entrada al API, puede ser absoluto o relativo. Una ruta absoluta contiene la ruta
lo que simplifica considerablemente su manejo completa desde la raíz del sistema de archivos hasta el archivo o
directorio al que apunta. Una ruta relativa contiene la ruta al
Java NIO: canales y búferes archivo o directorio relativo a alguna otra ruta. 

En la API de IO estándar, trabajas con secuencias de bytes y


secuencias de caracteres. En NIO, trabaja con canales y búferes. La forma mas sencilla de construir un objeto que cumpla la interfaz
Los datos siempre se leen de un canal a un búfer, o se escriben Path es a partir de la clase java.nio.file.Paths, que tiene métodos
desde un búfer a un canal. estáticos que retornan objetos Path a partir de una
representación tipo String del path deseado, por ejemplo:
Java NIO: IO sin bloqueo
Path p = Paths.get("/home/ad/mi_fichero");
Java NIO le permite hacer IO sin bloqueo. Por ejemplo, un hilo
puede pedirle a un canal que lea datos en un búfer. Mientras el Por supuesto, no es necesario que los ficheros existan de verdad
canal lee datos en el búfer, el hilo puede hacer otra cosa. Una vez en el disco duro para que se puedan crear los objetos Path
que se leen los datos en el búfer, el hilo puede continuar correspondientes: La representación y manejo de paths en Java no
procesándolo. Lo mismo es cierto para escribir datos en canales. está restringida por la existencia de esos ficheros o directorios en el
sistema de ficheros.
Java NIO: Selectores
El interfaz Path declara numerosos métodos que resultan muy
Java NIO contieneel concepto de "selectores". Un selector es un
útiles para el manejo de paths, como por ejemplo, obtener el
objeto que puede gestionar múltiples canales para eventos (como:
nombre corto de un fichero, obtener el directorio que lo contiene, while (it.hasNext()) {
resolver paths relativos, etc. System.out.println(it.next().getFileName());
Una instancia de tipo Path refleja el sistema de nombrado del }
sistema operativo subyacente, por lo que objetos path de diferentes }
sistemas operativos no pueden ser comparados fácilmente entre si. }

Operaciones con Path 5.2. Clases Java NIO Files


 Recuperar partes de una ruta. La clase java.nio.file.Files es el otro punto de entrada a la librería
 Eliminar redundancias de una ruta. de ficheros de Java. Es la que nos permite manejar ficheros reales
 Convertir una ruta. del disco desde Java.
 Unir dos rutas.
La clase java.nio.file.Files es el otro punto de entrada a la librería
 Crear una ruta relativa a otra dada. de ficheros de Java. Es la que nos permite manejar ficheros reales
 Comparar dos rutas. del disco desde Java.

Ejemplo: Esta clase tiene métodos estáticos para el manejo de ficheros, los
métodos de la clase Files trabajan sobre objetos Path. 
import java.nio.file.Path;
Las operaciones principales a realizar con archivos y
import java.nio.file.Paths;
directorios son:

public class PathEjamplo {  Verificación de existencia y accesibilidad.


public static void main(String args[]) {  Borrar un archivo o directorio.
Path path = Paths.get("C:/Users/alumno/PathEjemplo");  Copiar un archivo o directorio.
System.out.println(" path = " + path);  Mover un archivo o directorio.
System.out.println(" is absoute ? = " + path.isAbsolute());
System.out.println(" file short name = " + path.getFileName()); Veamos cómo se realizan algunas de estas operaciones.
System.out.println(" parent = " + path.getParent());
System.out.println(" uri = " + path.toUri());
path = Paths.get("/home/PathEjemplo");
System.out.println(" path = " + path);
Ejemplo 1: Existencia y comprobación de permisos
System.out.println(" is absoute ? = " + path.isAbsolute());
System.out.println(" file short name = " + path.getFileName()); import java.nio.file.Path;
System.out.println(" parent = " + path.getParent()); import java.nio.file.Paths;
System.out.println(" uri = " + path.toUri()); import java.nio.file.Files;
} public class FileEjemplo {
} public static void main(String args[]) {
Path path =
Paths.get("C:\\Users\\alumno\\FileEjamplo\\hola.txt");
Clase FileSystem
System.out.println(" path = " + path);
El concepto de FileSystem define un sistema de ficheros System.out.println(" exists = " + Files.exists(path));
completo. Mientras que por otro lado el concepto de Path hace System.out.println(" readable = " + Files.isReadable(path));
referencia a un directorio, fichero o link que tengamos dentro System.out.println(" writeable = " + Files.isWritable(path));
de nuestro sistema de ficheros. El siguiente código hace uso
System.out.println(" executeable = " + Files.isExecutable(path))
de FileSystem y Path para obtener el nombre de un fichero así como
la carpeta padre en la que se encuentra ubicado.
Ejemplo2: Creación y borrado de directorios
Ejemplo:
import java.nio.file.Path;
import java.nio.file.FileSystem;
import java.nio.file.Paths;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.IOException;
import java.util.Iterator;
// Crea un nuevo fichero o directorio o lo borra si ya existe
public class EjemploPath2 {
public class FileEjemplo2 {
public static void main(String args[]) {
public static void main(String args[]) {
FileSystem sistemaFicheros = FileSystems.getDefault();
Path path = Paths.get("C:\\Users\\alumno\\prueba");
Path rutaFichero =
sistemaFicheros.getPath("C:\\Users\\alumno\\PathEjemplo"); try {
System.out.println(rutaFichero.getFileName()); if (Files.exists(path))
System.out.println(rutaFichero.getParent().getFileName()); Files.delete(path);
Path rutaDirectorio = else
sistemaFicheros.getPath("C:\\Users\\alumno"); Files.createFile(path);
Iterator<Path> it = rutaDirectorio.iterator(); } catch (IOException e) {
System.err.println(e);
System.exit(1); import java.nio.file.Path;
} import java.nio.file.Paths;
} import java.nio.file.FileAlreadyExistsException;
} import java.nio.file.Files;
import java.io.IOException;
//import java.nio.file.FileAlreadyExistsException; //en caso de
El método  delete(Path) borra el fichero o directorio o lanza una
querer sobrescribir el directorio destino
excepción si el borrado falla. El siguiente ejemplo muestra como
public class FileEjemplo5 {
capturar y gestionar las excepciones que pueden producirse en el
borrado  Si el fichero o directorio no existe la excepción que se public static void main(String args[]) {
produce es  NoSuchFileException. Los sucesivos cath permiten Path sourcePath = Paths.get("C:\\Users\\alumno\\origen");
determinar por  que ha fallado el borrado: Path destinationPath =
Paths.get("C:\\Users\\alumno\\FileEjamplo\\destino");
try {
try { Files.copy(sourcePath, destinationPath);
Files.delete(path); //Files.copy(sourcePath, destinationPath,
StandardCopyOption.REPLACE_EXISTING);
} catch (NoSuchFileException x) {
} catch (FileAlreadyExistsException e) {
System.err.format("%s: no such" + " file or directory%n", path);
System.out.println("el fichero existe");
} catch (DirectoryNotEmptyException x) {
} catch (IOException e) {
System.err.format("%s not empty%n", path);
e.printStackTrace();
} catch (IOException x) {
}
// File permission problems are caught here.
}
System.err.println(x);
}
}

Ejemplo 5: Copiar ficheros


El metodo deleteIfExists(Path) tambien borra el fichero o
directorio, pero no lanza ningun error en caso de que el fichero o import java.io.IOException;
directorio no exista.
import java.nio.file.FileAlreadyExistsException;
Ejemplo3: crear un directorio import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Path; import java.nio.file.Paths;
import java.nio.file.Paths; import java.nio.file.StandardCopyOption;
import java.nio.file.FileAlreadyExistsException; public class FileEjemplo7 {
import java.nio.file.Files; public static void main(String args[]) {
import java.io.IOException; Path sourcePath =
// crea una nueva carpeta Paths.get("C:\\Users\\alumno\\FileEjamplo\\hola.txt");
public class FileEjemplo4 Path destinationPath
{ =Paths.get("C:\\Users\\alumno\\FileEjamplo\\destino\\hola.txt");
public static void main(String args[]) { try {
Path path = Paths.get("C:\\Users\\alumno\\newdir"); Files.copy(sourcePath, destinationPath,
try { StandardCopyOption.REPLACE_EXISTING);
Path newDir = Files.createDirectory(path); } catch (FileAlreadyExistsException e) {
} catch(FileAlreadyExistsException e){ System.out.println("el destino existe");
// el directorio ya existe } catch (IOException e) {
} catch (IOException e) { e.printStackTrace();
//error I/O }
e.printStackTrace(); }
} }
}
}
Ejemplo 6: Mover ficheros y directorios, cambiando el nombre

import java.io.IOException;
Ejemplo4: copiar directorios
import java.nio.file.FileAlreadyExistsException;
Se puede copiar un archivo o directorio usando el import java.nio.file.Files;
método copy(Path, Path, CopyOption...). La copia falla si el import java.nio.file.Path;
archivo de destino existe, a menos que se especifique la opción import java.nio.file.Paths;
REPLACE_EXISTING. 
import java.nio.file.StandardCopyOption;
Se puede copiar directorios  Aunque, los archivos dentro del public class FileEjemplo7 {
directorio no se copian, por lo que el nuevo directorio está vacío public static void main(String args[]) {
incluso cuando el directorio original contiene archivos.
Path sourcePath = public class FileEjemplo10 {
Paths.get("C:\\Users\\alumno\\FileEjamplo\\hola.txt"); public static void main(String args[]) {
Path destinationPath = Path inputFile =
Paths.get("C:\\Users\\alumno\\FileEjamplo\\destino\\OtroNombre.t Paths.get("C:\\Users\\alumno\\FileEjamplo\\origen\\hola.txt");
xt"); Path outputFile =
try { Paths.get("C:\\Users\\alumno\\FileEjamplo\\destino\\hola.txt");
Files.move(sourcePath, destinationPath, try {
StandardCopyOption.REPLACE_EXISTING); byte[] contents = Files.readAllBytes(inputFile);
} catch (FileAlreadyExistsException e) { Files.write(outputFile, contents,
System.out.println("el destino existe"); StandardOpenOption.WRITE,
} catch (IOException e) { StandardOpenOption.CREATE,
e.printStackTrace(); StandardOpenOption.TRUNCATE_EXISTING);
} } catch (IOException e) {
} System.err.println(" ERROR : " + e);
} System.exit(1);
}
}
5.3. Escribir contenido en }
Escritura desde buffers
un fichero La escritura desde buffers resulta mucho más eficiente que
utilizando arrays de bytes para ficheros grandes. 
Modos de acceso, el parámetro OpenOptions.
El siguiente programa Java copia ficheros, accediendo al fichero
A la hora de utilizar un fichero en Java se puede restringir el acceso original una 
que  tenemos al mismo desde el propio lenguaje, haciendo más vez por línea y escribiendo en el fichero destino una línea cada vez.
estrictos los permisos de acceso que dicho fichero ya tiene en el Utiliza las clases de java.io:  BufferedReader y BufferedWriter:
sistema de ficheros.
import java .nio. file. Path;
Por ejemplo, si el usuario tiene permisos de lectura y escritura import java .nio. file. Paths ;
sobre un fichero, un programa Java que solo quiera leerlo puede import java .nio. file. Files ;
abrir el fichero solo en modo lectura, lo que ayudará a evitar bugs import java .io. IOException;
desde el propio lenguaje. import java .nio. charset . Charset ;
A tal efecto, en java se definen una serie de modos de acceso a un import java .io. BufferedReader;
fichero a través del parámetro OpenOptions. La forma más cómoda de import java .io. BufferedWriter;
utilizar este parámetro es a través del enum StandardOpenOptions que import java .nio. file. StandardOpenOption;
puede tomar los siguientes valores (hay más): public class FileEjemplo11 {
// Copy a file
 WRITE: habilita la escritura en el fichero
public static void main( String args []) {
 APPEND: todo lo escrito al fichero se hará al final del
Path input = Paths .
mismo
get( "C:\\Users\\alumno\\FileEjamplo\\origen\\hola.txt") ;
 CREATE_NEW: crea un fichero nuevo y lanza una
Path output = Paths .
excepción si ya existía
get("C:\\Users\\alumno\\FileEjamplo\\destino\\hola.txt") ;
 CREATE: crea el fichero si no existe y simplemente lo
try {
abre si ya existía
BufferedReader inputReader = Files .
 TRUNCATE_EXISTING: si el fichero existe, y tiene
newBufferedReader(input , Charset .
contenido, se ignora su contenido para sobreescribirlo
defaultCharset());
desde el principio.
BufferedWriter outputWriter = Files .
Los métodos que se muestran en las siguientes ejemplos utilizan newBufferedWriter(output , Charset .
este parámetro, en la descripción de cada método en el API se defaultCharset() , StandardOpenOption. WRITE ,
explica cual es el comportamiento por defecto en caso de no StandardOpenOption.
utilizarse este parámetro. CREATE , StandardOpenOption.
TRUNCATE_EXISTING);
Escritura desde arrays de bytes String line;
La escritura a ficheros mediante arrays es la forma más sencilla (y while ( ( line = inputReader. readLine ()) != null ) {
limitada) de escritura de ficheros, y se realiza mediante el outputWriter. write (line , 0, line. length ());
método java.nio.file.Files.write(). outputWriter. newLine () ;
}
import java.io.IOException;
inputReader. close ();
import java.nio.file.Files;
outputWriter. close ();
import java.nio.file.Path;
} catch ( IOException e) {
import java.nio.file.Paths;
System .err. println (" ERROR : " + e);
import java.nio.file.StandardOpenOption;
System . exit (1);
} representando la información obtenida de los documentos XML en
} un programa en formato Java, o sea, proporciona a los
desarrolladores de aplicaciones Java, una forma rápida para
}
vincular esquemas XML a representaciones Java.

JAXB proporciona métodos para, a partir de documentos XML,

6.Trabajo con ficheros obtener árboles de contenido (generados en código Java), para
después operar con ellos o manipular los los mismos en una
aplicación Java y generar documentos XML con la estructura de
XML: analizadores los iniciales, pero ya modificados.

sintácticos (parser) y Parsear un documento XML consiste en "escanear" el documento


y dividirlo o separarlo lógicamente en piezas discretas. El
contenido parseado está entonces disponible para la aplicación.
vinculación (binding) Binding: Binding o vincular un esquema (schema) significa
generar un conjunto de clases Java que representan el esquema.
Probablemente hayas estudiado ya XML, bien porque hayas
cursado el módulo Lenguajes de marcas y sistemas de gestión de Compilador de esquema o schema compiler: liga un esquema
información, o bien porque lo conozcas por tu cuenta. Si no fuente a un conjunto de elementos de programa derivados. La
conoces XML, te recomendamos que te familiarices con él, hay vinculación se describe mediante un lenguaje de vinculación
múltiples tutoriales y cursos en Internet. basado en XML.

El metalenguaje XML se crea para evitar problemas de >Binding runtime framework: proporciona operaciones de
interoperabilidad entre plataformas y redes. Con él se consigue un unmarshalling y marshalling para acceder, manipular y validar
soporte estándar para el intercambio de datos: no sólo los datos contenido XML usando un esquema derivado o elementos de
están en un formato estándar sino también la forma de acceder a programa.
ellos. Y entre las ventajas de su uso destacamos:
Marshalling: es un proceso de codificación de un objeto en un
 Facilita el intercambio de información entre distintas medio de almacenamiento, normalmente un fichero. Proporciona a
aplicaciones ya que se basa en estándares aceptados. una aplicación cliente la capacidad para convertir un árbol de
 Proporciona una visión estructurada de la objetos Java JAXB a ficheros XML. Por defecto, el marshaller usa
información, lo que permite su posterior tratamiento de codificación UTF-8 cuando genera los datos XML.
forma local.
Unmarshalling: proporciona a una aplicación cliente la capacidad
de convertir datos XML a objetos Java JAXB derivados.
1.8. Conceptos previos
¿Cómo se trabaja con datos XML desde el punto de vista del
desarrollador de aplicaciones?

Una aplicación que consume información XML debe:


1.10. "Parser" o analizador
 Leer un fichero de texto codificado según dicho estándar. XML.
 Cargar la información en memoria y, desde allí... Cuando se quieren almacenar datos que deban ser leídas por
 Procesar esos datos para obtener unos resultados (que aplicaciones ejecutadas en múltiples plataformas será necesario
posiblemente también almacenará de forma persistente recurrir a formatos más estandarizados, como los lenguajes de
en otro fichero XML). marcas.

El proceso anterior se enmarca en lo que se conoce en informática Los documentos XML consiguen estructurar la información
como "parsing" o análisis léxico-sintáctico, y los programas que intercalando una serie de marcas denominadas etiquetas. En XML ,
lo llevan a cabo se denominan "parsers" o analizadores (léxico- las marcas o etiquetas tienen cierta similitud con un contenedor de
sintácticos). Más específicamente podemos decir que el "parsing información. Así, una etiqueta puede contener otras etiquetas o
XML" es el proceso mediante el cual se lee y se analiza un información textual. De este modo, conseguiremos subdividir la
documento XML para comprobar que está bien formado para, información estructurando de forma que pueda ser fácilmente
posteriormente, pasar el contenido de ese documento a una interpretada.
aplicación cliente que necesite consumir dicha información.
Como toda la información es textual, no existe el problema de
Schema: Un esquema (o schema) es una especificación XML que representar los datos de diferente manera. Cualquier dato, ya sea
dicta los componentes permitidos de un documento XML y las numérica o booleana, habrá transcribirla en modo texto, de modo
relaciones entre los componentes. Por ejemplo, un esquema que cualquiera que sea el sistema de representación de datos será
identifica los elementos que pueden aparecer en un documento posible leer e interpretar correctamente la información contenida en
XML, en qué orden deben aparecer, qué atributos pueden tener, y un archivo XML.
qué elementos son subordinados (esto es, son elementos hijos) para
Es cierto que los caracteres se pueden escribir usando también
otros elementos. Un documento XML no tiene por qué tener un
diferentes sistemas de codificación, pero XML ofrece diversas
esquema, pero si lo tiene, debe atenerse a ese esquema para ser un
técnicas para evitar que esto sea un problema. Por ejemplo, es
documento XML válido.
posible incluir en la cabecera del archivo que codificación se ha
utilizado durante el almacenamiento, o también se pueden escribir
1.9. Definiciones los caracteres de código ASCII superior a 127, utilizando entities
¿Qué es y para qué sirve JAXB (Java Architecture for XML de carácter , una forma universal de codificar cualquier símbolo .
Binding)? JAXB simplifica el acceso a documentos XML
XML consigue estructurar cualquier tipo de información Los analizadores secuenciales, que permiten extraer el contenido a
jerárquica. Se puede establecer cierta similitud con la forma como medida que se van descubriendo las etiquetas de apertura y cierre,
la información se almacena en los objetos de una aplicación y la se denominan analizadores sintácticos. Son analizadores muy
forma como se almacenaría en un documento XML . La rápidos, pero presentan el problema de que cada vez que se
información, en las aplicaciones orientadas a objeto, estructura, necesita acceder a una parte del contenido necesario releer todo el
agrupa y jerarquiza en clases, y en los documentos XML se documento de arriba a abajo.
estructura, organiza y jerarquiza en etiquetas contenidas unas
dentro de otras y atributos de las etiquetas En Java hay dos analizadores secuenciales: SAX, que es el
acrónimo de Simple API for XML . Es una analizador muy usado
en varias bibliotecas de tratamiento de datos XML , pero no suele
usarse en aplicaciones finales y STAX, Streaming API for XML,
Analizador XML posterior a SAX y que lo ha superado.
Dado que XML es un lenguaje utilizado ámpliamente en el Analizadores jerárquicos
desarrollo de la World Wide Web, existen ya herramientas y
estándares de programación para leer documentos XML. Las Generalmente, las aplicaciones finales que necesitan trabajar con
herramientas o programas que leen el lenguaje XML y comprueban datos XML suelen usar analizadores jerárquicos, porque además de
si el documento es válido sintácticamente, se denominan realizar un análisis secuencial que les permite clasificar el
analizadores o "parsers".  contenido, se almacenan en la memoria RAM siguiendo la
estructura jerárquica detectada en el documento. Esto facilita
Un parser XML es un módulo, biblioteca o programa que se ocupa mucho las consultas que haya que repetir varias veces, dado que las
de analizar, clasificar y transformar un archivo de XML en una estructuras jerárquicas de la memoria RAM tienen un rendimiento
representación interna,  extrayendo la información contenida en de acceso parcial a los datos muy eficiente.
cada una de las etiquetas y relacionándola de acuerdo con su
posición en la jerarquía.

 En el caso de XML, como el formato siempre es el mismo, no Los analizadores jerárquicos guardan todos los datos del XML en
necesitamos crear un parser cada vez que hacemos un programa, memoria dentro de una estructura jerárquica. Son ideales para
sino que existen un gran número de parsers o analizadores aplicaciones que requieran una consulta continua de los datos. El
sintácticos disponibles que pueden averiguar si un documento formato de la estructura donde se almacena la información en la
XML cumple con una determinada gramática. Estos analizadores o memoria RAM ha sido especificado por el organismo internacional
parsers pueden ser secuenciales como SAX o STAX o jerarquicos W3C (World Wide Web Consortium) y se suele conocer como
como DOM. DOM (Document Object Model). Es una estructura que HTML y 
javascript han popularizado mucho y se trata de una especificación
Analizadores secuenciales que Java materializa en forma de interfaces. La principal se
denomina Documento y representa todo un documento XML . Al
tratarse de una interfaz, puede ser implementada por varias clases.

Comparativa analizadores
CARACTERÍSTICA STAX SAX DOM TRAX
Tipo de API Pull, streaming Push, streaming En memoria Regla XSLT
Facilidad de uso Alta Media Alta Media
Capacidad XPath No No Si Si
Eficiencia de CPU y memoria Buena Buena Varia Varia
Solo hacia adelante Si Si No No

Lee XML Si Si Si Si
Escribe XML Si No Si Si
Crear, Leer, Modificar, Borrar No No Si No

6.1. DOM // Creación de una instancia Transformer


Transformer trans = TransformerFactory. newInstance .
newTransformer ;
DOM  (Document Object Model ) es una recomendación oficial
del World Wide Web Consortium (W3C). Define una interfaz que // Creación de los adaptadores Source y Results a partir de un
permite a los programas acceder y actualizar el estilo, la estructura Documento
y el contenido de los documentos XML. Los analizadores XML // y un File.
compatibles con DOM implementan esta interfaz. StreamResult result = new StreamResult ( file ) ;
DOMSource source = new DOMSource ( doc ) ;
DOM  (Document Object Model ) es una recomendación oficial
trans.transform ( source, result ) ;
del World Wide Web Consortium (W3C). Define una interfaz que
Con el fin de rebajar la complejidad, vamos a crear una clase que
permite a los programas acceder y actualizar el estilo, la estructura
llamaremos XmlCtrlDomcon utilidades genéricas que nos
y el contenido de los documentos XML. Los analizadores XML
simplifiquen el traspaso de archivos XML a DOM o viceversa.
compatibles con DOM implementan esta interfaz.

El estándar W3C define la especificación de la public class XmlCtrlDom {


clase DocumentBuilder con el propósito de poder instanciar estructuras public static Document instanciarDocument
DOM a partir de un XML. La clase DocumentBuilder es una clase throws ParserConfigurationException {
abstracta, y para que se pueda adaptar a las diferentes plataformas, Document doc = null ;
puede necesitar fuentes de datos o requerimientos diversos. doc = DocumentBuilderFactory. newInstance .
Recuerda que las clases abstractas no se pueden instanciar de forma newDocumentBuilder . newDocument ;
directa. Por este motivo, el consorcio W3 especifica también la return doc ;
clase DocumentBuilderFactory
}
Las instrucciones necesarias para leer un archivo XML y crear un public static void escriureDocumentATextXml ( Document
objeto Documento serían las siguientes:  doc, File file )
throws TransformerException {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory. newInstance ; 
DocumentBuilder dBuilder = dbFactory. newDocumentBuilder ; Transformer trans = TransformerFactory. newInstance .
Document doc = dBuilder. parse ( new File ( "fitxer.xml" ) ) ; newTransformer ;
La escritura de la información contenida en el DOM se puede trans.setOutputProperty ( OutputKeys. indent , "yes" ) ;
secuenciar en forma de texto utilizando otra utilidad de Java
StreamResult result = new StreamResult ( file ) ;
llamada Transformer. Se trata de una utilidad que permite realizar
DOMSource source = new DOMSource ( doc ) ;
fácilmente conversiones entre diferentes representaciones de
información jerárquica. Es capaz, por ejemplo, de pasar la trans. transform ( source, result ) ;
información contenida en un objeto Documento a un archivo de }
texto en formato XML . También sería capaz de hacer la operación public static Document instanciarDocument ( File fXmlFile )
inversa, pero el mismo DocumentBuilder ya se encarga de ello.  throws ParserConfigurationException,
SAXException,
Transformer es también una clase abstracta y requiere de IOException {
una fábrica para poder ser instanciada. La clase Transformer puede
Document doc = null ;
trabajar con multitud de contenedores de información porque en
realidad trabaja con un par de tipos adaptadores (clases que hacen doc = DocumentBuilderFactory.
compatibles jerarquías diferentes) que se llaman Source y Result. Las newInstance.newDocumentBuilder . parse ( fXmlFile ) ;
clases que implementen estas interfaces se encargarán de hacer doc. getDocumentElement.normalize ;
compatible un tipo de contenedor específico al requerimiento de la return doc ;
clase Transformer . Así, disponemos de las }
clases DOMSource, SAXSource o StreamSorce como adaptadores del ...
contenedor de la fuente de información ( DOM, SAX o Stream }
respectivamente). DOMResult, SAXResult o StreamResult son los
adaptadores equivalentes del contenedor destino.

El código básico para realizar una transformación de DOM archivo


de texto XML sería el siguiente:
6.1.1. La estructura DOM
La estructura DOM toma la forma de un árbol, donde cada parte
del XML se encontrará representada en forma de nodo. En función
de la posición en el documento XML, hablaremos de diferentes  Node.getAttribute(attrName) −
Retorna el atributo del nodo con
tipos de nodos. El nodo principal que representa todo el XML el nombre que se pasa como atributo.
entero denomina documento, y las diversas etiquetas, incluida la
etiqueta raíz, se conocen como nodos elemento. 
Para facilitar la obtención del contenido de
El contenido textual de una etiqueta se instancia como nodo de un Element ampliaremos las utilidades de la
tipo TextElement y los atributos como nodos de tipo Atribute. Cada clase XmlCtrlDom añadiendo dos métodos más.
nodo específico dispone de métodos para acceder a sus datos
concretos (nombre, valor, nodos hijos, nodo padre, etc.). public static String getValorEtiqueta ( String etiqueta,
Element elemento ) {
La estructura DOM toma la forma de un árbol, donde cada parte
Nodo nValue = elemento.
del XML se encontrará representada en forma de nodo. En función
getElementsByTagName ( etiqueta ) . item ( 0 ) ;
de la posición en el documento XML, hablaremos de diferentes
return nValue. getChildNodes . item ( 0 ) .
tipos de nodos. El nodo principal que representa todo el XML
getNodeValue ;
entero denomina documento, y las diversas etiquetas, incluida la
etiqueta raíz, se conocen como nodos elemento. El contenido }
textual de una etiqueta se instancia como nodo de tipo TextElement y
los atributos como nodos de tipo Atribute. Cada nodo específico public static Elemento getElementEtiqueta ( String
dispone de métodos para acceder a sus datos concretos (nombre, etiqueta, Element elemento ) {
valor, nodos hijos, nodo padre, etc.). return ( Element ) elemento.
getElementsByTagName ( etiqueta ).item ( 0 ) ;
El DOM resultante obtenido de un XML termina siendo una copia
}
exacta del archivo, pero con una disposición distinta. Tanto el
DOM como el XML tendrán información no visible, como los El primero recibe el nombre de la etiqueta y el elemento (o nodo
retornos de carro, que deben tenerse en cuenta para saber cómo parcial del árbol) a partir  del cual se desea realizar la búsqueda.
procesar correctamente el contenido y evitar sorpresas un poco Utilizando el método getElementsByTagName, conseguiremos todos los
comprensibles. nodos que tengan por nombre el valor del parámetro etiqueta. Es
decir, nos devolverá una colección de nodos. Si sólo existe un
Debes tener en cuenta que al mapear XML los retornos de carro se único nodo con el nombre del parámetro, éste ocupará la primera
interpretan en DOM como un hijo  y que  el contenido textual de posición de la lista. Por ello accedemos con el método item,
las etiquetas se plasma en el DOM como un nodo hijo de la indicando que nos interesa el primer elemento (posición cero).
etiqueta contenedora. Es decir, para obtener el texto de una etiqueta
hay que obtener el primer hijo de ésta. El segundo método es muy similar al primero, pero en vez de
recuperar el texto, obtendremos el nodo con todos los hijos que
La interfaz Documentcontempla un conjunto de métodos para tenga. Es útil para aplicar a nodos intermedios (no textuales).
seleccionar diferentes partes del árbol a partir del nombre de la
etiqueta o de un atributo identificador. Las partes del árbol se Los objetos Elemento disponen de métodos para añadir nuevos
devuelven como objetos Element, los cuales representan un nodo y hijos ( appendChild) o asignar el valor a un atributo ( setAtributte).
todos sus hijos. De este modo, podremos ir explorando partes del También permiten la consulta del valor de los atributos
árbol sin necesidad de tener que pasar por todos los nodos. ( getAttributte) o la navegación por los nodos del árbol ( getParentNode,
para obtener el padre; getFirstChild/getLastChild, para obtener el
primer / último hijo, o getNextSiblingpara navegar de hermano en
hermano).
Interfaces DOM 
El objeto Document hará de factory para cualquier nodo del
DOM define varias interfaces, las mas comunes son las documento. La creación de nuevos elementos (etiquetas) implicará
siguientes el uso de createElement. Si queremos crear contenido textual habrá
llamar al método createTextNode, y si lo que queremos son
 Node − Representa
a cualquier nodo del documento. comentarios llamaremos createComment.
 Element −
expone propiedades y métodos para manipular
los elementos del documento y sus atributos. La creación de nodos no implica la ubicación de este dentro del
 Attr − Representa un atributo de un elemento. árbol. Es decir, además de crearlos habrá asignarlos a un padre
usando appendChild.
 Text − Contenido de un elemento o atributo.
 Document − Representa al documento XML completo.
Generalmente nos referiremos a el como árbol 6.4.2. Ejemplo completo.
DOM. Proporciona información del documento. Permite El ejemplo siguiente muestra cómo utilizar DOM para analizar y
crear nuevos nodos en el documento. extraer información un fichero XML.
 NodeList. Colección de nodos a los que se puede acceder
Listamos la información contenida en el  documento clase.xml, si
por medio de un índice.
etiquetas.
Métodos DOM mas usuales
clase.xml
 Document.getDocumentElement() − Retorna el elemento raiz del
<? xml version = "1.0"?>
documento.
 Node.getFirstChild() −Retorna el primer nodo hijo del nodo.
<clase>
 Node.getLastChild() − Retorna el ultimo nodo  hijo del nodo.
<alumno numero = "393">
 Node.getNextSibling() − Retorna el siguiente hermano de un
<nombre> Luis </ nombre>
nodo.
<apellido> Luna </ apellido>
 Node.getPreviousSibling() −  Retorna el hermano anterior de
un nodo. <apodo> Na </ apodo>
<marcas> 85 </ marcas> import org.w3c.dom.Node;
</ alumno> import org.w3c.dom.Element;
<alumno numero = "493"> public class DomParserDemo {
<nombre> Antonio </ nombre> public static void main(String[] args) {
<apellido> Alvarez</ apellido> try {
<apodo> Avez </ apodo> File inputFile = new File("clase.xml");
<marcas> 95 </ marcas> DocumentBuilderFactory dbFactory =
</ alumno> DocumentBuilderFactory.newInstance();
<alumno numero = "593"> DocumentBuilder dBuilder =
<nombre> Juan </ nombre> dbFactory.newDocumentBuilder();
<apellido> Juz </ apellido> Document doc = dBuilder.parse(inputFile);
<apodo> jazz </ apodo> doc.getDocumentElement().normalize();
<marcas> 90 </ marcas> System.out.println("Root element :" +
</ alumno> doc.getDocumentElement().getNodeName());
</ clase> NodeList nList = doc.getElementsByTagName("alumno");
System.out.println("----------------------------");
for (int temp = 0; temp < nList.getLength(); temp++) {
Pasos a seguir... Node nNode = nList.item(temp);
1.- Importar paquetes XML. System.out.println("\nCurrent Element :" +
nNode.getNodeName());
import org.w3c.dom.*; if (nNode.getNodeType() == Node.ELEMENT_NODE) {
import javax.xml.parsers.*; Element eElement = (Element) nNode;
import java.io.*; System.out.println("numero de alumno : "+
2.- Crear un SAXBuilder. eElement.getAttribute("numero"));
System.out.println("nombre : "+
DocumentBuilderFactory factory = eElement.getElementsByTagName("nombre").item(0).getTextCont
DocumentBuilderFactory.newInstance(); ent());
DocumentBuilder builder = factory.newDocumentBuilder(); System.out.println("apellido :"+
3.- Crear un documento para el flujo de datos. eElement.getElementsByTagName("apellido").item(0).getTextCon
tent());
StringBuilder xmlStringBuilder = new StringBuilder(); System.out.println("apodo : "+
xmlStringBuilder.append("<?xml version="1.0"?> <class> eElement.getElementsByTagName("apodo").item(0).getTextConte
</class>"); nt());
ByteArrayInputStream input = new ByteArrayInputStream( System.out.println("marcas :
xmlStringBuilder.toString().getBytes("UTF-8")); "+eElement.getElementsByTagName("marcas").item(0).getTextCo
Document doc = builder.parse(input); ntent());
4.- Extraer el elemento raíz. }
}
Element root = document.getDocumentElement(); } catch (Exception e) {
e.printStackTrace();
5.- Examinar atributos.
}
//returns specific attribute }
getAttribute("attributeName"); }

//returns a Map (table) of names/values


getAttributes(); 6.4.3 Creación de un fichero
6.- Examinar subelementos.
XML a partir de un
//returns a list of subelements of specified name
getElementsByTagName("subelementName"); documento.
La escritura de la información contenida en el DOM se puede
secuenciar en forma de texto utilizando otra utilidad de Java
//returns a list of all child nodes
llamada Transformer. Se trata de una utilidad que permite realizar
getChildNodes(); fácilmente conversiones entre diferentes representaciones de
información jerárquica. Es capaz, por ejemplo, de pasar la
El programa completo... información contenida en un objeto Documento a un archivo de
texto en formato XML.
import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory; La escritura de la información contenida en el DOM se puede
import javax.xml.parsers.DocumentBuilder; secuenciar en forma de texto utilizando otra utilidad de Java
llamada Transformer . Se trata de una utilidad que permite
import org.w3c.dom.Document;
realizar fácilmente conversiones entre diferentes
import org.w3c.dom.NodeList;
representaciones de información jerárquica. Es capaz, por
ejemplo, de pasar la información contenida en un objeto 2. Cada evento invoca a un método que ha sido realizado
Documento a un archivo de texto en formato XML .  por el programador procesando el documento poco a
poco y no consumiendo prácticamente memoria, aunque
Transformer es también una clase abstracta y requiere de una fábrica por otra parte impide tener visión general de todo el
para poder ser instanciada. La clase Transformer puede trabajar con documento XML.
multitud de contenedores de información porque en realidad trabaja
con un par de tipos adaptadores (clases que hacen compatibles SAX (API Simple para XML), es una interfaz simple de
jerarquías diferentes) que se llaman Source y Result. Las clases que aplicaciones XML, fácil e intuitiva. El parser trabaja de la siguiente
implementen estas interfaces se encargarán de hacer compatible un forma:
tipo de contenedor específico al requerimiento de la
clase Transformer. Así, disponemos de las clases DOMSource, 1. Lee un fichero XML de forma secuencial, produciendo
SAXSource o StreamSorce como adaptadores del contenedor de la eventos de manera secuencial en función de los
fuente de información ( DOM, SAX o Stream resultados de lectura.
respectivamente). DOMResult, SAXResult o StreamResult son los 2. Cada evento invoca a un método que ha sido realizado
adaptadores equivalentes del contenedor destino. por el programador procesando el documento poco a
poco y no consumiendo prácticamente memoria, aunque
El código básico para realizar una transformación de DOM archivo por otra parte impide tener visión general de todo el
de texto XML sería el siguiente: documento XML.
3.
1.- Instanciar el documento DOM en memoria.
Permite analizar el documento  XML de forma secuencial, es decir,
DocumentBuilderFactory factory = va cargando en memoria diferentes partes del mismo, cosa
DocumentBuilderFactory.newInstance(); contraria a lo que hace DOM que carga todo el documento de golpe
en memoria.
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation implementation = Es conveniente utilizar SAX:
builder.getDOMImplementation();
Document document = implementation.createDocument(null,  Cuando el documento XML  es considerablemente
name, null); grande.
2.- El documento DOM se crea en memoria creando primero el  Cuando no se requiere una modificación estructural.
elemento raíz.  Si se quiere parsear diferentes partes del documento.

Element raiz = document.getDocumentElement(); La lectura de un documento XML produce eventos los cuales
invocan a métodos, los eventos son: inicio y fin de un archivo
y a partir de el añadiendo otros elementos, los métodos:
XML(startDocument() y endDocument()), inicio y fin de un elemento
(startElement() y endElement()) y la información que llevan las diferentes
createElement(String tagName) //crea el elemento del tipo
etiquetas (characters()).
especificado
createTextNode(String data)//crea un Textnode dando valor SAX genera un objeto procesador de XML llamado XMLReader,
(Node newChild) para después decir que objetos tienen métodos para transferir los
appendChild(Node newChild) eventos. Estos objetos implementan los siguientes interfaces:
//añade un nodo hijo al final de de la lista de nodos hijos del
nodo3.- Creación e instalación Transformer.  ContentHandler, el cual recibe las notificaciones de los
eventos del fichero XML.
 DTDHandler, que recoge los eventos del DTD del fichero.
<span>Transformer trans =  ErrorHandler, crea el tratamiento de errores.
TransformerFactory.newInstance&nbsp;.newTransformer&nbsp;;<  EntityResolver, se utilizan siempre que se referencia a otra
br></span><span id="yui_3_17_2_1_1596016483417_136"> entidad.
// Creación de los adaptadores Source y Results a partir de un  DefaultHandler, la cual implementa por defecto los métodos,
Documento siendo el programador quien los defina. Con esta clase se
<br></span><span> podrá crear el parser XML. Se compone de los siguientes
// y un File.<br></span><span>StreamResult result = new eventos básicos:
StreamResult ( file ) ; o startDocument: se llama cuando se detecta que el
<br></span><span>DOMSource source = new DOMSource ( doc ) documento empieza. Aquí deben indicarse las
;<br></span> acciones a realizar al inicio del documento.
<span>trans. transform ( source, result ) ;</span> o endDocument: se llama cuando se detecta que el
documento ha acabado. Por lo tanto, aquí
deben indicarse las acciones a realizar al

6.2. SAX. finalizar el documento.


o startElement: Se llama cuando encuentra un
nuevo elemento, nodo, etiqueta, tag, etc. Aquí
SAX (API Simple para XML), es una interfaz simple de debe indicarse el tratamiento que se deberá
aplicaciones XML, fácil e intuitiva. El parser trabaja de la siguiente realizar sobre cada nuevo elemento, como la
forma: recogida de información de sus atributos.
1. Lee un fichero XML de forma secuencial, produciendo o endElement: Se llama una vez ha leído el
eventos de manera secuencial en función de los elemento. Aquí se encuentra la información del
resultados de lectura. nodo y del contenido del nodo por lo que es
aquí donde, normalmente, se recoge la
información. Debemos usar un analizador StAX cuando:
o Characters: se invoca para encontrar una cadena
de texto.  Puede procesar el documento XML de forma lineal de
arriba a abajo.
6.3. StAX.  El documento no está profundamente anidado.
 Está procesando un documento XML muy grande cuyo
StAX es una API basada en Java para analizar documentos árbol DOM consumiría demasiada memoria. Las
XML de forma similar a como lo hace el analizador SAX. Pero implementaciones DOM típicas usan diez bytes de
hay dos diferencias principales entre las dos API: memoria para representar un byte de XML.
 StAX es una API PULL, mientras que SAX es una API  El problema a resolver involucra solo una parte del
PUSH. Significa que en el caso del analizador StAX, una documento XML.
aplicación cliente necesita solicitar al analizador StAX  Los datos están disponibles tan pronto como el
que obtenga información de XML siempre que lo analizador los vea, por lo que StAX funciona bien para
necesite. Pero en el caso del analizador SAX, se requiere un documento XML que llega a través de una
una aplicación cliente para obtener información cuando transmisión.
el analizador SAX notifica a la aplicación cliente que la
información está disponible. Para poder utilizar clases e interfaces de ambas
 StAX API puede leer y escribir documentos API necesitamos un origen de datos XML valido. Esto lo
XML. Usando SAX API, un archivo XML solo se puede conseguimos con la factoria XMLInputFactory:
leer.

StAX consta realmente de 2 distintas API:

 API Cursor: Representa un cursor con el cual se puede ir XMLInputFactory xmlif = XMLInputFactory.newInstance();


hacia adelante en un documento XML desde el principio XMLStreamReader xmlsr =xmlif.createXMLStreamReader(new
hasta el final. Este cursor puede apuntar un elemento a FileReader("books.xml"));
la vez y siempre se mueve hacia adelante, nunca hacia
atrás.
 API Iterator : Representa un flujo de un documento XML o bien 
como un conjunto de objetos de eventos discretos. La
aplicación saca estos eventos en el mismo orden que los XMLInputFactory inputFactory =
proporciona el parser al leerlos del documento XML. Por XMLInputFactory.newInstance();
cada paso de iteración se obtiene un objeto XMLEvent, que InputStream in = new FileInputStream("books.xml");
contiene información sobre el evento generado en el Como deciamos anteriormente,  STAX consiste en dos API
proceso de lectura de la información. Mediante la llamados lectores "Iterador" y "cursor"
referencia a este objeto, podemos extraer la información
de los eventos generados, con los métodos que  ¿Cómo funciona?
proporciona esta clase.
Una de las principales diferencias entre ambos estilos es que El analizador crea diferentes tipos de eventos a medida que avanza
cuando se usa la Iterator API es posible ir hacia atras en la jerarquia , leyendo el documento XML de origen.
cosa que no puede realizarse cuando utilizamos la Cursor API, ya Algunos de los tipos de eventos importantes son:
que una vez mueves el cursor hacia el próximo evento, no se tiene
información acerca del evento previo. Sin embargo la Cursor API 1. Comience el documento
es mas eficiente en cuanto a memoria, así que la selección de que 2. Elemento de inicio
estilo de API utilizar dependerá de las necesidades. 3. Comentarios
4. Caracteres
6.3.1. Características de StAX 5. Elemento final
6. Documento final
Las siguientes son las características de StAX API:
partimos del siguiente documento XML:
 Lee un documento XML de arriba a abajo, reconociendo
<? xml version = "1.0"?>
los tokens que componen un documento XML bien
<BookCatalogue xmlns = "http://www.publishing.org">
formado.
<Libro>
 Los tokens se procesan en el mismo orden en que
aparecen en el documento. <Título> Yogasana Vijnana: la ciencia del yoga </ Title>
 Informa sobre el programa de aplicación la naturaleza de <ISBN> 81-40-34319-4 </ ISBN>
los tokens que el analizador ha encontrado a medida que <Cost currency = "INR"> 11.50 </ Cost>
ocurren. </ Book>
 El programa de aplicación proporciona un lector de </ BookCatalogue>
"eventos" que actúa como un iterador e itera sobre el
evento para obtener la información requerida. Otro lector
disponible es "cursor" que actúa como un puntero a los Este documento genera 18 eventos entre primarios y secundarios:
nodos XML.
 A medida que se identifican los eventos, los elementos
XML pueden recuperarse del objeto de evento y pueden
procesarse más.
# Element/Attribute Event
1 version="1.0" StartDocument
2 isCData = false data = "\n" IsWhiteSpace = true Characters
3 qname = BookCatalogue:http://www.publishing.org attributes = null namespaces = StartElement
{BookCatalogue" -> http://www.publishing.org"}
4 qname = Book attributes = null namespaces = null StartElement
5 qname = Title attributes = null namespaces = null StartElement
6 isCData = false data = "Yogasana Vijnana: the Science of Yoga\n\t" IsWhiteSpace = false Characters
7 qname = Title namespaces = null EndElement
8 qname = ISBN attributes = null namespaces = null StartElement
9 isCData = false data = "81-40-34319-4\n\t" IsWhiteSpace = false Characters
10 qname = ISBN namespaces = null EndElement
11 qname = Cost attributes = {"currency" -> INR} namespaces = null StartElement
12 isCData = false data = "11.50\n\t" IsWhiteSpace = false Characters
13 qname = Cost namespaces = null EndElement
14 isCData = false data = "\n" IsWhiteSpace = true Characters
15 qname = Book namespaces = null EndElement
16 isCData = false data = "\n" IsWhiteSpace = true Characters
17 qname = BookCatalogue:http://www.publishing.org namespaces = {BookCatalogue" -> EndElement
http://www.publishing.org"}
18 EndDocument

 Los eventos se crean en el orden en que se encuentran los books.xml


elementos XML correspondientes en el documento,
incluida la anidación de elementos, la apertura y el cierre <bookstore>
de elementos, el orden de los atributos, el inicio del <book category="cooking">
documento y el final del documento, y así sucesivamente. <title lang="en">Everyday Italian</title>
 Al igual que con la sintaxis XML adecuada, todos los <author>Giada De Laurentiis</author>
elementos del contenedor tienen los correspondientes <year>2005</year>
eventos de inicio y final; por ejemplo, <price>30.00</price>
cada StartElement tiene un EndElement correspondiente , </book>
incluso para elementos vacíos.
<book category="children">
 Los eventos de atributo se tratan como eventos
<title lang="en">Harry Potter</title>
secundarios, y se accede a ellos desde su
<author>J K. Rowling</author>
evento StartElement correspondiente .
<year>2005</year>
 De forma similar a los eventos de Atributo , los eventos
de Espacio de nombres se tratan como secundarios, pero <price>29.99</price>
aparecen dos veces y son accesibles dos veces en la </book>
secuencia de eventos, primero desde <book category="web">
su StartElement correspondiente y luego desde <title lang="en">XQuery Kick Start</title>
su EndElement correspondiente . <author>James McGovern</author>
 Los eventos de caracteres se especifican para todos los <author>Per Bothner</author>
elementos, incluso si esos elementos no tienen datos de <author>Kurt Cagle</author>
caracteres. Del mismo modo, los eventos de carácter se
<author>James Linn</author>
pueden dividir entre eventos.
<author>Vaidyanathan Nagarajan</author>
 El analizador StAX mantiene una pila de espacio de
<year>2003</year>
nombres, que contiene información sobre todos los
espacios de nombres XML definidos para el elemento <price>49.99</price>
actual y sus antecesores. Se puede acceder a la pila del </book>
espacio de nombres, que se expone a través de la <book category="web" cover="paperback">
interfaz javax.xml.namespace.NamespaceContext , mediante el <title lang="en">Learning XML</title>
prefijo del espacio de nombres o el URI. <author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
6.3.2. Ejemplo de API Cursor </book>
El siguiente programa es un ejemplo muy sencillo de como utilizar </bookstore>
un cursor para recorrer un documento XMLPartiendo del
documento XML books.xml,  listamos los  títulos de los libros.
import java.io.FileNotFoundException; XMLInputFactory inputFactory =
import java.io.FileReader; XMLInputFactory.newInstance();
import java.util.ArrayList; // Configura un nuevo eventReader a partir del fichero XML
import javax.xml.stream.FactoryConfigurationError; InputStream in = null;
import javax.xml.stream.XMLInputFactory; try {
import javax.xml.stream.XMLStreamException; in = new FileInputStream("books.xml");
import javax.xml.stream.XMLStreamReader; } catch (FileNotFoundException e1) {
import javax.xml.stream.events.XMLEvent; e1.printStackTrace();
//El programa java que recorre el documento para extraer los titulos }
y el atributo lang es el siguiente try {
&nbsp;public class ListaLibros {
public static void main(String[] args) throws XMLEventReader eventReader =
FileNotFoundException, XMLStreamException { InputFactory.createXMLEventReader(in);
// Creamos el flujo // repetitiva que recorre todos los eventos
XMLInputFactory xmlif = XMLInputFactory.newInstance(); while (eventReader.hasNext()) {
XMLStreamReader xmlsr = xmlif.createXMLStreamReader(new XMLEvent event = eventReader.nextEvent();
FileReader("books.xml")); // si el evento es el inicio del nodo titulo
String tag = null; // avanzo un evento para obtener el titulo del libro
int eventType; if (event.getEventType() ==
System.out.println("Lista de libros"); MLStreamConstants.START_ELEMENT) {
// iteramos con el cursor a lo largo del documento StartElement startElement = event.asStartElement();
while (xmlsr.hasNext()) { if (startElement.getName().getLocalPart() == "title") {
eventType = xmlsr.next(); Iterator iterator = ((StartElement) event).getAttributes();
switch (eventType) { while (iterator.hasNext())
case XMLEvent.START_ELEMENT: { Attribute attribute = (Attribute) iterator.next();
tag = xmlsr.getLocalName(); QName name = attribute.getName();
if (tag.equals("title")) { String value = attribute.getValue();
System.out.println(xmlsr.getElementText() + " System.out.println("Atributo name/valor: " ++ "/" +
idioma&nbsp; " + xmlsr.getAttributeValue(0)); value); }
} event = eventReader.nextEvent();
break; System.out.println((String)
case XMLEvent.END_DOCUMENT: event.asCharacters().getData()); }
System.out.println("Fin del documento"); } else if (event.getEventType() ==
break; XMLStreamConstants.END_DOCUMENT)
} { System.out.println("fin del documento");
} }
} }
} } catch (XMLStreamException e) {
e.printStackTrace();
}
6.3.3. Ejemplo de API Event }
}
Utilizamos el documento books.XML  del ejemplo de la API
cursor, el listado es similar al ejemplo de API de cursor

import java.io.FileInputStream;
import java.io.FileNotFoundException;
6.4. Binding
import java.io.InputStream; El Binding es una técnica que consiste en vincular clases Java con
import java.util.Iterator; formatos específicos de almacenamiento de manera automatizada. 
import javax.xml.namespace.QName;
El Binding es una técnica que consiste en vincular clases Java
import javax.xml.stream.XMLEventReader; con formatos específicos de almacenamiento de manera
import javax.xml.stream.XMLInputFactory; automatizada. 
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException; En Java existen varias bibliotecas para gestionar el binding , como
por ejemplo JAXB , JiBX , XMLBinding , etc. Desde la versión 6.0
import javax.xml.stream.events.Attribute;
se ha incorporado en el JDK estándar JAXB, una potente biblioteca.
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent; Java Architecture for XML Binding (JAXB) permite a los
public class EventReader { desarrolladores Java asignar clases de Java a representaciones
public static void main(String[] args) { XML. JAXB proporciona dos características principales: la
capacidad de serializar las referencias de objetos Java a XML y la
// primero crea un nuevo XMLInputFactory
inversa, es decir, deserializar XML en objetos Java. En otras
palabras, JAXB permite almacenar y recuperar datos en memoria
en cualquier formato XML, sin la necesidad de implementar un <ListaLibro>
conjunto específico de rutinas de carga y guardado de XML para la <Libro>
estructura de clases del programa.  <autor>XXXXXXX</autor>
La siguiente figura muestra lo que ocurre durante el proceso de <nombre>XXXXXXX</nombre>
enlace de JAXB. <editorial>XXXXXXX</editorial>
<isbn>XXXXXXX</isbn>
</Libro>
......
</ListaLibro>
....
<lugar>XXXXXXX</lugar>
<nombre>XXXXXX</nombre>
</libreria>
Para mapear la raiz es necesario una clase librería con anotación
@XmlRootElement.
6.4.1. Configuración con      
anotaciones @XmlRootElement
Las Anotaciones pueden asociarse a un paquete, a una clase, a
un atributo o incluso a un parámetro. Estas clases especiales se public class Libreria {
declaran en el código de la aplicación anteponiendo el símbolo .....
@ en el nombre de la Anotación. }
Esta clase tiene un atributo por cada etiqueta del XML incluido
Las Anotaciones pueden asociarse a un paquete, a una clase, a ListaLibro que es un array de elementos de tipo Libro:
un atributo o incluso a un parámetro. Estas clases especiales se
declaran en el código de la aplicación anteponiendo el símbolo @XmlElementWrapper(name = "ListaLibro")
@ en el nombre de la Anotación . Cuando el compilador de Java @XmlElement(name = "Libro")
detecta una Anotación crea una instancia y la inyecta en el
private ArrayList<Libro> ListaLibro;
elemento estructural afectado (paquete, clase, método, atributo,
etc.). Esto hace que éstas no aparezcan como atributos o métodos
propios del objeto, y por eso decimos que no interacciona con el
modelo de datos, pero las aplicaciones que lo necesiten pueden
obtener la instancia inyectada y usarla.

Las Anotaciones pueden declararse con parámetros o sin


ellos. En caso de que tengan parámetros, estos pueden ser otros
Anotaciones, valores constantes o valores literales, de modo que La clase librería, es la clase que mapea  el XML 
estén disponibles en tiempo de compilación (que es cuando el
import java.util.ArrayList;
compilador realiza la inyección).
import javax.xml.bind.annotation.XmlElement;
Anotaciones principales. import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(namespace = "namespace", name = "nombre" ): Define la raíz
del XML. //Esto significa que la clases "Libreria.java" es el elemento raiz
@XmlType(propOrder = { "field2", "field1",.. }, name = "nombre"): Permite @XmlRootElement
definir en que orden se van escribir los elementos dentro del XML. public class Libreria {
Esta anotación deberán tenerla todas las clases que no mapean la //Wrapper
raiz del XML. @XmlElementWrapper(name = "ListaLibro")
@XmlElement(name = "nombre"):  Define el elemento de XML que se va
@XmlElement(name = "Libro")
usar. Si el atributo de la clase tiene el mismo nombre que la
private ArrayList<Libro> ListaLibro;
etiqueta XML, podemos omitirlo. Tenemos que escribir esta
anotación  antes del método setter correspondiente. Mirar ejemplos private String nombre;
en el siguiente subcapitulo. private String lugar;
@XmlAttribute se utiliza para mapear atributos a los nodos XML.  public ArrayList<Libro> getListaLibro() {
@XmlElementWrapper: ofrece la posibilidad de crear un contenedor return ListaLibro;
alrededor de una representación XML. Este contenedor puede }
contener una colección de elementos. public void setListaLibro(ArrayList<Libro> ListaLibro) {
El parámetro name = "nombre" permite especificar el nombre de la this.ListaLibro = ListaLibro;
etiqueta XML. }
public void setNombre(String nombre) {
6.4.2. Ejemplos con }
this.nombre = nombre;

anotaciones. public void setLugar(String lugar) {


Tenemos la estructura XML siguiente: this.lugar = lugar;
}
<libreria>
public String getNombre() { el código fuente, podremos escribir una aplicación
return nombre; basada en las clases que resulten.
3. Construir el árbol de objetos Java: con nuestra
}
aplicación, se genera el árbol de objetos java, también
public String getLugar() {
llamado árbol de contenido, que representa los datos
return lugar; XML que son validados con el esquema. Hay dos formas
} de hacer esto:
} o Instanciando las clases generadas.
La clase libro que mapea cada uno de los nodos <Libro> del o Invocando al método unmarshall de una clase
XML generada y pasarlo en el documento. El método
unmarshall toma un documento XML válido y
import javax.xml.bind.annotation.XmlType; construye una representación de árbol de
@XmlType(propOrder = { "autor", "nombre", "editorial", "isbn" }) objetos.
public class Libro { 4. Acceder al árbol de contenido usando nuestra
private String nombre; aplicación: ahora podemos acceder al árbol de contenido
private String autor; y modificar sus datos.
5. Generar un documento XML desde el árbol de
private String editorial;
contenido. Para poder hacerlo tenemos que invocar al
private String isbn; método marshall sobre el objeto raíz del árbol.
public String getNombre() {
return nombre; JAXB proporciona dos principales características:
}
 La capacidad de serializar (marshalling) objetos Java a
public String getAutor() {
XML.
return autor;
}  Lo inverso, es decir, deserializar (unmarshalling) XML a
public String getEditorial() { objetos Java.
return editorial;
O sea que JAXB permite almacenar y recuperar datos en
} memoria en cualquier formato XML, sin la necesidad de
public String getIsbn() { implementar un conjunto específico de rutinas XML de carga y
return isbn; salvaguarda para la estructura de clases del programa.
}
El compilador de JAXB (schema compiler) permite generar una
public void setNombre(String nombre) {
serie de clases Java que podrán ser llamadas desde nuestras
this.nombre = nombre;
aplicaciones a través de métodos sets y gets para obtener o
} establecer los datos de un documento XML.
public void setAutor(String autor) {
this.autor = autor; Los pasos en el proceso de enlace de JAXB están representados en
} la figura:
public void setEditorial(String editorial) {
this.editorial = editorial;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
}

1. Generar clases: podemos escribirlas manualmente, como


6.4.3. Funcionamiento de en el capitulo anterior o utilizar las clases  generadas por
el IDE JAXB automáticamente utilizando el esquema
JAXB .xsd correspondiente al XML, lo veremos más adelante.
Para construir una aplicación JAXB necesitamos tener un esquema
XML. 2. Deben compilarse todas las clases generadas, los
archivos fuente y el código de la aplicación .
Tras obtener el esquema XML, seguimos los siguientes pasos
para construir la aplicación JAXB: 3. Aplicar Marshall a los objetos de las clases mapeadas
para crear XML
1. Escribir el esquema: es un documento XML que
contiene la estructura que se tomará como indicaciones 4. Aplicar UnMarshall al XML para obtener objetos de las
para construir las clases. Estas indicaciones pueden ser, clases mapeadas . 
por ejemplo, el tipo primitivo al que se debe unir un valor Marshall
de atributo en la clase generada.
2. Generar los ficheros fuente de Java: para esto usamos Para poder hacer esta traducción, lo primero que necesitamos es un
el compilador de esquema, ya que éste toma el esquema contexto, el cual instanciaremos pasándole la clase de nuestro root:             
como entrada de información. Cuando se haya compilado
&nbsp;JAXBContext jaxbContext = libro1.setNombre("The Game");
JAXBContext.newInstance(Libreria.class); libro1.setAutor("Neil Strauss");
libro1.setEditorial("Harpercollins");
Ya tenemos un contexto y ahora toca generar nuestro Marshaller
libroLista.add(libro1);
       Libro libro2 = new Libro();
libro2.setIsbn("978-3832180577");
Marshaller marshaller = jaxbContext.createMarshaller(); libro2.setNombre("Feuchtgebiete");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPU libro2.setAutor("Charlotte Roche");
T, true);
libro2.setEditorial("Dumont Buchverlag");
libroLista.add(libro2);
Para obtener un resultado, debemos pasarle una salida a nuestro // Se crea La libreria y se le asigna la lista de libros
marshaller. Aquí tienes un par de ejemplo de como hacerlo.         Libreria libreria = new Libreria();
libreria.setNombre("LIbreria sin limite");
marshaller.marshal(libreria, System.out);
libreria.setLugar("Barrio Obrero");
o bien              libreria.setListaLibro(libroLista);
// Creamos un contexto de la clase JAXB y lo intanciamos
File libreria-jaxb = this.getFile(); JAXBContext context =
if (libreria-jaxbl != null) { JAXBContext.newInstance(Libreria.class);
marshaller.marshal(libreria, libreria-jaxb); Marshaller m = context.createMarshaller();
} m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
Boolean.TRUE);
// Lo creamos con system out
UnMarshall
m.marshal(libreria, System.out);
Otra parte también fácil, tenemos varios inputs y utilizaremos el // Escribimos en el archivo
fichero por ahora para poder parsear. Partiendo de que tenemos ya m.marshal(libreria, new File(LIBRERIA_XML));
un contexto, el cual reutilizaremos en esta parte.     // Obtenemos las variables obtenidas del XML creado
anteriormente
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
System.out.println();
System.out.println("Salida del XML: ");
Libreria libreria = (Libreria) unmarshaller.unmarshal( libreria-
Unmarshaller um = context.createUnmarshaller();
jaxb);
Libreria libreria2 = (Libreria) um.unmarshal(new
FileReader(LIBRERIA_XML));
Así de simple, recuperaremos o pasaremos de nuestro fichero xml a ArrayList<Libro> lista = libreria2.getListaLibro();
un objeto el cual tenemos ya mapeado for (Libro libro : lista) {
System.out.println("Libro: " + libro.getNombre() + " de " +
libro.getAutor());
}
6.4.4. Ejemplo: Marshall, }

Unmarshall. }

Una vez que tenemos el proyecto con las clases del apartado
Ejemplo anotaciones, vamos a añadir el siguiente programa
6,7,5, Generación automática de
import java.io.File;
import java.io.FileReader; clases Java a partir del esquema
import java.io.IOException;
import java.util.ArrayList;
.xsd.
AXB es una parte de la plataforma Java SE y una de las APIs de la
import javax.xml.bind.JAXBContext;
plataforma Java EE, y es parte del Java Web Services Development
import javax.xml.bind.JAXBException; Pack (JWSDP). También es uno de los fundamentos para WSIT.
import javax.xml.bind.Marshaller; JAXB es parte de la versión 1.6 SE.
import javax.xml.bind.Unmarshaller;
JAXB es una parte de la plataforma Java SE y una de las APIs de
public class JavaJAXB {
la plataforma Java EE, y es parte del Java Web Services
private static final String LIBRERIA_XML = "./libreria-
Development Pack (JWSDP). También es uno de los fundamentos
jaxb.xml";
para WSIT. JAXB es parte de la versión 1.6 SE.
public static void main(String[] args) throws JAXBException,
IOException { La herramienta "xjc" se puede utilizar para convertir un XML
// Lista de LIbros Schema y otros tipos de archivo de esquemas (en Java 1.6, RELAX
ArrayList<Libro> libroLista = new ArrayList<Libro>(); NG, XML DTD y WSDL son compatibles experimentalmente) a
// Creamos varios libros representaciones de clase. Las clases son marcadas usando
anotaciones del espacio de nombres javax.xml.bind.annotation.*, por
Libro libro1 = new Libro();
ejemplo, @XmlRootElement y @XmlElement. Las secuencias de listas
libro1.setIsbn("978-0060554736"); XML se representan con atributos de tipo java.util.List.
Los serializadores y deserializadores se crean a través de una
instancia de JAXBContext. Byte

Además, JAXB incluye la herramienta " schemagen" que en esencia


puede llevar a cabo la inversa de "xjc", creando un XML Schema a xsd:unsigned
java.math.BigDecimal
partir de un conjunto de clases anotadas. Long

La siguiente tabla muestra las asignaciones de tipos de datos XML


Schema (XSD) a tipos de datos Java en JAXB: javax.xml.datatype.XMLGre
xsd:time
gorianCalendar
Tipo de
XML Tipo de dato Java
javax.xml.datatype.XMLGre
Schema xsd:date
gorianCalendar

xsd:string java.lang.String
javax.xml.datatype.XMLGre
xsd:g
gorianCalendar
xsd:positiveI
java.math.BigInteger
nteger
xsd:anySimp
leType (for
java.lang.Object
xsd:element
xsd:int int
of this type)

xsd:long long
xsd:anySimp
leType (for
java.lang.String
xsd:short short xsd:attribute
of this type)

xsd:decimal java.math.BigDecimal
xsd:duration javax.xml.datatype.Duration

xsd:float float
xsd:NOTAT
javax.xml.namespace.QName
ION
xsd:double double

xsd:boolean boolean Los pasos para obtener las clases IDE Eclipse

1. Descargar la distribución:
xsd:byte byte Download standalone distribution, descomprimimos el
fichero.
2. Añadir todas las clases que estan en la carpeta \jaxb-ri-
xsd:QName javax.xml.namespace.QName 2.3.0\jaxb-ri\lib, jaxb-api.jar, jaxb-core.jar, jaxb-
impl.jar, jaxb-jxc.jar, jaxb-xjc.jar
3. Obtener el esquema .xsd a partir del XML.
xsd:dateTim javax.xml.datatype.XMLGre 4. Crear un proyecto en Eclipse, en la carpeta scr del
e gorianCalendar proyecto situar el esquema  y en la carpeta raíz del
proyecto situamos el fichero XML .Para generar las
clases de forma automática clicamos el botón derecho del
xsd:base64Bi ratón sobre el esquema, generate -> JAXB Classes.
byte[]
nary

xsd:hexBina
byte[]
7.Librerías para
ry

xsd:unsigned
Int
long conversión de
xsd:unsigned
documentos XML a
int
Short
otros formatos
xsd:unsigned short En la mayoría de las aplicaciones informáticas, hay que mostrar la
información resultante de los procesos que se ejecutan, sobre todo
en aplicaciones que generan información que implica tomar
decisiones comerciales. Dicha información está almacenada
normalmente en bases de datos o en archivos.

Hoy en día, XML está muy extendido, y muchas empresas guardan


la información en ficheros o bases de datos con ese formato.

Hay muchos productos o herramientas informáticas que permiten


convertir documentos XML a otros formatos.

En nuestro caso, vamos a optar por una herramienta que permite


generar informes de todo tipo en Java de una forma sencilla:
JasperReport.
Las plantillas de los informes de JasperReports son sencillamente
Esta herramienta permite generar informes electrónicos en formato ficheros XML con la extensión .jrxml. Podemos hacer que
pdf, quizás el formato más usado debido a su portabilidad entre NetBeans reconozca este tipo de ficheros como XML, para que
sistemas conservando la apariencia. Pero existen muchos más: xls, cuando los editemos en el editor se muestren los mismos códigos
html, rtf, csv, xml, etc de colores en las etiquetas y demás elementos de la sintaxis de
XML.

En la imagen se ilustra cómo conseguirlo: en NetBeans pinchamos

1.11. Introducción a en el menú Tools, y ahí en Options. Ahí seleccionamos


Miscellaneous, luego la pestaña Files. Entonces pulsamos en el
botón New... para añadir la nueva extensión.
JasperReport Los pasos a seguir para trabajar con JasperReport serían:
En Java, durante un tiempo, la generación de informes fue uno de
los puntos débiles del lenguaje, pero hoy en día, existen muchas Paso 1: Diseñar la plantilla del informe: un fichero .jrxml. El
librerías y herramientas dedicadas (varias de ellas, de código documento de diseño está representado por un archivo XML que
abierto) para la rápida generación de informes. JasperReports, es mantiene la estructura de un archivo DTD (Document Type
una de las más conocidas. Definition) definido por el motor de JasperReports.
JasperReports es una herramienta que consta de un poderoso motor La generación de un diseño implica editar un archivo XML
para la generación de informes. Está empaquetada en un archivo validado mediante:
JAR y puede ser utilizada como una librería, la cuál podemos
integrar en cualquier IDE de desarrollo en Java para desarrollar <!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD
nuestras aplicaciones. Está escrita totalmente en Java, su código es Report Design//EN"
abierto y es totalmente gratuita bajo los términos de la licencia "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
GPL (Licencia Pública General).

En la presentación que acabas de ver, al descomprimir el fichero de


la descarga, has visto que en el mismo hay varios directorios o Estos documentos XML cuentan con una estructura similar a la de
carpetas. Comentamos brevemente qué contiene cada una: cualquier documento de texto. Fundamentalmente se siguen estas
secciones:
 build: es la librería JasperReports sin empaquetar, con
todas las clases que incluye.  title Título del informe.
 demo: podemos encontrar algunos ejemplos de  pageHeader Encabezado del documento.
utilización de la librería. Estos ejemplos están preparados  columnHeader Encabezado de las columnas.
para ser compilados con la herramienta "ant". Puedes  detail Detalle del documento. Cuerpo
inspeccionar el código Java e intentar compilarlos y  columnFooter Pie de la columna.
ejecutarlos.  pageFooter Pie del documento.
 dist: es donde se encuentra realmente la librería  sumary Cierre del documento.
empaquetada en un fichero JAR (jasperreports-3.7.4.jar) y
algunos ficheros JAR que no utilizaremos. También Paso 2: Compilación: Una vez que se ha realizado el diseño, se
podemos acceder a la documentación tipo javadoc. compila antes de poder iniciar el proceso de carga de datos. La
 docs: es la referencia rápida en formato XML. compilación se lleva a cabo a través del método compileReport().
 lib: Diferentes librerías necesarias por JasperReports,
como algunas para exportar a distintos formatos, para En este proceso, el diseño se transforma en un objeto serializable
incluir gráficos, etc. de tipo net.sf.jasperreports.engine JasperReport, que luego se guarda en
disco.
 src: Ficheros fuente de la librería.

1.12. Diseñar y compilar la


plantilla 1.13. Rellenar el informe
con datos, exportar el
informe
Paso 3: Rellenar el informe con datos: mediante los métodos
fillReportXXX(), se puede realizar la carga de datos del informe,
pasándole como parámetros el objeto de diseño (o bien, el archivo
que lo representa en formato serializado) y la conexión JDBC a la
base de datos desde donde se obtendrá la información que
necesitemos.

Como resultado de este proceso, se obtiene un objeto que


representa un documento listo para ser impreso, un objeto
serializable de tipo JasperPrint. Este objeto puede guardarse en
disco para su uso posterior, o bien puede ser impreso, enviado a la
pantalla o transformado en PDF, XLS, CSV, etc.

Paso 4: Visualización

Ahora podemos optar por mostrar un informe por pantalla,


imprimirlo, o bien obtenerlo en algún tipo específico de fichero,
como PDF, etc.

 Para mostrar un informe por pantalla se utiliza la clase


JasperViewer, la cual, a través de su método main(), recibe el
informe a mostrar.
 Para imprimir el informe usaremos los métodos
printReport(), printPage() o printPages(), contenidos en la clase
JasperPrintManager.
 Para exportar los datos a un formato de archivo
específico podemos utilizar los métodos
exportReportXXX().

8.Anexo I.- Listar ficheros


de una carpeta, filtrando.

9.Anexo II.- Código de


separador de rutas
11. Anexo IV.- Código
de crear un directorio

10. Anexo III.- Código


de crear un fichero

Tema 3. Manejo de conectores


El sistema gestor de bases de datos, en inglés conocido como:
1.Introducción Database Management System (DBMS) gestiona el modo en que
los datos se almacenan, mantienen y recuperan.

En el caso de una base de datos relacional, el sistema gestor de


base de datos se denomina: Relational Database Management
System (RDBMS).

Tradicionalmente, la programación de bases de datos ha sido como


una torre de Babel: gran cantidad de productos de bases de datos en
el mercado y cada uno "hablando" en su lenguaje privado con las
aplicaciones.

Java, mediante JDBC (Java Database Connectivity), permite


Actualmente, las bases de datos relacionales constituyen el simplificar el acceso a bases de datos relacionales, proporcionando
sistema de almacenamiento probablemente más extendido, aunque un lenguaje mediante el cual las aplicaciones pueden comunicarse
otros sistemas de almacenamiento de la información se estén con motores de bases de datos. Sun desarrolló este API para el
abriendo paso poco a poco. acceso a bases de datos, con tres objetivos principales en mente:

Una base de datos relacional se puede definir, de una manera  Ser un API con soporte de SQL: poder construir
simple, como aquella que presenta la información en tablas con sentencias SQL e insertarlas dentro de llamadas al API
filas y columnas. de Java.
 Aprovechar la experiencia de los API's de bases de
Una tabla o relación es una colección de objetos del mismo tipo
datos existentes.
(filas o tuplas).
 Ser lo más sencillo posible.
En cada tabla de una base de datos se elige una clave primaria para
identificar de manera unívoca a cada fila de esta.
1.1. El desfase objeto- 2. Protocolos de acceso
relacional a bases de datos
Inicialmente, cada empresa desarrolladora de un SGBD
implementaba soluciones propietarias específicas para su
sistema, pero pronto se dieron cuenta de que colaborando
conjuntamente podían sacar mayor rendimiento y avanzar
mucho más rápidamente.

Cada SGBD tiene su propia conexión y su propio API


El desfase objeto-relacional, también conocido como impedancia
objeto-relacional, consiste en la diferencia de aspectos que
existen entre la programación orientada a objetos y la base de
datos. Estos aspectos se pueden presentar en cuestiones como:

 Lenguaje de programación: el programador debe


conocer el lenguaje de programación orientado a objetos
(POO) y el lenguaje de acceso a datos.
 Tipos de datos: en las bases de datos relacionales
siempre hay restricciones en el uso de tipos, mientras que
la programación orientada a objetos utiliza tipos de datos
más complejos.
La llegada del ODBC representó un avance sin precedentes en el
 Paradigma de programación: en el proceso de diseño y
camino hacia la interoperabilidad entre bases de datos y lenguajes
construcción del software se tiene que hacer una
de programación. La mayoría de empresas desarrolladoras de
traducción del modelo orientado a objetos de clases al
sistemas gestores de bases de datos incorporaron los drivers de
modelo Entidad-Relación (E/R) puesto que el primero
conectividad a las utilidades de sus sistemas y los lenguajes de
maneja objetos y el segundo maneja tablas y tuplas (o
programación más importantes desarrollaron bibliotecas
filas), lo que implica que se tengan que diseñar dos
específicas para soportar el API ODBC.
diagramas diferentes para el diseño de la aplicación.
Aunque la industria aceptó ODBC como medio principal para
El modelo relacional trata con relaciones y conjuntos debido a
acceso a bases de datos en Windows, la verdad es que no se
su naturaleza matemática. Sin embargo, el modelo de POO
introduce bien en el mundo Java, debido a la complejidad que
trata con objetos y las asociaciones entre ellos. Por esta razón, el
presenta ODBC, y que entre otras cosas ha impedido su transición
problema entre estos dos modelos surge en el momento de querer
fuera del entorno Windows.
persistir los objetos de negocio.
Sistema de conexión ODBC configurado usando diferentes
La escritura (y de manera similar la lectura) mediante JDBC
controladores (drivers) y un API estándar.
implica:

 Abrir una conexión.


 Crear una sentencia en SQL.
 Copiar todos los valores de las propiedades de un objeto
en la sentencia, ejecutarla y así almacenar el objeto.

Esto es sencillo para un caso simple, pero complicado si el objeto


posee muchas propiedades, o bien se necesita almacenar un objeto
que a su vez posee una colección de otros elementos. Se necesita
crear mucho más código, además del tedioso trabajo de creación de
sentencias SQL.

Este problema es lo que denominábamos impedancia Objeto-


Relacional, o sea, el conjunto de dificultades técnicas que surgen
cuando una base de datos relacional se usa en conjunto con un
programa escrito en POO. JDBC  (Java Database Connectivity) se trata de un API bastante
similar a ODBC en cuanto a funcionalidad,  implementado
Como ejemplo de desfase objeto-relacional, podemos poner el específicamente para usar con el lenguaje Java, adaptado a las
siguiente: supón que tienes un objeto "Agenda Personal" con un especificidades de Java. Es decir, la funcionalidad se encuentra
atributo que sea una colección de objetos de la clase "Persona". capsulada en clases (ya que Java es un lenguaje totalmente
Cada persona tiene un atributo "teléfono". Al transformar este caso orientado a objetos) y además, no depende de ninguna plataforma
a relacional, se ocuparía más de una tabla para almacenar la específica, de acuerdo con la característica multiplataforma
información, conllevando varias sentencias SQL y bastante código. defendida por Java.La idea en el desarrollo de JDBC era intentar
ser tan sencillo como fuera posible, pero proporcionando a los
desarrolladores la máxima flexibilidad.

Java, mediante JDBC, permite simplificar el acceso a bases de


datos relacionales, proporcionando un lenguaje mediante el cual las
aplicaciones pueden comunicarse con motores de bases de datos. 
Sun desarrolló este API (java.sql.*)para el acceso a bases de datos, /*Añadir imágenes
con tres objetivos principales en mente:
El API JDBC soporta dos modelos de procesamiento para acceso a
 Ser un API con soporte de SQL: poder construir bases de datos: de dos y tres capas.
sentencias SQL e insertarlas dentro de llamadas al API
En el modelo de dos capas, una aplicación se comunica
de Java.
directamente a la fuente de datos. Esto necesita un conector JDBC
 Aprovechar la experiencia de los API's de bases de datos que pueda comunicar con la fuente de datos específica a la que
existentes. acceder.

Los comandos o instrucciones del usuario se envían a la base de


 Ser lo más sencillo posible.
datos y los resultados se devuelven al usuario. La fuente de datos
Los desarrolladores de Los Sistemas Gestores de Bases de Datos puede estar ubicada en otra máquina a la que el usuario se conecte
proporcionan la implementación de esa interfaz (Drivers). por red. A esto se denomina configuración cliente/servidor, con la
máquina del usuario como cliente y la máquina que aloja los datos
JDBC es similar en estructura a ODBC. Una aplicación JDBC está como servidor.
compuesta de varias capas, como se muestra en la figura:
En el modelo de tres capas, los comandos se envían a una capa
intermedia de servicios, la cual envía los comandos a la fuente de
datos. La fuente de datos procesa los comandos y envía los
resultados de vuelta la capa intermedia, desde la que luego se le
envían al usuario.

El API JDBC viene distribuido en dos paquetes:

 java.sql, dentro de J2SE.


 javax.sql, extensión dentro de J2EE

La capa superior en este modelo es la aplicación Java. Las


aplicaciones Java son portátiles: puede ejecutar una aplicación Java
2.2. Conectores o Drivers
/*Añadir imagen
sin modificaciones en cualquier sistema que tenga instalado
una maquina virtual java  (Java runtime environment).  Un conector o driver es un conjunto de clases encargadas de
implementar los interfaces del API y acceder a la base de datos.
Una aplicación Java que utiliza JDBC puede comunicarse con
muchas bases de datos con pocas modificaciones, si es que las Para poder conectarse a una base de datos y lanzar consultas, una
hay. Al igual que ODBC, JDBC proporciona una manera aplicación necesita tener un driver adecuado. Un conector suele ser
consistente de conectarse a una base de datos, ejecutar comandos y un fichero .jar que contiene una implementación de todas las
recuperar los resultados. Al igual que ODBC, JDBC no impone un interfaces del API JDBC.
lenguaje de comando común: puede usar la sintaxis específica de
Oracle cuando está conectado a un servidor Oracle y la sintaxis Cuando se construye una aplicación de base de datos, JDBC
específica de MySQL cuando está conectado a un servidor oculta lo específico de cada base de datos, de modo que el
MySQL.  programador se ocupe sólo de su aplicación.

La clase JDBC DriverManager es responsable de localizar un El conector lo proporciona el fabricante de la base de datos o bien


controlador JDBC que necesita la aplicación. Cuando una un tercero. El código de nuestra aplicación no depende del driver,
aplicación cliente solicita una conexión de base de datos, la puesto que trabajamos mediante los paquetes java.sql y javax.sql.
solicitud se expresa en forma de una URL (Uniform Resource
JDBC ofrece las clases e interfaces para:
Locator). Una URL de JDBC es similar a las URL que utiliza con
un navegador web.  Para conectarnos a la base de datos Oracle,   Establecer una conexión a una base de datos.
por ejemplo: jdbc:oracle:thin:ejemplo/ejemplo@localhost:1521:XE  Ejecutar una consulta.
A medida que cada controlador se carga en una Máquina Virtual de  Procesar los resultados.
Java (VM), se registra con el DriverManager JDBC . Cuando una
Ejemplo:
aplicación solicita una conexión, el DriverManager pregunta a
cada Controlador si puede conectarse a la base de datos /* Añadir imagen
especificada en la URL dada. Tan pronto como encuentra
un controlador adecuado , la búsqueda se detiene y En principio, todos los conectores deben ser compatibles con ANSI
el controlador intenta establecer una conexión con la base de SQL-2 Entry Level (ANSI SQL-2 se refiere a los estándares
datos. Si el intento de conexión falla, el Controlador lanzará adoptados por el American National Standards Institute en 1992.
una SQLException a la aplicación. Si la conexión se completa con Entry Level se refiere a una lista específica de capacidades de
éxito, el controlador crea un objeto de conexión y lo devuelve a la SQL.) Los desarrolladores de drivers pueden establecer que sus
aplicación. conectores conocen estos estándares.

Hay cuatro tipos de drivers JDBC: Tipo 1, Tipo 2, Tipo 3 y Tipo


4, que veremos a continuación.

2.1. Arquitectura JDBC


Este driver está basado en servidor, por lo que no se necesita
2.3. Conectores tipo 1 y ninguna librería de base de datos en las máquinas clientes.
Normalmente, un driver de tipo 3 proporciona soporte para
tipo 2 balanceo de carga, funciones avanzadas de administrador de
/*Añadir Imágenes sistemas tales como auditoría, etc.

Los conectores tipo 1 se denominan también JDBC-ODBC Tipo 4: Protocolo nativo.


Bridge (puente JDBC-ODBC).
En este caso se trata de conectores que convierten directamente las
Proporcionan un puente entre el API JDBC y el API ODBC. El llamadas JDBC al protocolo de red usando por el sistema gestor de
driver JDBC-ODBC Bridge traduce las llamadas JDBC a llamadas la base de datos. Esto permite una llamada directa desde la
ODBC y las envía a la fuente de datos ODBC. máquina cliente al servidor del sistema gestor de base de datos y es
una solución excelente para acceso en intranets.
Como ventajas destacar:
Como ventaja se tiene que no es necesaria traducción adicional o
 No se necesita un driver específico de cada base de datos capa middleware, lo que mejora el rendimiento, siendo éste mejor
de tipo ODBC. que en el caso de los tipos 1 y 2.
 Está soportado por muchos fabricantes, por lo que
tenemos acceso a muchas Bases de Datos. Además, no se necesita instalar ningún software especial en el
cliente o en el servidor.
Como desventajas señalar:
Como inconveniente, de este tipo de conectores, el usuario necesita
 Hay plataformas que no lo tienen implementado. un driver diferente para cada base de datos.
 El rendimiento no es óptimo ya que la llamada JDBC se
realiza a través del puente hasta el conector ODBC y de Un ejemplo de este tipo de conector es Oracle Thin.
ahí a la interface de conectividad de la base de datos. El /* Añadir imagen
resultado recorre el camino inverso.
 Se tiene que registrar manualmente en el gestor de
ODBC teniendo que configurar el DSN (Data Source
Names, Nombres de fuentes de datos).

Este tipo de driver va incluido en el JDK.


3.Conexión a una base
Los conectores tipo 2 se conocen también como: API nativa de datos
Convierten las llamadas JDBC a llamadas específicas de la base de Para acceder a una base de datos y así poder operar con ella, lo
datos para bases de datos como SQL Server, Informix, Oracle, o primero que hay que hacer es conectarse a dicha base de datos.
Sybase.
En Java, para establecer una conexión con una base de datos
El conector tipo 2 se comunica directamente con el servidor de podemos utilizar el método getConnection() de la clase DriverManager.
bases de datos, por lo que es necesario que haya código en la Este método recibe como parámetro la URL de JDBC que
máquina cliente. identifica a la base de datos con la que queremos realizar la
conexión.
Como ventaja, este conector destaca por ofrecer un rendimiento
notablemente mejor que el JDBC-ODBC Bridge. La ejecución de este método devuelve un objeto Connection que
representa la conexión con la base de datos.
Como inconveniente, señalar que la librería de la base de datos del
vendedor necesita cargarse en cada máquina cliente. Por esta razón Cuando se presenta con una URL específica, DriverManager itera
los drivers tipo 2 no pueden usarse para Internet. sobre la colección de drivers registrados hasta que uno de ellos
reconoce la URL especificada. Si no se encuentra ningún conector
Los drivers Tipo 1 y 2 utilizan código nativo vía JNI, por lo que
adecuado, se lanza una SQLException
son más eficientes.
Veamos un ejemplo con comentarios, para conectarnos a una base
/* Añadir imagen
de datos MySQL:

/*Añadir imagen

2.4. Conectores tipo 3 y


tipo 4 3.1. Instalar el conector de
/*Añadir imagen

Tipo 3: JDBC-Net pure Java driver.


la base de datos
Para que podamos ejecutar el código anterior, necesitamos instalar
Tiene una aproximación de tres capas. Las peticiones JDBC a la el conector de la base de datos.
base de datos se pasan a través de la red al servidor de la capa
Entre nuestra aplicación Java y el Sistema Gestor de Base de Datos
intermedia (middleware). Este servidor traduce este protocolo
(SGBD), se intercala el conector JDBC. Este conector es el que
independiente del sistema gestor a protocolo específico del sistema
implementa la funcionalidad de las clases de acceso a datos y
gestor y se envía a la base de datos. Los resultados se mandan de
proporciona la comunicación entre el API JDBC y el SGBD.
vuelta al middleware y se enrutan al cliente.

Es útil para aplicaciones en Internet.


La función del conector es traducir los comandos del API JDBC al connection = dataSource.getConnection();
protocolo nativo del SGBD.
Cuando hayamos finalizado la operación entonces cerraremos la
En la siguiente presentación vamos a ver cómo descargarnos el conexión lógica con el siguiente código:
conector que necesitamos para trabajar con MySQL. Como verás,
tan sólo consiste en descargar un archivo, descomprimirlo y desde connection.close();
NetBeans añadir el fichero .jar que constituye el driver que
necesitamos.

/*Añadir imagen
4.Creación de la base
3.2. Pool de conexiones (I) de datos
Acabamos de ver cómo se realiza una conexión a una base de Juan le explica a Antonio, que una base de datos puede crearse
datos. En ocasiones, sobre todo cuando se trabaja en el ámbito de utilizando las herramientas proporcionadas por el fabricante de la
las aplicaciones distribuidas, en entornos web, es recomendable base de datos, o por medio de sentencias SQL desde un programa
gestionar las conexiones de otro modo. Java. Pero normalmente es el administrador de la base de datos, a
través de las herramientas que proporcionan el sistema gestor, el
La explicación es que: abrir una conexión, realizar las operaciones que creará la base de datos. No todos los conectores JDBC
necesarias con la base de datos, y cerrar la conexión; puede ser soportan la creación de la base de datos mediante el lenguaje de
lento en entornos web si lo hacemos como hemos visto. definición de datos (DDL). Es decir, la sentencia CREATE
DATABASE no es parte del estándar SQL, sino que es dependiente
En las aplicaciones en las que es necesario el acceso concurrente y
masivo a una base de datos, como es el caso de las aplicaciones del sistema gestor de la base de datos.
web, es necesario disponer de varias conexiones. El proceso de Así pues, mediante JDBC podemos conectarnos y manipular bases
creación y destrucción de una conexión a una base de datos es de datos: crear tablas, modificarlas, borrarlas, añadir datos en las
costoso e influye sensiblemente en el rendimiento de una tablas, etc. Pero la creación en sí de la base de datos la hacemos
aplicación. Es mejor en estos casos, por tanto, abrir una o más con la herramienta específica para ello.
conexiones y mantenerlas abiertas.
Normalmente, cualquier sistema gestor de bases de datos incluye
La versión 3 y 4 de JDBC proporcionan un pool de conexiones que asistentes gráficos para crear la base de datos, sus tablas, claves, y
funciona de forma transparente. todo lo necesario.
Al iniciar un servidor JavaEE, automáticamente el pool de También, como en el caso de MySQL, o de Oracle, y la mayoría de
conexiones crea un número de conexiones físicas iniciales. los sistemas gestores de bases de datos, se puede crear la base de
Cuando un objeto Java del servidor J2EE necesita una conexión a datos, desde la línea de comandos de MySQL o de Oracle, con las
través del método dataSource.getConnection(), la fuente de datos sentencias SQL apropiadas.
javax.sql.DataSource habla con el pool de conexiones y éste le entrega
Veamos cómo crear paso a paso una base de datos con Microsoft
una conexión lógica java.sql.Connection. Esta conexión lógica la Access. Si no dispones de Microsoft Access, no te preocupes, más
recibe, por último, el objeto Java. abajo puedes descargar la base de datos ya creada.
Cuando un objeto Java del servidor Java EE desea cerrar una /*Añadir imagen
conexión a través del método connection.close(), la fuente de datos
javax.sql.DataSource habla con el pool de conexiones y le devuelve la
conexión lógica en cuestión.

Si hay un pico en la demanda de conexiones a la base de datos, el


pool de conexiones de forma transparente crea más conexiones
5. Operaciones:
físicas de objetos tipo Connection. Si por el contrario las conexiones a
la base de datos disminuyen, el pool de conexiones, también de ejecución de
forma transparente elimina conexiones físicas de objetos de tipo
Connection. consultas
Para operar con una base de datos, ejecutando las consultas
necesarias, nuestra aplicación deberá hacer:
3.2.1. Pool de conexiones (II)  Cargar el driver necesario para comprender el protocolo
El código básico para conectarnos a una base de datos con pool de
conexiones transparente a través de JNDI podría ser: que usa la base de datos en cuestión.
 Establecer una conexión con la base de datos.
//Initial Context es el punto de entrada para  Enviar consultas SQL y procesar el resultado.
// comenzar a explorar un espacio de nombres.  Liberar los recursos al terminar.
 Gestionar los errores que se puedan producir.
javax.naming.Context ctx = new InitialContext();
dataSource = (DataSource) Podemos utilizar los siguientes tipos de sentencias:
ctx.lookup("java:comp/env/jdbc/Basededatos");
 Statement:
para sentencias sencillas en SQL.
Cada vez que necesitamos realizar una operación tendremos que  PreparedStatement:
para consultas preparadas, como por
escribir el siguiente código para obtener una conexión lógica: ejemplo las que tienen parámetros.
 CallableStatement: para ejecutar procedimientos Definir la fuente de datos ODBC es bien fácil, de todos modos, te
almacenados en la base de datos. lo ponemos aquí para veas cómo se hace.

El API JDBC distingue dos tipos de consultas: /*Añadir imagen

 Consultas: SELECT
 Actualizaciones: INSERT, UPDATE, DELETE, sentencias
DDL. 5.1.1. Ejemplo: consultas con
Veamos a continuación cómo realizar una consulta en la base de
datos que creamos en el apartado anterior, la base de datos
MS-Access (II)
Las consultas que se realizan a una base de datos se realizan
farmacia.mdb.
utilizando objetos de las clases Statement y PreparedStatement. Estos
En este caso utilizaremos un acceso mediante puente JDBC- objetos se crean a partir de una conexión.
ODBC. Dicho puente da acceso a bases de datos ODBC.
Statement stmt = con.createStatement();
Este driver está incorporado dentro de la distribución de Java, por
lo que no es necesario incorporarlo explícitamente en el classpath La clase Statement contiene los métodos executeQuery y executeUpdate
de una aplicación Java. para realizar consultas y actualizaciones, respectivamente. Ambos
métodos soportan consultas en SQL-92. Así por ejemplo, para
obtener los nombres de los medicamentos que tenemos en la tabla
medicamentos, de la base de datos farmacia.mdb que creamos
5.1. Ejemplo: consultas con anteriormente, tendríamos que emplear la sentencia:

MS-Access (I) ResultSet rs = stmt.executeQuery("SELECT nombre from


medicamentos");
/* Añadir imagen
El método executeQuery devuelve un objeto ResultSet para poder
En primer lugar, tenemos que definir la fuente de datos ODBC. recorrer el resultado de la consulta utilizando un cursor.
Dependiendo de la versión de Windows con la que trabajemos, el
programa de definición de fuentes de datos ODBC puede variar de while (rs.next())
localización, pero siempre dentro del Panel de Control o algún
String usuario = rs.getString("nombre");
subgrupo. En Windows 7, lo encontramos en el panel de control,
luego en herramientas administrativas y finalmente en “Orígenes
El método next se emplea para hacer avanzar el cursor. Para obtener
de datos (ODBC)”.
una columna del registro utilizamos los métodos get. Hay un
Dentro de la pestaña “DSN de usuario” encontramos los diferentes método get para cada tipo básico Java y para las cadenas.
drivers ODBC instalados en el sistema.
Hay que comentar que un método interesante del cursor es wasNull
A continuación, hay que instalar el driver JDBC. Las clases e que nos informa si el último valor leído con un método get es nulo.
interfaces para trabajar con una base de datos relacional quedan
Respecto a las consultas de actualización, executeUpdate, retornan el
establecidas por el API JDBC. Algunas de estas clases están
número de registros insertados, registros actualizados o eliminados,
parcialmente diferidas y los interfaces están sin implementar. Es
dependiendo del tipo de consulta que se trate.
responsabilidad de cada sistema gestor la implementación de las
clases que dan acceso a las bases de datos. Por ello, para cada tipo Aquí tienes el proyecto que realiza la consulta de todos los
de base de datos se trabaja con un conjunto diferente de clases. medicamentos de la tabla que los contiene, llamada medicamentos,
Esto es lo que se denomina driver JDBC. en la base de datos farmacia.mdb.
Dentro del código se carga el driver antes de acceder a la base de /*Añadir imagen
datos:

Class.forName("jdbc:odbc:admdb");

Posteriormente, una vez instalado el conector y cargado dentro del 5.2. Consultas preparadas
código Java sólo necesitamos realizar la conexión a la base de Las consultas preparadas están representadas por la clase
datos para comenzar a trabajar con ella. La clase DriverManager PreparedStatement.
define el método getConnection para crear una conexión a una base de
datos. Este método toma como parámetro una URL JDBC donde se Son consultas precompiladas, por lo que son más eficientes, y
indica el sistema gestor y la base de datos. Opcionalmente, y pueden tener parámetros.
dependiendo del sistema gestor, habrá que especificar el login y
Una consulta se instancia del modo que vemos con un ejemplo:
password para la conexión. En el caso de JDBC-ODBC la cadena
de conexión sería: jdbc:odbc:admdb, en la que no es necesario PreparedStatement pstmt = con.preparedStatement("SELECT *
establecer el protocolo. Finalmente, el código para establecer una from medicamentos");
conexión quedaría del siguiente modo:
Para las consultas que se realizan muy a menudo es aconsejable
Connection con = usar este tipo de consultas, de modo que el rendimiento del sistema
DriverManager.getConnection("jdbc:odbc:admdb"); será mejor de esta manera.
Ahora ya podemos realizar las consultas que deseemos. Si hay que emplear parámetros en una consulta, se puede hacer
usando el carácter ‘?’. Por ejemplo, para realizar una consulta de
un medicamento que tenga un código determinado, haríamos la
consulta siguiente: almacenados en
PreparedStatement pstmt = con.preparedStatement("SELECT *
from medicamentos WHERE codigo = ? ");
MySQL
A continuación, vamos a realizar un procedimiento almacenado en
MySQL, que simplemente insertará datos en la tabla clientes.
Establecemos los parámetros de una consulta utilizando métodos
Desde el programa Java que realizamos, llamaremos para ejecutar a
set que dependen del tipo SQL de la columna.
ese procedimiento almacenado. Por tanto, ¿cuál sería la secuencia
Así, le decimos que el primer parámetro, que es el único que tiene que seguiríamos para realizar esto?
esta consulta, es “712786”:
 Si no tenemos creada la tabla de clientes, la creamos. Por
pstmt.setString(1, "712786"); simplicidad, en este ejemplo, trabajamos sobre la base de
datos que viene por defecto en MySQL, el esquema
El primer argumento de este método es la posición del parámetro denominado: test. Para crear la tabla de clientes, el script
dentro de la consulta. correspondiente es:
/*Añadir imagen
Finalmente, ejecutamos la consulta utilizando el método  Creamos el procedimiento almacenado en la base de
executeQuery()o executeUpdate(), ambos sin parámetros, dependiendo datos. Sería tan fácil como:
del tipo de consulta. /*Añadir imagen
 Crear la clase Java para desde aquí, llamar al
procedimiento almacenado:
/*Añadir imagen
6. Ejecución de Si hemos definido la tabla correctamente, con su clave primaria, y
ejecutamos el programa, intentando insertar una fila igual que otra
procedimientos insertada, o sea, con la misma clave primaria, obtendremos un
mensaje al capturar la excepción de este tipo:
almacenados en la SQL Exception:

base de datos com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolat


ionException:
Duplicate entry '765' for key 'PRIMARY'
Un procedimiento almacenado es un procedimiento o subprograma
que está almacenado en la base de datos.

Muchos sistemas gestores de bases de datos los soportan, por


ejemplo: MySQL, Oracle, etc.
7.Transacciones
Además, estos procedimientos suelen ser de dos clases: Cuando tenemos una serie de consultas SQL que deben ejecutarse
en conjunto, con el uso de transacciones podemos asegurarnos de
 Procedimientos almacenados. que nunca nos quedaremos a medio camino de su ejecución.
 Funciones, las cuales devuelven un valor que se puede
emplear en otras sentencias SQL. Las transacciones tienen la característica de poder “deshacer” los
cambios efectuados en las tablas, de una transacción dada, si no se
Un procedimiento almacenado típico tiene: han podido realizar todas las operaciones que forman parte de
dicha transacción.
 Un nombre.
 Una lista de parámetros. Por eso, las bases de datos que soportan transacciones son mucho
 Unas sentencias SQL. más seguras y fáciles de recuperar si se produce algún fallo en el
servidor que almacena la base de datos, ya que las consultas se
Veamos un ejemplo de sentencia para crear un procedimiento ejecutan o no en su totalidad.
almacenado sencillo para MySQL, aunque sería similar en otros
sistemas gestores: Al ejecutar una transacción, el motor de base de datos garantiza:
atomicidad, consistencia, aislamiento y durabilidad (ACID) de
/*Añadir imagen la transacción (o conjunto de comandos) que se utilice.
Como se ve en los comentarios, este procedimiento admite un El ejemplo típico que se pone para hacer más clara la necesidad de
parámetro, llamado par1. También se declara una variable a la que transacciones en algunos casos es el de una transacción bancaria.
llamamos var1 y es de tipo carácter y longitud 13. Si el valor que le Por ejemplo, si una cantidad de dinero es transferida de la cuenta
llega de parámetro es igual a 24, entonces se asigna a la variable de Antonio a la cuenta de Pedro, se necesitarían dos consultas:
var1, la cadena 'perro rabioso' y en caso contrario se le asignará la
cadena: 'gato persa'. Finalmente, se inserta en la tabla “Animales” el  En la cuenta de Antonio para quitar de su cuenta ese
valor que se asignó a la variable var1. dinero:
UPDATE cuentas SET saldo = saldo - cantidad WHERE
cliente = “Antonio”;
 En la cuenta de Pedro para añadir ese dinero a su cuenta:
6.1. Ejecutando UPDATE cuentas SET saldo = saldo + cantidad WHERE
cliente = “Pedro”;
procedimientos
Pero ¿qué ocurre si por algún imprevisto (un apagón de luz, etc.), También conviene cerrar las consultas ( Statement y PreparedStatement) y
el sistema “cae” después de que se ejecute la primera consulta, y los resultados (ResultSet) para liberar los recursos.
antes de que se ejecute la segunda? Antonio tendrá una cantidad de
dinero menos en su cuenta y creerá que ha realizado la Una excepción es una situación que no se puede resolver y que
transferencia. Pedro, sin embargo, creerá que todavía no le han provoca la detención del programa de manera abrupta. Se produce
realizado la transferencia. por una condición de error en tiempo de ejecución.

En Java hay muchos tipos de excepciones, el paquete


java.lang.Exception es el que contiene los tipos de excepciones.

7.1. Commit y Rollback


/*Añadir imagen Para saber más
Una transacción tiene dos finales posibles, COMMIT o Resumen
ROLLBACK. Si se finaliza correctamente y sin problemas se hará
con COMMIT, con lo que los cambios se realizan en la base de
datos, y si por alguna razón hay un fallo, se deshacen los cambios
efectuados hasta ese momento, con la ejecución de ROLLBACK.
8.1. Excepciones
Por defecto, al menos en MySQL o con Oracle, en una conexión Cuando se produce un error durante la ejecución de un
trabajamos en modo autocommit con valor true. Eso significa que cada programa, se genera un objeto asociado a esa excepción. Ese
consulta es una transacción en la base de datos. objeto es de la clase Exception o de alguna de sus subclases. Este
objeto se pasa entonces al código que se ha definido para gestionar
Por tanto, si queremos definir una transacción de varias
la excepción.
operaciones, estableceremos el modo autocommit a false con el
método setAutoCommit de la clase Connection. En una porción de programa donde se trabajará con ficheros, y con
bases de datos podríamos tener esta estructura para capturar las
En modo no autocommit las transacciones quedan definidas por las
posibles excepciones.
ejecuciones de los métodos commit y rollback. Una transacción abarca
desde el último commit o rollback hasta el siguiente commit. Los /*Añadir imagen
métodos commit o rollback forman parte de la clase Connection.
El bloque de instrucciones del try es el que se ejecuta, y si en él
En la siguiente porción de código de un procedimiento ocurre un error que dispara una excepción, entonces se mira si es
almacenado, puedes ver un ejemplo sencillo de cómo se puede de tipo fichero no encontrado; si es así, se ejecutarían las
utilizar commit y rollback: tras las operaciones se realiza el commit, y si instrucciones del bloque del fichero no encontrado. Si no era de ese
ocurre una excepción, al capturarla realizaríamos el rollback. tipo la excepción, se mira si es del siguiente tipo, o sea, de entrada
salida, y así sucesivamente.

Las instrucciones que hay en el bloque del finally, se ejecutarán


siempre, se haya producido una excepción o no, ahí suelen ponerse
instrucciones de limpieza, de cierre de conexiones, etc.

Las acciones que se realizan sobre una base de datos pueden lanzar
la excepción SQLException. Este tipo de excepción proporciona entre
otra información:

 Una cadena de caracteres describiendo el error. Se


obtiene con el método getMesage.
 Un código entero de error que especifica al fabricante de
la base de datos.
Es conveniente planificar bien la aplicación para minimizar el
tiempo en el que se tengan transacciones abiertas ejecutándose, ya
que consumen recursos y suponen bloqueos en la base de datos que Para saber más
puede parar otras transacciones. En muchos casos, un diseño
cuidadoso puede evitar usos innecesarios que se salgan del modo Resumen
estándar AutoCommit.

8.2. Cierre de conexiones


8.Excepciones y cierre Como ya hemos dicho, al trabajar con bases de datos, se consumen
muchos recursos por parte del sistema gestor, así como del resto de
de conexiones la aplicación.

Por esta razón, resulta totalmente conveniente cerrarlas con el


Debemos tener en cuenta siempre que las conexiones con una base método close cuando ya no se utilizan.
de datos consumen muchos recursos en el sistema gestor, y por lo
tanto en el sistema informático en general. Por ello, conviene Podríamos por tanto tener un ejemplo de cómo hacer esto:
cerrarlas con el método close siempre que vayan a dejar de ser
/*Añadir imagen
utilizadas, en lugar de esperar a que el garbage collector de Java las
elimine.
Tema 4. Mapeo objeto relacional
Ya hemos dicho que las herramientas ORM se utilizan para dar
1. Concepto de Mapeo solución al problema de que, en la programación orientada a
objetos, la gestión de datos se implementa usando objetos; sin
objeto-relacional embargo, en los sistemas de gestión de bases de datos SQL sólo se
pueden almacenar y manipular valores escalares organizados en
tablas relacionales.
A la hora de almacenar los datos de un programa orientado a
objetos en una base de datos relacional, surge un inconveniente Object Relational Mapping (ORM) es la herramienta que nos sirve
debido a incompatibilidad de sistemas de tipo de datos. En el para transformar representaciones de datos de los Sistemas de
software orientado a objetos, la información se representa como Bases de Datos Relacionales, a representaciones (Modelos) de
clases y objetos. En las bases de datos relacionales, como tablas y objetos. Dado a que los RDBMS carecen de la flexibilidad para
sus restricciones. Por tanto, para almacenar la información tratada representar datos no escalares, la existencia de un ORM es
en un programa orientado a objetos en una base de datos relacional fundamental para el desarrollo de sistemas de software robustos y
es necesaria una traducción entre ambas formas. escalables.

El mapeo objeto-relacional (ORM) soluciona este problema. Es En el modelo relacional, cada fila en la tabla se mapea a un objeto
una técnica de programación que se utiliza con el propósito de y cada columna a una propiedad.
convertir datos entre el utilizado en un lenguaje de programación
orientado a objetos y el utilizado en una base de datos relacional, Las herramientas ORM pues, actúan como un puente que conecta
gracias a la persistencia. Esto posibilita el uso en las bases de datos las ventajas de los RDBMS con la buena representación de estos en
relacionales de las características propias de la programación un lenguaje Orientado a Objetos, o, dicho en otras palabras, nos
orientada a objetos (básicamente herencia y polimorfismo). lleva de la base de datos al lenguaje de programación.

La mayoría de las aplicaciones se construyen usando técnicas de En el siguiente documento podrás ver un adelanto de los siguientes
programación orientada a objetos; sin embargo, los sistemas de puntos de la unidad:
bases de datos más extendidos son de tipo relacional.
/* Añadir imagen
Las bases de datos más extendidas son del tipo relacional y estas
sólo permiten guardar tipos de datos primitivos (enteros, cadenas
de texto, etc.) por lo que no se puede guardar de forma directa los
objetos de la aplicación en las tablas. Por tanto, se debe convertir
los valores de los objetos en valores simples que puedan ser
2.1. Características
Las herramientas ORM facilitan el mapeo de atributos entre una
almacenados en una base de datos (y poder recuperarlos más base de datos relacional y el modelo de objetos de una aplicación,
tarde). mediante archivos declarativos (XML) que permiten establecer
estas relaciones. Gracias a las ORM, podemos conectar con una
El mapeo objeto-relacional surge, pues, para dar respuesta a esta
problemática: traducir los objetos a formas que puedan ser base de datos relacional para extraer la información contenida en
objetos de programas que están almacenados. Para ello, sólo
almacenadas en bases de datos preservando las propiedades de los
objetos y sus relaciones; estos objetos se dice entonces que son tendremos que definir la forma en la que establecer la
correspondencia entre las clases y las tablas una sola vez
persistentes.
(indicando qué propiedad se corresponde con cada columna, qué
/* Añadir imagen clase con cada tabla, etc.). Una vez hecho esto, podremos utilizar
POJO's de nuestra aplicación e indicar a la ORM que los haga
El ORM se encarga, de forma automática, de convertir los objetos persistentes, consiguiendo que una sola herramienta pueda leer o
en registros y viceversa, simulando así tener una base de datos escribir en la base de datos utilizando VO's directamente.
orientada a objetos.
Una herramienta ORM permite tomar un objeto Java y hacerlo
persistente, carga el objeto de la base de datos a memoria y permite
hacer consultas a las tablas de la base de datos.
2. Herramientas ORM. Ventajas de ORM.

Características y  Ayudan a reducir el tiempo de desarrollo de software. La


mayoría de las herramientas ORM disponibles, permiten

herramientas más la creación del modelo a través del esquema de la base de


datos, es decir, el usuario crea la base de datos y la
herramienta automáticamente lee el esquema de tablas y
utilizadas 
relaciones y crea un modelo ajustado.
Abstracción de la base de datos.
 Reutilización.
 Permiten persistir objetos a través de un método Orm.Save
y generar el SQL correspondiente.
 Permiten recuperar los objetos persistidos a través de un
método Orm.Load. 3.Instalación y
 Lenguaje propio para realizar las consultas.
 Independencia de la base de datos. configuración de
 Incentivan la portabilidad y escalabilidad de los
programas de software. Hibernate
Desventajas de ORM.
La instalación de Hibernate sobre el IDE NetBeans requiere tener
 Tiempo utilizado en el aprendizaje. Este tipo de instalado previamente este entorno de desarrollo, junto al JDK
herramientas suelen ser complejas por lo que su correcta
utilización lleva un tiempo que hay que emplear en ver el Una vez que inicializamos NetBeans, podemos encontrar la
funcionamiento correcto y ver todo el partido que se le herramienta Hibernate como un plugin de este entorno de
puede sacar. desarrollo. Lo único que tienes que hacer es ir a la lista de plugins
 Menor rendimiento (aplicaciones algo más lentas). Esto de NetBeans y comprobar que lo tienes instalado; en caso
es debido a que todas las consultas que se hagan sobre la contrario, deberás instalarlo desde la opción de plugins disponibles
base de datos, el sistema primero deberá de Para utilizar Hibernate en una aplicación, es necesario conocer
transformarlas al lenguaje propio de la herramienta, cómo configurarlo.
luego leer los registros y por último crear los objetos.
 Sistemas complejos. Normalmente la utilidad de ORM Hibernate puede configurarse y ejecutarse en la mayoría de
desciende con la mayor complejidad del sistema aplicaciones Java y entornos de desarrollo. El archivo de
relacional. configuración de Hibernate recibe el nombre de Hibernate.cfg.xml
y contiene información sobre la conexión de la base de datos y
/* Añadir imagen otras propiedades. Al crearlo, hay que especificar la conexión a la
base de datos.

En los siguientes puntos del tema veremos más detenidamente el


2.2. Herramientas ORM proceso de configuración.

más utilizadas /* Añadir imagen

Entre las herramientasORM más relevantes encontramos las


siguientes:

Hibernate: 4. Ficheros de
Hibernate es una herramienta de Mapeo objeto-relacional (ORM)
para la plataforma Java (y disponible también para .Net con el configuración y mapeo.
nombre de NHibernate) que facilita el mapeo de atributos entre una
base de datos relacional tradicional y el modelo de objetos de una
aplicación. Utiliza archivos declarativos (XML) o anotaciones en
Estructura y
los beans de las entidades que permiten establecer estas relaciones.
propiedades
Hibernate es software libre, distribuido bajo los términos de la
licencia GNU LGPL Para empezar a trabajar con Hibernate es necesario configurar la
herramienta para que conozca qué objetos debe recuperar de la
Java Persistence Api (JPA): base de datos relacional y en qué lugar los hará persistir. Por tanto,
el primer paso será tener una base de datos relacional con la que
El Java Persistence API (JPA) es una especificación de Sun
poder trabajar.
Microsystems para la persistencia de objetos Java a cualquier base
de datos relacional. Esta API fue desarrollada para la plataforma Debes conocer
JEE e incluida en el estándar de EJB 3.0, formando parte de la Java
Specification Request JSR 220. /* Imágenes

Para su utilización, JPA requiere de J2SE 1.5 (también conocida En NetBeans, cuando se crea el archivo de configuración de
como Java 5) o superior, ya que hace uso intensivo de las nuevas Hibernate usando el asistente, podemos especificar la conexión a la
características de lenguaje Java, como las anotaciones y los base de datos, eligiendo de una lista de conexiones de bases de
genéricos. datos registradas en el IDE. Cuando se genera el archivo de
configuración, el IDE añade de forma automática detalles de la
iBatis: conexión e información basada en la conexión de la base de datos
seleccionada. El IDE añade también las bibliotecas de Hibernate en
iBatis es un framework (marca de trabajo) de persistencia
el proyecto. Después de crear el fichero de configuración, éste
desarrollado por la Apache software Foundation. Al igual que que
puede ser editado usando el editor interactivo, o editar directamente
el resto de los proyectos desarrollados por la ASF, iBatis es una
el código XML.
herramienta de código libre y de código abierto.
El fichero de configuración contiene información sobre la base de
iBatis sigue el mismo esquema de uso que Hibernate; se apoya en
datos a la que vamos a conectar la aplicación. Si la aplicación se va
ficheros de mapeo XML para persistir la información contenida en
a conectar a varias bases de datos, sería necesario definir tantos
los objetos en un repositorio relacional.
archivos de configuración como bases de datos a las que nos  Hibernate.show_sql.Para mostrar la herramienta. Por
queramos conectar. defecto, su valor es true.

Para tener toda esta información, en Hibernate surgen dos ficheros


distintos:

 El archivo de propiedades de Hibernate 4.2. Ficheros de mapeo.


(Hibernate.properties), que es el encargado de determinar
todos los aspectos relacionados con el gestor de la base Estructura, elementos y
de datos y las conexiones con él.
 Los archivos que definen el emparejamiento (mapping) propiedades
de propiedades con tablas y columnas (*.hbm.xml). Hibernate utiliza ficheros de mapeo para relacionar tablas con
objetos Java, estos ficheros están en formato XML y que tienen
/*Añadir imagen
extensión .hbm.xml.
Para utilizar Hibernate necesitamos tener una base de datos Hibernate-mapping:
Todos los ficheros de mapeo comienzan y acaban
relacional instalada en NetBeans. La base de datos Sakila es una con esta etiqueta. Al comienzo indicamos en el atributo package el
muestra gratuita disponible, como plugin, en NetBeans. paquete Java donde se encuentra la clase.
La seleccionamos desde la lista de plugins disponibles y la Los archivos de mapeo indican la correspondencia entre el bean y
instalamos en nuestro IDE. una tabla de la base datos; por tanto, en el momento en que se
inicie una tarea que requiera el acceso a la base de datos se
Como ya se ha visto, tras instalar el plugin podemos crear la base obtendrá una conexión JDBC.
de datos Sakila desde la ventana Servicios de NetBeans. Para ello,
seleccionaremos el servidor de MySQL y a continuación esta base A los archivos de mapeo se les asigna el nombre de la Clase
de datos. Conectaremos con ella para poder tenerla disponible seguido de la extensión "hbm.xml".
cuando empecemos a extraer la información que se nos pida.
Podemos utilizar la ingeniería inversa para crear archivos de mapeo
basados en tablas de la base de datos que seleccionemos. El archivo
de ingeniería inversa es Hibernate.reveng.xml. Se trata de un archivo

4.1. Ficheros de XML que se puede utilizar para modificar la configuración


predeterminada de Hibernate.cfg.xml con el propósito de especificar

configuración. explícitamente el esquema de base de datos que se va a utilizar,


filtrar las tablas que no deseamos recuperar y especificar cómo se

Propiedades asignan los tipos JDBC a los tipos de Hibernate.

El archivo de configuración de Hibernate es el Hibernate.cfg.xml y Para extraer un tabla concreta de la base de datos, la sintaxis en el
contiene información sobre la conexión de base de datos, las mapeo requiere definir el POJO Nombre_Clase.hbm.xml, donde
asignaciones de recursos y otras propiedades de conexión. nombre_clase se corresponderá con el nombre la tabla que
queremos extraer y donde se describe cómo se relacionan clases y
tablas y propiedades y columnas.
Debes conocer Mediante el asistente de NetBeans, seleccionamos Nuevo Mapeo
Resumen en Hibernate y rellenamos los campos que nos piden, en función de
la información que nos interese extraer de la base de datos.

De esta manera, NetBeans genera un POJO nombre_clase.java (siendo


Al seleccionar una conexión a una base de datos en NetBeans, se nombre_clase aquella tabla cuya información nos interesa extraer
crea un archivo de configuración en Hibernate que guarda los de la base de datos) con todos los campos necesarios.
detalles de esa conexión. NetBeans también añade de forma
automática la biblioteca de Hibernate para la ruta de clase que Con ello, genera un fichero de mapeo de Hibernate, agregando su
tendrá nuestro proyecto. Después de la creación del archivo entrada a Hibernate.cfg.xml, entre las etiquetas.
Hibernate.cfg.xml, podemos editarlo o modificar el código xml
Debes conocer
mediante el editor xml.
/* Añadir imagen
/* Añadir imagen

Las propiedades más importantes del fichero Hibernate.cfg.xml son:

 Hibernate.dialect:
ejemplo, MySQL.
Dialecto o lenguaje empleado. Por 5.Mapeo de colecciones,
 Hibernate.connection.driver_class . Driver utilizado para la
conexión con la base de datos. relaciones y herencia
 Hibernate.connection.url. Dirección de la base de datos con la
que se va a conectar Hibernate. 1. Mapeo de colecciones.
 Hibernate.connection.username. Nombre del usuario que va a
Hay bastantes rangos de mapeos que se pueden generar para
realizar la extracción de información. Por defecto, el
colecciones que cubran diversos modelos relacionales.
nombre de usuario es root.
 Hibernate.connection.password . Contraseña el root. El elemento de mapeo de Hibernate utilizado para mapear una
colección depende del tipo de la interfaz; por ejemplo, un elemento
se utiliza para mapear propiedades de tipo Set aunque, no obstante, JDO permite a los programadores convertir sus clases en
existen además los elementos de mapeo etc. persistentes, de forma que los objetos pertenecientes a clases
concretas definidas por el programador pueden mantener su
Las instancias de colección de distinguen por la clave foránea de la estado, con la única limitación de que el estado esté compuesto por
entidad que posee la colección. El elemento mapea la columna los atributos persistentes que sean independientes del contexto de
clave de la colección. ejecución: tipos primitivos, tipos de referencia e interfaz y algunas
clases del sistema que permiten modelar el estado como por
Hay que resaltar que las colecciones pueden contener casi
ejemplo la clase Array, Date, etc.
cualquier tipo de datos; esto implica que un objeto en una
colección puede ser manejado con una semántica de "valor" o Para poder indicar las clases y atributos que son persistentes, se
podría ser una referencia a otra entidad, con su propio ciclo de utiliza un fichero de configuración XML, que se denomina
vida. Todos los mapeos de colección necesitan una columna índice descriptor de persistencia. Para que las instancias de las clases
en la tabla de colección: una columna índice es una columna que persistentes pueden mantenerse en los sistemas gestores de bases
mapea a un índice de array o índice de List. Por último, una de datos, es necesario establecer la correspondencia entre los
colección de valores o asociación muchos-a-muchos requiere una objetos y su estado persistente.
tabla de colección dedicada con una columna o columnas de clave
foránea, columna de elemento de colección y probablemente una o
varias columnas índice.

2. Mapeo de relaciones. 7.Sesiones; estados de un


Para persistir, las relaciones usan las denominadas transacciones,
ya que los cambios pueden incluir varias tablas. Una regla general objeto
para el mapeo es respetar el tipo de relación en el modelo de
objetos y en el modelo relacional: así, una relación 1-1 en el Para poder utilizar la persistencia en Hibernate es necesario definir
modelo de objetos deberá corresponderse a una relación 1-1 en el un objeto Session utilizando la clase SesssionFactory. La sesión
modelo relacional. corresponde con un objeto que representa una unidad de trabajo
con la base de datos. La sesión nos permite representar el gestor de
Para mapear las relaciones, se usan los identificadores de objetos persistencia, ya que dispone de una API básica que nos permite
(OID). Son la llave primaria de la tabla relacionada y se agregan cargar y guardar objetos.
como una columna más en la tabla donde se quiere establecer la
relación. Dicha columna es una clave foránea a la tabla con la que La sesión está formada internamente por una cola de sentencias
está relacionada. SQL que son necesarias ejecutar para poder sincronizar el estado
de la sesión con la base de datos.
3. Mapeo de herencia.
Asimismo, la sesión contiene una lista de objetos persistentes. Una
Como hemos comentado, las colecciones funcionan en ambos sesión corresponde con el primer nivel de caché.
modelos, objeto y relacional. Para el caso de la herencia se presenta
el problema que las base de datos relacionales no la soportan. Así Si para realizar el acceso a datos, usamos Hibernate, la sesión nos
es que somos nosotros quienes debemos modelar como se verá la permite definir el alcance de un contexto determinado. Para poder
herencia en el modelo relacional. Existen tres tipos de mapeos utilizar los mecanismos de persistencia de Hibernate se debe
principales: modelar la jerarquía a una sola tabla, modelar la inicializar el entorno Hibernate y obtener un objeto Session
jerarquía completa en tablas, mapear cada tabla en tablas concretas. utilizando la clase SessionFactory de Hibernate. Un objeto Session
La decisión estará basada en el rendimiento y en la escalabilidad Hibernate representa una única unidad-de-trabajo para un almacén
del modelo. de datos dado y lo abre un ejemplar de SessionFactory. Se deben
cerrar las sesiones cuando se haya completado todo el trabajo de
una transacción.

6.Clases persistentes Los estados en los que se puede encontrar un objetos son:

 Transitorio (Transient). En este estado estará un objeto


Se denomina "persistencia" de los objetos a su capacidad para recién creado que no ha sido enlazado con el gestor de
guardarse y recuperarse desde un medio de almacenamiento. Las persistencia.
clases persistente son clases en una aplicación que nos van a servir  Persistente: Ente este caso el objeto está enlazado con la
para representar entidades de la base de datos. No se considera que sesión. Todos los cambios que se realicen será
todas las instancias de una clase persistente puedan estar en estado persistentes.
persistente, ya que una instancia puede ser transitorio o separada.  Disociado (Detached): En este caso nos encontramos con
un objeto persistente que sigue en memoria después de
El estándar Java Data Objects (JDO), define una clase con que termine la sesión. En este caso existe en Java y en la
capacidad de persistencia, como aquella que implementa la base de datos.
interaface javax.jdo.PersistenceCapable.  Borrado (Removed): En este caso el objeto está marcado
para ser borrado de la base de datos. Existe en la
Las clases persistentes tienen la capacidad de definir objetos que
aplicación Java y se borrará de la base de datos al
pueden almacenarse y recuperarse y un almacén persistente de
terminar la sesión.
datos. La especificación JDO incorpora la figura del procesador de
clases en código ejecutable Java, JDO Enhacer, que es un programa
que modifica los archivos compilados de las clases, añadiendo el
código ejecutable necesario para realizar la grabación y
recuperación transparente de los atributos de las instancias
persistentes.
Los objetos cargados, grabados, creados o consultados por la
8. Carga, sesión pueden ser manipulados por la aplicación, y cualquier
cambio a su estado de persistencia será persistido cuando se le
almacenamiento y aplique "flush" a la sesión.

No hay que invocar ningún método en particular para que las


modificación de modificaciones se vuelvan persistentes. Así que la manera más
sencilla y directa de actualizar el estado de un objeto es cargarlo

objetos. con load(), y luego manipularlo directamente, mientras la sesión


esté abierta.

Para cargar un objeto de acceso a datos en la aplicación Java, el Para borrar objetos persistentes, podemos ejecutar Session.delete(), que
método load() de la clase Session suministra un mecanismo para quitará el estado de un objeto de la base de datos. Por supuesto, su
capturar una instancia persistente, si conocemos su identificador. El aplicación podría aún contener una referencia al objeto quitado. Se
método load() acepta un objeto Class, y cargará el estado de una puede borrar objetos en cualquier orden, no se van a producir
nueva instancia de esa clase, inicializada en estado persistente. violaciones de llave externa, pero sí es posible violar constraints NOT
NULL aplicadas a la columna de llave externa.
El método load() lanzará una excepción irrecuperable si no existe la
fila de base de datos correspondiente. Si no se está seguro de que Muchas aplicaciones necesitan capturar un objeto en una
exista una fila correspondiente, debe usarse el método get(), el cual transacción, mandarlo a la capa de interfaz de usuario para su
consulta la base de datos inmediatamente y devuelve null si no manipulación, y grabar sus cambios en una nueva transacción. Las
existe una fila correspondiente aplicaciones que usan este tipo de estrategia en entornos de alta
concurrencia, normalmente usan datos versionados para garantizar
Existen dos métodos que se encargan de recuperar un objeto aislamiento durante la "larga" unidad de trabajo.
persistente por identificador: load() y get(). La diferencia entre ellos
radica en cómo indican que un objeto no se encuentra en la base de Hibernate soporta este modelo, proveyendo "reasociación" de
datos: get() devuelve un nulo y load() lanza una excepción entidades desprendidas usando los métodos Session.update() o
ObjectNotFoundException . Session.merge().

Aparte de esta diferencia, load() intenta devolver un objeto proxy


siempre y cuando le sea posible (no esté en el contexto de
persistencia). Con lo que es posible que la excepción sea lanzada
cuando se inicialice el objeto proxy. Esto es conocido como carga
9.Consultas SQL
perezosa.
Usando Hibernate, la ejecución de consultas SQL nativas se
En el caso que se obtenga un proxy, no tiene impacto sobre la base controla por medio de la interfaz SQLQuery, la cual se obtiene
de datos (no se ejecuta ninguna consulta), hasta que no se inicializa llamando a Session.createSQLQuery(). Las siguientes secciones
el mismo. Muy útil cuando se obtiene una referencia de un objeto describen cómo utilizar esta API para consultas
para asociarlo a otro. (No es necesario obtener el objeto). Se
La consulta SQL más básica es para obtener a una lista de escalares
modifica un objeto persistente.
(valores).
/*Añadir imagen
 sess.createSQLQuery("SELECT * FROM
Personas").list();
 sess.createSQLQuery("SELECT ID,NOMBRE, EDAD

8.1. Almacenamiento y FROM PERSONAS").list();

Estas retornarán una lista de objetos arrays ( Object[]) con valores


modificando de objetos escalares para cada columna en la tabla PERSONAS. Hibernate
utilizará ResultSetMetadata para deducir el orden real y los tipos de los
persistentes valores escalares retornados.
Para almacenar objetos persistentes se proceso siguiendo los
Otro tipo de consulta más compleja es la consulta de entidades.
siguientes pasos:
Para obtener los objetos entidades desde una consulta sql nativa, se
1. Se instancia un objeto nuevo (estado transitorio). utiliza por medio de addEntity().
2. Se obtiene una sesión y se comienza la transacción,
 sess.createSQLQuery("SELECT * FROM
inicializando el contexto de persistencia.
PERSONAS").addEntity(Persona.class);
3. Una vez obtenida da la sesión, se llama al método save(),
el cual introduce el objeto en el contexto de persistencia.  sess.createSQLQuery("SELECT ID,NOMBRE,EDAD
Este método devuelve el identificador del objeto FROM PERSONAS").addEntity(Persona.class);
persistido. Se especifica esta consulta:
4. Para que los cambios sean sincronizados en las bases de
datos, es necesario realizar el commit de la transacción.  La cadena de consulta SQL.
Dentro del objeto sesión se llama al método flush(). Es  La entidad devuelta por la consulta.
posible llamarlo explícitamente. En este momento, se
obtiene la conexión JDBC a la bases de datos para poder Asumiendo que Persona es mapeado como una clase con las
ejecutar la oportuna sentencia. columnas IDENTIFICACION, NOMBRE y FECHA DE
5. Finalmente, la sesión se cierra, con el objeto de liberar el NACIMIENTO las consultas anteriores devolverán una Lista en
contexto de persistencia, y por tanto, devolver la donde cada elemento es una entidad Persona.
referencia del objeto creado al estado disociado.
10. Lenguajes propios from Alumnos where nombre='Francisco'.

Si existe un alias, usaremos un nombre de propiedad calificado:


de la herramienta ORM from Alumnos as alumnos where alumnos.nombre='Francisco'.

Hibernate utiliza un lenguaje de consulta potente (HQL) que se Esto retorna instancias de Alumnos llamados "Francisco".
parece a SQL. Sin embargo, comparado con SQL, HQL es
completamente orientado a objetos y comprende nociones como Funciones de agregación. Las consultas HQL pueden retornar
herencia, polimorfismo y asociación. Las consultas se escriben en resultados de funciones de agregación sobre propiedades:
HQL y Hibernate se encarga de convertirlas al SQL usado por la
base de datos con la que estemos trabajando y ejecutarla para select avg(alumnos.nota), sum(alumnos.nota), max(alumnos.nota),
realizar la operación indicada. count(alumnos) from Alumnos alumnos.

HQL es case-insensitive, o sea que sus sentencias pueden escribirse Expresiones. Las expresiones utilizadas en la cláusula where
en mayúsculas y minúsculas. Por lo tanto "SeLeCt", "seleCT", incluyen lo siguiente: operadores matemáticos, operadores de
"select", y "SELECT" se entienden como la misma cosa. Lo único comparación binarios, operadores lógicos, paréntesis () que indican
con lo que debemos tener cuidado es con los nombres de las clases agrupación, funciones Java, etc.
que estamos recuperando y con sus propiedades, ahí si se
La cláusula order by. La lista retornada por una consulta se puede
distinguen mayúsculas y minúsculas. O sea, en este caso
ordenar por cualquier propiedad de una clase retornada o
"pruebas.Hibernate.Usuario" NO ES LO MISMO que
componentes. La palabra asc o desc opcionales indican ordenamiento
"PrueBAs.Hibernate.UsuArio".
ascendente o descendente respectivamente.
Entre las características más importantes de HQL.
La cláusula group by. Una consulta que retorna valores agregados
 Soporte completo para operaciones relacionales: HQL se puede agrupar por cualquier propiedad de una clase retornada o
permite representar consultas SQL en forma de objetos. componentes:
HQL usa clases y atributos o propiedades en vez de
Subconsultas. Para bases de datos que soportan subconsultas,
tablas y columnas.
Hibernate soporta subconsultas dentro de consultas. Una
 Regresa sus resultados en forma de objetos: Las subconsulta se debe encerrar entre paréntesis (frecuentemente por
consultas realizadas usando HQL regresan los resultados una llamada a una función de agregación SQL). Incluso se
de las mismas en la forma de objetos o listas de objetos, permiten subconsultas correlacionadas (subconsultas que se
que son más fáciles de usar. refieren a un alias en la consulta exterior).
 Consultas Polimórficas: Podemos declarar el resultado
usando el tipo de la superclase e Hibernate se encargara
de crear los objetos adecuados de las subclases correctas
de forma automática. 12. Gestión de transacciones
 Soporte para características avanzadas: HQL contiene Una transacción es un conjunto de órdenes que se ejecutan
muchas características avanzadas que son muy útiles y formando una unidad de trabajo, en forma indivisible o atómica.
que no siempre están presentes en todas las bases de
datos, o no es fácil usarlas, como paginación, fetch joins Para la gestión de transacciones en Hibernate, no se produce
con perfiles dinámicos, inner y outer joins, etc. Además bloqueo de objetos en la memoria. La aplicación puede esperar el
soporta proyecciones, funciones de agregación (max, comportamiento definido por el nivel de aislamiento de sus
avg), y agrupamientos, ordenamientos, y subconsultas. transacciones de las bases de datos. Gracias a la Session, la cual
 Independiente del manejador de base de datos: Las también es un caché con alcance de transacción. Para realizar con
consultas escritas en HQL son independientes de la base éxito la gestión de transacciones, éstas se van a basar en el uso del
de datos (siempre que la base de datos soporte la objeto Session.
característica que estamos intentando utilizar)
El objeto Session se obtiene a partir de un objeto SessionFactory,
invocando el método openSession. Un objeto SessionFactory
representa una configuración particular de un conjunto de
10.1. Lenguaje HQL metadatos de mapping objeto/relaciona.

Clausula from: La consulta más simple que se puede realizar con


Hibernate, es utilizando la cláusula from, la siguiente sería una
consulta que mostraría todos los datos de una tabla de nombre
Alumnos:

from Alumnos

Cláusula select: La cláusula select escoge qué objetos y


propiedades devolver en el conjunto de resultados de la consulta.
Un ejemplo de consulta podría ser:

select alumno.nombre from Alumnos alumno where


alumno.nombre like 'A%'

La cláusula where: La cláusula where nos permite refinar la lista de


instancias retornadas. Si no existe ningún alias, puede referirse a
las propiedades por nombre:
Cuando se crea el objeto Session , se le asigna la conexión de la base
de datos que va a utilizar. Una vez obtenido el objeto Session, se
crea una nueva unidad de trabajo ( Transaction) utilizando el
método beginTransaction. Dentro del contexto de la transacción
creada, se pueden invocarlos métodos de gestión de persistencia
proporcionados por el objeto Session, para recuperar, añadir,
eliminar o modificar el estado de instancias de clases persistentes.
También se pueden realizar consultas. Si las operaciones de
persistencia no han producido ninguna excepción, se invoca el
método commit de la unidad de trabajo para confirmar los cambios
realizados. En caso contrario, se realiza un rollback para deshacer los
cambios producidos. Sobre un mismo objeto Session pueden
crearse varias unidades de trabajo. Finalmente se cierra el objeto
Session invocando su método close.
Tema 5. Bases de datos objeto-
relacionales y orientadas a objetos
mapeo de objetos subyacente, que es costoso y poco flexible,
1. Introducción cuando los objetos y sus interacciones son complejos.

Las Bases de Datos Relacionales (BDR) son ideales para


aplicaciones tradicionales que soportan tareas administrativas, y
que trabajan con datos de estructuras simples y poco cambiantes,
incluso cuando la aplicación pueda estar desarrolla en un lenguaje
2. Características de
OO y sea necesario un Mapeo Objeto Relacional (ORM)

Pero cuando la aplicación requiere otras necesidades, como por


las bases de datos
ejemplo, soporte multimedia, almacenar objetos muy cambiantes y
complejos en estructura y relaciones, este tipo de base de datos no
orientadas a objetos
son las más adecuadas.
En una BDOO, los datos se almacenan como objetos. Un objeto es,
Recuerda, que si queremos representar un objeto y sus relaciones al igual que en POO, una entidad que se puede identificar
en una BDR esto implica que: unívocamente y que describe tanto el estado como el
comportamiento de una entidad del 'mundo real'. El estado de un
 Los objetos deben ser descompuestos en diferentes objeto se describe mediante atributos y su comportamiento es
tablas. definido mediante procedimientos o métodos. Entonces, ¿a qué
 A mayor complejidad, mayor número de tablas, de equivalen las entidades, ocurrencias de entidades y relaciones del
manera que se requieren muchos enlaces (joins) para modelo relacional? Las entidades son las clases, las ocurrencias de
recuperar un objeto, lo cual disminuye dramáticamente el entidad son objetos creados desde las clases, las relaciones se
rendimiento. mantienen por medio de inclusión lógica, y no existen claves
primarias, los objetos tienen un identificador.
Las Bases de Datos Orientadas a Objetos (BDOO) o Bases de
Objetos se integran directamente y sin problemas con las La principal característica de las BDOO es que soportan un
aplicaciones desarrolladas en lenguajes orientados a objetos, ya que modelo de objetos puro y que el lenguaje de programación y el
soportan un modelo de objetos puro y son ideales para esquema de la base de datos utilizan las mismas definiciones de
almacenar y recuperar datos complejos permitiendo a los usuarios tipos.
su navegación directa (sin un mapeo entre distintas
representaciones). Otras características importantes de las BDOO son las
siguientes:
Las Bases de Objetos aparecieron a finales de los años 80
motivadas fundamentalmente por dos razones:  Soportan las características propias de la Orientación
a Objetos como agregación, encapsulamiento,
 Las necesidades de los lenguajes de Bases de Datos polimorfismo y herencia. La herencia se mantiene en la
Orientadas a Objetos (POO), como la necesidad de propia base de datos.
persistir objetos.  Identificador de objeto (OID). Cada objeto tiene un
 Las limitaciones de las bases de datos relacionales, como identificador, generado por el sistema, que es único para
el hecho de que sólo manejan estructuras muy simples cada objeto, lo que supone que cada vez que se necesite
(tablas) y tienen poca riqueza semántica modificar un objeto, habrá que recuperarlo de la base de
datos, hacer los cambios y almacenarlo nuevamente. Los
Pero como las BDOO no terminaban de asentarse, debido OID son independientes del contenido del objeto, esto es,
fundamentalmente a la inexistencia de un estándar, y las BDR si cambia su información, el objeto sigue teniendo el
gozaban y gozan en la actualidad de una gran aceptación, mismo OID. Dos objetos serán equivalentes si tienen la
experiencia y difusión, debido fundamentalmente a su gran misma información, pero diferentes OID.
robustez y al lenguaje SQL, los fabricantes de bases de datos  Jerarquía y extensión de tipos. Se pueden definir
comenzaron e implementar nuevas funcionalidades orientadas a nuevos tipos basándose en otros tipos predefinidos,
objetos en las BDR existentes. Así surgieron, las bases de datos cargándolos en una jerarquía de tipos (o jerarquía de
objeto-relacionales. clases). Objetos complejos. Los objetos pueden tener una
Las Bases de Datos Objeto-Relacionales (BDOR) son bases de estructura de objeto de complejidad arbitraria, a fin de
datos relacionales que han evolucionado hacia una base de datos contener toda la información necesaria que describe el
más extensa y compleja, incorporando conceptos del modelo objeto.
orientado a objetos. Pero en estas bases de datos aún existe un  Acceso navegacional de datos. Cuando los datos se
almacenan en una estructura de red densa y
probablemente con una estructura de diferentes niveles  Carencia de un modelo de datos universal. No hay
de profundidad, el acceso a datos se hace principalmente ningún modelo de datos aceptado universalmente, y la
navegando la estructura de objetos y se expresa de forma mayor parte de los modelos carecen de una base teórica.
natural utilizando las construcciones nativas del lenguaje,  Falta de estándares. Existe una carencia de estándares
sin necesidad de uniones o joins típicas en las BDR. general para los sistemas de BDOO.
 Gestión de versiones. El mismo objeto puede estar  Complejidad. La estructura de una BDOO es más
representado por múltiples versiones. Muchas compleja y difícil de entender que la de una BDR.
aplicaciones de bases de datos que usan orientación a  Competencia de otros modelos. Las bases de datos
objetos requieren la existencia de varias versiones del relacionales y objeto-relacionales están muy asentadas y
mismo objeto, ya que, si estando la aplicación en extendidas, siendo un duro competidor.
funcionamiento es necesario modificar alguno de sus  Difícil optimización de consultas. La optimización de
módulos, el diseñador deberá crear una nueva versión de consultas requiere una compresión de la implementación
cada uno de ellos para efectuar cambios. de los objetos, para poder acceder a la base de datos de
manera eficiente. Sin embargo, esto compromete el
concepto de encapsulación.

2.2 Ventajas e inconvenientes


/* Añadir imagen

El uso de una BDOO puede ser ventajoso frente a una BDR


3. Gestores de bases
de datos orientadas a
relacional si nuestra aplicación requiere alguno de estos elementos:

 Un gran número de tipos de datos diferentes.




Un gran número de relaciones entre los objetos.
Objetos con comportamientos complejos.
objetos
Una de las principales ventajas de los sistemas de bases de datos /* Añadir imagen
orientados a objetos es la transparencia, (manipulación directa de
datos utilizando un entorno de programación basado en objetos), Un Sistema Gestor de Bases de Datos Orientada a Objetos
por lo que el programador, solo se debe preocupar de los objetos de (SGBDOO) y en inglés ODBMS, Object Database Management
su aplicación, en lugar de como los debe almacenar y recuperar de System) es un software específico, dedicado a servir de interfaz
un medio físico. entre la base de objetos, el usuario y las aplicaciones que la
utilizan. Un SGBDOO incorpora el paradigma de Orientación a
Otras ventajas de un sistema de bases de datos orientado a objetos Objetos y permite el almacenamiento de objetos en soporte
son las siguientes: secundario:

 Gran capacidad de modelado. El modelado de datos  Por ser SGBD debe incluir mecanismos para optimizar el
orientado a objetos permite modelar el 'mundo real' de acceso, gestionar el control de concurrencia, la seguridad
una manera óptima gracias al encapsulamiento y la y la gestión de usuarios, así como facilitar la consulta y
herencia. recuperación ante fallos.
 Flexibilidad. Permiten una estructura cambiante con solo  Por ser OO incorpora características de identidad,
añadir subclases. encapsulación, herencia, polimorfismo y control de tipos.
 Soporte para el manejo de objetos complejos.
Cuando aparecieron las bases de datos orientadas a objetos, un
Manipula de forma rápida y ágil objetos complejos, ya
grupo formado por desarrolladores y usuarios de bases de objetos,
que la estructura de la base de datos está dada por
denominado ODMG (Object-Oriented Database Management
referencias (apuntadores lógicos) entre objetos.
Group), propuso un estándar que se conoce como estándar
 Alta velocidad de procesamiento. Como el resultado de
ODMG-93 y que se ha ido revisando con el tiempo, pero que en
las consultas son objetos, no hay que reensamblar los
realidad no ha tenido mucho éxito, aunque es un punto de partida.
objetos cada vez que se accede a la base de objetos
 Extensibilidad. Se pueden construir nuevos tipos de Debes conocer
datos a partir de los ya existentes, agrupar propiedades
comunes de diversas clases e incluirlas en una /*Añadir resumen
superclase, lo que reduce la redundancia.
 Mejora los costes de desarrollo, ya que es posible la ¿Qué estrategias o enfoques se siguen para el desarrollo de
reutilización de código, una de las características de los SGBDOO? Básicamente, las siguientes:
lenguajes de programación orientados a objetos.
 Facilitar el control de acceso y concurrencia, puesto  Ampliar un lenguaje de programación OO existente con
que se puede bloquear a ciertos objetos, incluso en una capacidades de BD (Ejemplo: GemStone).
jerarquía completa de objetos.  Proporcionar bibliotecas de clases con las capacidades
 Funcionan de forma eficiente en entornos tradicionales de las bases de datos, como persistencia,
cliente/servidor y arquitecturas distribuidas. transacciones, concurrencia, etc., (Ejemplo: ObjectStore
y Versant).
Pero, aunque los sistemas de bases de datos orientados a objetos  Ampliar un lenguaje de BD con capacidades OO, caso de
pueden proporcionar soluciones apropiadas para muchos tipos de SQL 2003 y Object SQL (OQL, propuesto por ODMG).
aplicaciones avanzadas de bases de datos, también tienen sus
desventajas. Éstas son las siguientes: Tal y como estarás pensando, la carencia de un estándar real hace
difícil el soporte para la portabilidad de aplicaciones y su
interoperabilidad, y es en parte por ello, que a diferencia de las
bases de datos relacionales donde hay muchos productos donde Entonces, ¿las referencias de asociación son como las relaciones
elegir, la variedad de sistemas de bases de datos orientadas a del modelo relacional? Así es:
objetos es mucho menor. En la actualidad hay diferentes productos
de este tipo, tanto con licencia libre como propietaria.  La referencia de asociación representa las relaciones o
interrelaciones entre objetos independientes, dando la
A continuación, te indicamos algunos ejemplos de SGBOO: posibilidad de que los objetos puedan detectarse
mutuamente en una o dos direcciones, (lo que en el
 Db4o de Versant. Es una BDOO Open Source para Java modelo relacional representamos mediante claves ajenas
y .NET. Se distribuye bajo licencia GPL. o foráneas que provienen de relaciones uno a uno, uno a
 Matisse. Es un SGBOO basado en la especificación muchos y muchos a muchos).
ODMG, proporciona lenguajes para definición y  Una relación uno a muchos se representa mediante un
manipulación de objetos, así como interfaces de objeto tipo colección (List, Set, etc.). En una BDOO la
programación para C, C++, Eiffel y Java. colección se maneja como cualquier otro objeto (aunque
 ObjectDB. Es una BDOO que ofrece soporte para Java, potencialmente profundo) y normalmente se podrá
C++, y Python entre otros lenguajes. No es un producto recuperar y almacenar el objeto padre junto con la
libre, aunque ofrecen versiones de prueba durante un colección asociada y su contenido en una sola llamada.
periodo determinado.
 EyeDB. Es un SGBOO basado en la especificación Además, un objeto miembro referenciado puede ser referenciado
ODMG, proporciona lenguajes para definición y por más de un objeto estructurado y, no se elimina
manipulación de objetos, e interfaces de programación automáticamente cuando se elimina el objeto del nivel superior.
para C++ y Java. Se distribuye bajo licencia GNU y es
software libre.
 Neodatis, ObjectStore y GemStone. Son otros SGBDOO.
3.3. Instalación del gestor de
objetos Db4o
3.2. Objetos simples y /* Añadir imagen

objetos estructurados DB4O es un novedoso motor de base de datos orientada a objetos.


Sus siglas se corresponden con la expresión "DataBase 4 (for)
/* Añadir imagen Objects", que a su vez es el nombre de la compañía que lo
desarrolla: db4objects, Inc., disponible para Java y .Net, y utilizada
En las BDOO los objetos se encuentran interrelacionados por en la actualidad por diversas compañías para el desarrollo de
referencias entre ellos de manera similar a como los objetos se aplicaciones de dispositivos móviles, dispositivos médicos y
referencian entre sí en memoria. biotecnología, aplicaciones web, software enlatado y aplicaciones
en tiempo real.
Un objeto de tipo simple u objeto simple es aquel que no contiene
a otros objetos y por tanto posee una estructura de un solo nivel de Tres características importantes de Db4o son las siguientes:
profundidad en este sentido.
 El modelo de clases es el propio esquema de la base de
Un objeto de tipo estructurado u objeto estructurado incluye datos, por lo que se elimina el proceso de diseño,
entre sus componentes a otros objetos y se define aplicando los implementación y mantenimiento de la base de datos.
constructores de tipos disponibles por el SGBDOO recursivamente  Está diseñada bajo la estrategia de proporcionar
a varios niveles de profundidad. bibliotecas de clases con las capacidades tradicionales de
las bases de datos, y con el objetivo de cero
Entre un objeto y sus componentes de cada nivel, existen dos tipos administración.
de referencia:
 Puede trabajar como base de datos embebida, lo que
 Referencia de propiedad. Se aplica cuando los significa que se puede distribuir con la aplicación, y solo
componentes de un objeto se encapsulan dentro del la aplicación que lanza la base de datos embebida puede
propio objeto y se consideran, por tanto, parte de ese acceder a ella, siendo ésta invisible para el usuario final.
objeto. Relación es-parte-de. No necesitan tener La mayor clave del éxito que está teniendo este motor de base de
identificadores de objeto y sólo los métodos de ese objeto datos frente a otros competidores que han desarrollado tecnologías
pueden acceder a ellos. Desaparecen si el propio objeto similares, es que se ha optado por un modelo de licenciamiento
se elimina. idéntico al utilizado por empresas como MySQL: licencia dual
 Referencia de asociación. Se aplica cuando entre los GPL/comercial. Es decir, si se quiere desarrollar software libre con
componentes del objeto estructurado existen objetos esta biblioteca, su uso no conlleva ningún coste por licencia; sin
independientes, pero es posible hacer referencia a ellos embargo si se desea aplicar a un software privativo, se aplica otro
desde el objeto estructurado. Relación está-asociado- modelo de licenciamiento concreto.
con. Cuando un objeto estructurado tiene que acceder a
sus componentes referenciados, lo hace invocando los Actualmente este producto funciona como una biblioteca para dos
métodos apropiados de los componentes, ya que no están tipos de plataformas de desarrollo: Java y.NET (tanto la
encapsulados dentro del objeto estructurado. implementación de Microsoft como la de Mono).

Por ejemplo, si observas la figura superior derecha, en un objeto Una de las ventajas de db4o es que es un simple fichero .jar
tipo Oficina los componentes codigo y dirección son_parte_del distribuible con cualquier aplicación sin necesidad de tener que
objeto, mientras que el componente jefe, es un objeto instalar nada. Tampoco necesita drivers de tipo JDBC o similar.
independiente que está_asociado_con el objeto oficina.
La instalación de db4o consistirá en:
 Instalar el motor de base de datos, que son las clases
necesarias para hacer que funcione la API en toda su


extensión.
Instalar alguna aplicación para visualizar los datos con
3.2 Apertura y cierre de
los que se está trabajando. Esto último es necesario, pues
en otro caso se trabajaría a ciegas con los datos.
conexiones
/*Añadir imagen

En general, la conexión de una aplicación Java con una base de


objetos se podrá realizar vía:
4. El API de la base  JDBC.

de objetos  El API proporcionado por el propio gestor de objetos.

En el caso de Db4o, el paquete com.db4o proporciona las clases e


Todos los SGBDOO, independientemente de su estrategia de interfaces que permiten abrir conexiones a una base de objetos
diseño, proporcionan un API (Interfaz de Programación de db4o, así como el cierre de la misma. Estas son:
Aplicaciones), más o menos extenso, disponible para ciertos
lenguajes OO. En el caso de Db4o, el API está disponible para Java  Abrir conexión. Podemos utilizar las siguientes clases:
y .Net. o Db4oEmbedded. Es una clase que hereda de
java.lang.Object y proporciona métodos estáticos
Los principales paquetes del API de Db4o son los siguientes: como openFile() para abrir una instancia de la
base de datos en modo embebido. En modo
 com.db4o. Paquete principal (core) de la Base de Objetos. embebido tiene la limitación de que sólo se
Las interfaces y clases más importantes que incluye son: puede utilizar en la base de datos una conexión.
o ObjectContainer. Es el interfaz que permite o ObjectServer. Es un interfaz que permite trabajar
realizar las principales tareas con la base de con una base de datos db4o en modo cliente-
objetos. Un ObjectContainer puede representar servidor. Una vez abierta la base de datos
una base de datos independiente (stand- como servidor mediante Db4o.openServer(), el
alone) o una conexión a un servidor (en línea método openClient() del interfaz ObjectServer
cliente-servidor). Este interfaz proporciona permitirá abrir conexiones cliente
métodos para almacenar store(), consultar directamente en memoria o bien mediante
queryByExample() y eliminar delete() objetos de la TCP/IP.
base de datos, así como cerrar la conexión a  Cerrar conexión. Para ello utilizaremos el método close()
ésta close(). También permite confirmar commit y de la interfaz ObjectContainer.
deshacer rollback transacciones.
o EmbeddedObjectContainer. Es un interfaz que El esquema de trabajo para operar con la base de objetos será
extiende a ObjectContainer y representa un el siguiente:
ObjectContainer local atacando a la base de datos.
o Db4oEmbedded. Es una clase que proporciona  Declarar un ObjectContainer.
métodos estáticos para conectar con la base de  Abrir una conexión a la base de objetos ( openFile()). Si al
datos en modo embebido. abrir la BDOO esta no existe, se creará.
o ObjectServer. Es el interfaz que permite trabajar  Realizar operaciones con la base de objetos como
con una base de datos db4o en modo cliente- consultas, borrados y modificaciones (en un bloque try{ }
servidor. catch (){ } ).
o ObjectSet. Es un interfaz que representa el  Cierre o desconexión de la base de objetos (close()).
conjunto de objetos devueltos por una consulta.
En el siguiente recurso didáctico tienes un ejemplo de apertura,
 com.db4o.query. Paquete con funcionalidades de consulta.
creación y cierre a una base de objetos en modo embebido. En la
Proporciona interfaces que permiten establecer las
BDOO creada se almacenan 4 objetos mediante el método store().
condiciones y criterios de una consulta y una clase para
realizar consultas mediante Native Query (Consultas
nativas).
 com.db4o.config. Paquete con funcionalidades de
configuración. Contiene interfaces y clases que nos 3.3 Consultas a la base de
permiten configurar y/o personalizar la base de objetos
según necesiades. La configuración de la base de objetos objetos
se hace por norma general antes de abrir la sesión en la A una BDOO se podrán realizar consultas mediante:
misma.
o EmbeddedConfiguration. Es la interface de  Un lenguaje de consultas como OQL, si el gestor está
configuración para el uso en modo embebido. basado en el estándar ODMG e incluye sentencias del
tipo SQL.
Siempre que trabajemos con bases de objetos Db4o utilizaremos el  El API proporcionado por el propio sistema gestor de
interface ObjectContainer, puesto que es quien representará a la base bases de datos orientadas a objetos.
de objetos, sea embebida o no.
Los tres sistemas de consulta que proporciona Db4o basados en el
La documentación del API viene en formato JavaDoc y la puedes API del propio gestor, son los siguientes:
encontrar en el directorio /doc/api del fichero .zip descargado y
descomprimido.
 Consultas por ejemplo. Query By Example (QBE). Es Los objetos estructurados son objetos que contienen a su vez a
la forma más sencilla y básica de realizar consultas, pero otros objetos (objetos hijo u objetos miembro).
tienen bastantes limitaciones.
En el caso de objetos estructurados se habla de diferentes niveles
 Consultas nativas. Native Queries (NQ). Es la interface
de profundidad del objeto. El nivel más alto, nivel 1, será el que
principal de consultas de la base de objetos. Permiten
corresponde a la definición del objeto estructurado (objeto padre),
realizar un filtro contra todas las instancias de la base de
el siguiente nivel, nivel 2, corresponderá a la definición del objeto
objetos.
hijo y así sucesivamente podrá haber un nivel 3, 4... dependiendo
 Consultas SODA. Simple Object Data Access
de que los objetos hijos a su vez incluyan en su definición a otro u
(SODA). Permite generar consultas dinámicas. Es más
otros objetos miembro.
potente que las anteriores y más rápida puesto que las
anteriores (QBE y NQ) tienen que ser traducidas a En el siguiente ejemplo, definimos la clase charla (objeto
SODA para ejecutarse. estructurado padre) que incorpora a un objeto ponente (objeto
miembro). El nivel más alto de profundidad o nivel 1 es el que
¿En qué consiste cada uno de estos sistemas de consulta?
corresponde a la definición de charla y el nivel 2 corresponderá a la
En el siguiente recurso didáctico encontrarás un resumen y definición del objeto ponente.
ejemplos de estos sistemas de consulta. Los ejemplos se realizan
¿Cómo se almacenan, consultan y actualizan los objetos
sobre la base de objetos Congreso.
estructurados en Db4o?
/* Añadir imagen
 Los objetos estructurados se almacenan asignando
valores con set() y después persistiendo el objeto con
store(). Al almacenar un objeto estructurado del nivel más

3.4 Actualización de objetos alto, se almacenarán de forma implícita todos los objetos
hijo.

simples  Las consultas se realizan por cualquiera de los sistemas


soportados por el gestor y se podrá ir descendiendo por
Recuerda que un objeto simple es un objeto que no contiene a los diferentes niveles de profundidad.
otros objetos, como por ejemplo los objetos de la clase ponente. Un  La eliminación o borrado de un objeto estructurado se
segmento de la definición de esta clase, es la siguiente: realiza mediante el método delete(). Por defecto, no se
eliminarán los objetos miembro. Para eliminar objetos
/* Añadir imagen
estructurados en cascada o de forma recursiva,
Para consultar objetos simples se pueden utilizar cualquiera de los eliminando los objetos miembro, habrá que configurar de
tres sistemas de consulta proporcionados por db4o, tal y como has modo apropiado la base de objetos antes de abrirla,
podido ver en el apartado anterior. mediante el paquete com.db4o.config. En el caso de modo
embebido, se hará mediante la interface
Para modificar objetos almacenados debes seguir los siguientes EmbeddedConfiguration . En la nueva configuración se debe
pasos: indicar cascadeOnDelete(true).
 La modificación se realizará actualizando los nuevos
 Cambiar los valores del objeto con los nuevos valores. valores mediante el método set(). Por defecto las
 Almacenar de nuevo el objeto con el método store() de la modificaciones solo afectan al nivel más alto. Para
interfaz ObjectContainer. actualizar de forma recursiva todos los objetos miembro
habrá que indicar en la configuración cascadeOnUpdate(true).
Por ejemplo, el siguiente método permitirá modificar objetos
ponente, en concreto actualizar el e-mail de ponentes por nif de En este otro enlace dispones de un ejemplo con eliminación y
ponente: modificación de charlas en cascada.
/*Añadir imagen /*Añadir imagen

Db4o necesita conocer previamente un objeto para poder


actualizarlo. Esto significa que para poder ser actualizados los
objetos, éstos deben de haber sido insertados o recuperados en la
misma sesión; en otro caso se añadirá otro objeto en vez de 5. El lenguaje de
actualizarse.

Para eliminar objetos almacenados utilizaremos el método delete()


consulta de objetos
de la interface ObjectContainer .

Por ejemplo, el siguiente método elimina un objeto ponente por su


OQL
nif: OQL (Object Query Languaje) es el lenguaje de consulta de
objetos propuesto en el estándar ODMG.
/*Añadir imagen
Las siguientes son algunas de las características más relevantes
de OQL:

3.5 Actualización de objetos  Es un lenguaje declarativo del tipo de SQL que permite
realizar consultas de modo eficiente sobre bases de datos
estructurados 
orientadas a objetos.
Su sintaxis es similar a la de SQL, proporcionando un
/*Añadir imagen
superconjunto de la sintaxis de la sentencia SELECT,
con algunas características añadidas para los conceptos Además, en una consulta OQL se pueden utilizar, entre otros, los
ODMG, como la identidad del objeto, los objetos siguientes operadores y expresiones:
complejos, las operaciones, la herencia, el polimorfismo
y las relaciones.  Operadores de acceso: "." / "->" aplicados a un atributo,
 No posee primitivas para modificar el estado de los una expresión o una relación. FIRST / LAST (primero /
objetos ya que las modificaciones se pueden realizar último elemento de una lista o un vector).
mediante los métodos que estos poseen.  Operadores aritméticos: +, -, *, /, -(unario), MOD, ABS
 Puede ser usado como un lenguaje autónomo o para formar expresiones aritméticas.
incrustado dentro de otros lenguajes como C++,  Operadores relacionales: >, =, <=, <>, = que permiten
Smalltalk y Java. comparaciones y construir expresiones lógicas.
 Una consulta OQL incrustada en uno de estos  Operadores lógicos: NOT, AND, OR que permiten enlazar
lenguajes de programación puede devolver objetos que otras expresiones.
coincidan con el sistema de tipos de ese lenguaje.
A continuación, te indicamos de manera resumida, algunas otras
 Desde OQL se pueden invocar operaciones escritas en
características, del estándar OQL:
estos lenguajes.
 Permite acceso tanto asociativo como navegacional:  Definición de vistas, es decir, es posible dar nombre a
o Una consulta asociativa devuelve una una consulta y utilizarlo en otras consultas.
colección de objetos.  Extracción de elementos sencillos de colecciones set, bag,
o Una consulta navegacional accede a objetos o list.
individuales y las interrelaciones entre objetos  Operadores de colecciones como funciones de
sirven para navegar entre objetos. agregación (MAX(), MIN(), COUNT(), SUM() y AVG()) y
cuantificadores (FOR ALL, EXISTS).
 Realización de agrupaciones mediante GROUP BY y filtro
de los grupos mediante HAVING.
5.1 Sintaxis, expresiones y  Combinación de consultas mediante JOINs
 Unión, intersección y resta de colecciones mediante los
operadores operadores UNION, INTERSEC y EXCEPT.
La sintaxis básica y resumida de una sentencia SELECT del OQL
En los siguientes apartados nos centraremos en el OQL concreto de
estándar es la siguiente:
un SGBDOO y que por supuesto, incorpora sus propias
/*Añadir imagen particularidades y diferencias respecto a la propuesta OQL de
ODMG.
SELECT [DISTINCT <expresión, ...>]
FROM <lista from>
[WHERE <condición>]
[ORDER BY <expresión>] 5.2 Matisse, un gestor de
Por ejemplo, suponiendo el esquema de base de objetos que puedes objetos que incorpora
ver en la figura ampliable de la derecha, la siguiente sentencia
select recupera de la base de objetos los atributos nombre y el OQL
correo de objetos tipo profesor cuyo año de ingreso es anterior al Para practicar y trabajar con OQL utilizaremos Matisse, un gestor
1990, y ordenados alfabéticamente por nombre: orientado a objetos que incorpora características del estándar
ODMG, como los lenguajes ODL y OQL, y que tiene soporte para
SELECT p.nombre, p.email FROM p in Profesor WHERE Java. Aunque Matisse llama SQL a su lenguaje de consultas,
p.ingreso <= 1990 ORDER BY p.nombre; nosotros nos referiremos a él como OQL.

Las siguientes, son algunas consideraciones a tener en cuenta: El propio gestor proporciona el driver matisse.jar para interactuar
con aplicaciones escritas en Java.
 En las consultas se necesita un punto de entrada, que
suele ser el nombre de una clase. Dentro de los paquetes del API destacamos:
 El resultado de una consulta es una colección que puede
ser tipo bag (si hay valores repetidos) o tipo set (no hay  com.matisse. Proporciona las clases e interfaces básicos
valores repetidos). En este último caso habrá que para trabajar con Java y una base de datos de objetos
especificar SELECT DISTINCT. Matisse.
 En general, una consulta OQL puede devolver un  MtDatabase. Clase que proporciona todos los métodos para

resultado con una estructura compleja especificada en la realizar las conexiones y transacciones en la base de
misma consulta utilizando struct. objetos.
 Una vez que se establece un punto de entrada, se pueden  com.matisse.sql. Proporciona clases que permiten interactuar

utilizar expresiones de caminos para especificar un con la base de objetos vía JDBC.
camino a atributos y objetos relacionados. Una expresión
Todas las interacciones entre una aplicación Java y la base de
de camino empieza normalmente con un nombre de
objetos Matisse se realizan en el contexto de una transacción
objeto persistente o una variable iterador, seguida de
(implícita o explícita).
ninguno o varios nombres de relaciones o de atributos
conectados mediante un punto.
 Es posible crear objetos mutables (no literales) formados
por el resultado de una consulta.
En el siguiente recurso didáctico encontrarás diferentes ejemplos
5.3 Ejecución de Sentencias de consultas utilizando de forma autónoma o conversacional el
lenguaje OQL de Matisse.
OQL /*Añadir imagen
La sintaxis básica del OQL de Matisse es una sentencia SELECT de
la forma: SELECT... FROM... WHERE...;

or ejemplo, para recuperar el valor de todos los atributos de los


objetos tipo Profesor, escribiríamos la siguiente sentencia OQL: 5.4 Ejecución de sentencias
SELECT * FROM Profesor;
OQL vía JDBC
Y para recuperar del atributo nombre de los objetos tipo Profesor Veremos ahora cómo realizar consultas a una base de objetos
cuyo año de ingreso es anterior al 1990, escribiríamos la siguiente Matisse mediante sentencias OQL embebidas en Java. Para ello, la
sentencia: conexión a la base de objetos se realizará vía JDBC. Matisse
proporciona dos formas de manipular objetos vía JDBC: mediante
SELECT nombre FROM Profesor WHERE ingreso <= 1990; JDB puro o mediante una mezcla de JDBC y Matisse.

Las siguientes son algunas consideraciones y ejemplos sobre las 1. Para crear una conexión vía JDBC puro utilizaremos
consultas con SELECT: java.SQL.* y com.Matisse.SQL.MtDriver , no siendo necesario en
este caso el paquete com.Matisse.
 Toda sentencia SELECT finaliza en punto y coma. a. La cadena de conexión será de la forma: String
 Además de la cláusula WHERE, que permite establecer un url = "JDBC:mt://" + hostname + "/" + dbname;
criterio de selección se pueden utilizar las cláusulas de b. La conexión se realizará mediante Connection
agrupamiento GROUP BY, y de ordenación ORDER BY, jcon = DriverManager.getConnection(url);
entre otras. También se pueden asignar alias mediante AS, 2. Para crear una conexión vía JDBC y Matisse (a través de
realizar búsquedas por patrones de caracteres con LIKE. MtDatabase) se necesita java.SQL.* y com.Matisse.MtDatabase.
Ejemplo: título y tema de las tesis cuyo tema contien la a. La cadena de conexión será de la forma:
palabra Objeto, ordenadas por tema. MtDatabase db = new MtDatabase(hostname,
dbname);
SELECT titulo AS "Tesis", tema FROM Tesis b. La conexión se realizará mediante: db.open(); y
WHERE tema LIKE '%Objeto%' ORDER BY tema; Connection jcon = db.getJDBCConnection();

Una vez realizada la conexión por uno u otro método, ya podremos


 Al recuperar todos los atributos de una clase mediante ejecutar sentencias OQL vía JDBC, (tal y como si de una sentencia
SELECT *, la consulta retornará el OID de cada objeto SQL se tratara) en la aplicación java.
recuperado, así como las interrelaciones o relaciones
definidas para esa clase. El OID y la interrelación son del
tipo string y se representan mediante un número
hexadecimal. Realmente el identificador recuperado para
la interrelación, hace referencia al primer objeto 6.Características de las
relacionado, incluso aunque la interrelación incluya a


más de un objeto.
Se pueden hacer JOIN de clases, y por ejemplo esto puede
bases de datos objeto-
permitir obtener todos los objetos relacionados con otro
objeto en una consulta asociativa.
relacionales
Ejemplo: nombre de cada profesor y título y tema de las
Las BDOR las podemos ver como un híbrido de las BDR y las
tesis que dirige con JOIN
BDOO que intenta aunar los beneficios de ambos modelos, aunque
por descontado, ello suponga renunciar a algunas características de
SELECT p.nombre, t.titulo, t.tema FROM Profesor p
ambos.
JOIN Tesis t ON t.es_dirigida = p.OID;
Los objetivos que persiguen estas bases de datos son:
 Mediante SELECT se pueden realizar consultas
navegacionales haciendo referencia a las  Mejorar la representación de los datos mediante la
interrelacionales entre objetos. orientación a objetos.
Ejemplo: nombre de cada profesor y título y tema de las  Simplificar el acceso a datos, manteniendo el sistema
tesis que dirige, navegacional relacional.

En una BDOR se siguen almacenando tablas en filas y columnas,


SELECT t.titulo AS "Tesis", tema, t.es_dirigida.nombre aunque la estructura de las filas no está restringida a contener
AS "Profesor " FROM Tesis t; escalares o valores atómicos, sino que las columnas pueden
almacenar tipos estructurados (tipos compuestos como vectores,
 También se pueden realizar consultas navegacionales a conjuntos, etc.) y las tablas pueden ser definidas en función de
través de la referencia de los objetos (REF()). otras, que es lo que se denomina herencia directa.
Ejemplo: tesis que dirigen los profesores con ingreo el
1990 o posterior Y eso, ¿cómo es posible?

Pues porque internamente tanto las tablas como las columnas son
SELECT REF(p.dirige) FROM Profesor p 1) tratados como objetos, esto es, se realiza un mapeo objeto-
WHERE p.ingreo >= 1990; relacional de manera transparente.
Como consecuencia de esto, aparecen nuevas características, END;
entre las que podemos destacar las siguientes:

 Tipos definidos por el usuario. Se pueden crear nuevos


tipos de datos definidos por el usuario, y que son
7.Gestores de Bases de
Datos Objeto-
compuestos o estructurados, esto es, será posible tener en
una columna un atributo multivaluado (un tipo
compuesto).
 Tipos Objeto. Posibilidad de creación de objetos como
nuevo tipo de dato que permiten relaciones anidadas.
Relacionales
 Reusabilidad. Posibilidad de guardar esos tipos en el
Podemos decir que un sistema gestor de bases de datos objeto-
gestor de la BDOR, para reutilizarlos en tantas tablas
relacional (SGBDOR) contiene dos tecnologías; la tecnología
como sea necesario
relacional y la tecnología de objetos, pero con ciertas restricciones.
 Creación de funciones. Posibilidad de definir funciones A continuación, te indicamos algunos ejemplos de gestores objeto-
y almacenarlas en el gestor. Las funciones pueden relacionales, tanto de código libre como propietario, todos ellos
modelar el comportamiento de un tipo objeto, en este con soporte para Java:
caso se llaman métodos.
 Tablas anidadas. Se pueden definir columnas como  De código abierto:
arrays o vectores multidimensionales, tanto de tipos o PostgreSQL
básicos como de tipos estructurados, esto es, se pueden
o Apache Derby
anidar tablas
 De código propietario
 Herencia con subtipos y subtablas.
o Oracle
Estas y otras características de las bases de datos objeto- o First SQL
relacionales vienen recogidas en el estándar SQL 1999. o DB2 de IBM

Las normativas SQL99 y SQL2003 son el estándar base que siguen


los SGBDOR en la actualidad, aunque como siempre ocurre, cada
6.1 El estándar SQL99 gestor incorpora sus propias particularidades y diferencias respecto
al estándar. Por ejemplo, en Oracle se pueden usar las dos
La norma ANSI SQL1999 (abreviadamente, SQL99) extiende el
posibilidades de herencia, de tipos y de tablas, mientras que en
estándar SQL92 de las Bases de Datos Relacionales, y da cabida a
PostgreSQL solo se puede usar la herencia entre tablas.
nuevas características orientadas a objetos preservando los
fundamentos relacionales.

Algunas extensiones que contempla este estándar y que están 7.1 Instalación del Gestor
relacionadas directamente con la orientación a objetos son las
siguientes: PostgreSQL
Para practicar con este tipo de gestores y algunas de las nuevas
 Extensión de tipos de datos. características que incorporan, hemos elegido PostgreSQL,
o Nuevos tipos de datos básicos para datos de considerado como el gestor de código abierto más avanzado del
caracteres de gran tamaño, y datos binarios de mundo.
gran tamaño (Large Objects)
o Tipos definidos por el usuario o tipos El código fuente de PostgreSQL está disponible bajo la licencia
estructurados. BSD. Esta licencia te da libertad para usar, modificar y distribuir
o Tipos colección, como los arrays, set, bag y list. PostgreSQL en cualquier forma, ya sea junto a código abierto o
o Tipos fila y referencia cerrado. Además, PostgreSQL. incluye API para diferentes
 Extensión de la semántica de datos. lenguajes de programación, entre ellos Java y .NET
o Procedimientos y funciones definidos por el
usuario, y almacenados en el gestor. En la instalación se solicita una contraseña para el usuario postgres,
o Un tipo estructurado puede tener métodos que es el administrador por defecto de la Base de Datos. La utilidad
definidos sobre él. pgAdmin (III) permite realizar esta administración de forma visual.

Por ejemplo, el siguiente segmento de SQL crea un nuevo tipo de


dato, un tipo estructurado de nombre profesor y que incluye en su
definición un método, el método sueldo() .
7.2 Tipos de datos: tipos
CREATE TYPE profesor AS
básicos y tipos
( id INTEGER,
nombre VARCHAR (20),
estructurados
/*Añadir imagen
sueldo_base DECIMAL (9,2),
complementos DECIMAL (9,2), Como ya sabes, los SGBDOR incorporan un conjunto muy rico de
INSTANTIABLE NOT FINAL tipos de datos. PostgreSQL no soporta herencia de tipos, pero
METHOD sueldo() RETURNS DECIMAL (9,2)); permite definir nuevos tipos de datos mediante los mecanismos
de extensión.
CREATE METHOD sueldo() FOR profesor
BEGIN
Te vamos a comentar tres categorías de tipos de datos que
...... encontramos en PostgreSQL:
Recuerda que en JDBC, una base de datos está representada por
 Tipos básicos: el equivalente a los tipos de columna una URL. La cadena correspondiente tiene una de las tres formas
usados en cualquier base de datos relacional. siguientes:
 Tipos compuestos: un conjunto de valores definidos por
el usuario con estructura de fila de tabla, y que como tal  jdbc: postgresql: base de datos
puede estar formada por tipos de datos distintos.  jdbc: postgresql: //host/base de datos
 Tipos array: un conjunto de valores distribuidos en un  jdbc: postgresql: //host: puerto/base de datos
vector multidimensional, con la condición de que todos
sean del mismo tipo de dato (básico o compuesto). El nombre de host por defecto, del servidor PostgreSQL, será
Ofrece más funcionalidades que el array del estándar localhost, y el puerto por el que escucha el 5432. Como ves, esta
SQL99. cadena es idéntica a la empleada por otros sistemas gestores de
bases de datos.
Entre los tipos básicos, podemos destacar:
Para conectar con la base de datos, utilizaremos el método
 Tipos numéricos. Aparte de valores enteros, números de DriverManager.getConnection() que devuelve un objeto
coma flotantes, y números de precisión arbitraria, Connection (la conexión con la base de datos). Una de las posibles
PostgreSQL incorpora también un tipo entero auto- sintaxis de este método es:
incremental denominado serial.
 Tipos de fecha y hora. Además de los típicos valores de Connection conn = DriverManager.getConnection(url, username,
fecha, hora e instante, PostgreSQL incorpora el tipo password);
interval para representar intervalos de tiempo.
 Tipos de cadena de caracteres. Prácticamente los Una vez abierta, la conexión se mantendrá operativa hasta que se
mismos que en cualquier BDR. llame a su método close() para efectuar la desconexión. Si al intentar
 Tipos largos. Como, por ejemplo, el tipo BLOB para conectar con la base de datos ésta no existe, se generará una
representar objetos binarios. En la actualidad presentes excepción del tipo PSQLException "FATAL: no existe la base de
en muchas BDR como MySQL. datos ...". En cualquier caso se requiere un bloque try-catch .

¿No soporta PostgreSQL el tipo estructurado? /*Añadir imagen

Los tipos compuestos de PostgreSQL son el equivalente a los


tipos estructurados definidos por el usuario del estándar SQL99. 7.4 Consulta y actualización
De hecho, son la base sobre la que se asienta el soporte a objetos.
de tipos básicos
Por ejemplo, podemos crear un nuevo tipo, el tipo dirección a partir PostgreSQL implementa los objetos como filas, las clases como
del nombre de la calle (varchar), del número de la calle ( integer) y del tablas, y los atributos como columnas. Hablaremos por tanto de
código postal (integer), de la siguiente forma: tablas, filas y columnas, tal y como lo hace PostgreSQL.

CREATE TYPE direccion AS ( Para interactuar con PostgreSQL desde Java, vía JDBC, debemos
calle varchar, enviar sentencias SQL a la base de datos mediante el uso de
comandos.
numero integer,
Por tanto, si nuestra conexión es conn, para enviar un comando
codigo_postal integer); Statement haríamos lo siguiente:

y luego definir la tabla de nombre afiliados, con una columna  Crear la sentencia, por ejemplo.: Statement sta =
basada en el nuevo tipo: conn.createStatement();
 Ejecutar la sentencia:
CREATE TABLE afiliados AS( o sta.executeQuery(string sentenciaSQL); si
afiliado_id serial, sentenciaSQL es una consulta (SELECT)
nombre varchar(45), o sta.executeUpdate(string sentenciaSQL); si
apellidos varchar(45), sentenciaSQL es una actualización ( INSERT,
domicilio direccion); UPDATE O DELETE)
o sta.execute(string sentenciaSQL); si sentenciaSQL
es un CREATE, DROP, o un ALTER
7.3 Conexión mediante Como ves, en PostgreSQL se utilizan estos comandos como en
JDBC cualquier otra BDR.
La conexión de una aplicación Java con PostgreSQL se realiza
mediante un conector tipo JDBC. En el siguiente enlace te proporcionamos un ejemplo que ilustra
este hecho, con sentencias perfectamente conocidas por ti del
Una vez integrado en un proyecto, el driver puede utilizarse desde modelo relacional. Se crean varias tablas en la base de datos
cualquiera de sus clases mediante un: anaconda, se insertan, modifican, eliminan y consultan datos de
tipos básicos.
import java.sql.*
/*Añadir imagen

En las próximas secciones, emplearemos estos mismos comandos


para estudiar las nuevas características del estándar SQL99
donde como se ve, sólo hay que agregar uno o más corchetes '[]' al
7.5 Consulta y actualización tipo de dato.

de tipos estructurados Aunque PostgreSQL permite especificar el tamaño de cada


Imaginemos que tenemos el tipo estructurado direccion: dimensión en la declaración, y acepta escribir:

CREATE TYPE direccion AS ( o bien nombre_columna tipo_dato[2][3] , las


nombre_columna tipo_dato[5]

calle varchar, numero integer, codigo_postal varchar); versiones actuales ignoran estos valores en la práctica, de manera
que los array declarados de esta forma tienen la misma
funcionalidad que los del ejemplo anterior.
y la tabla afiliados, con una columna basada en el nuevo tipo:
En realidad, ninguna de estas declaraciones es conforme al estándar
CREATE TABLE afiliados(afiliado_id serial, nombre varchar, SQL99, que sólo contempla el tipo array como columnas de vectores
apellidos varchar, domicilio direccion); unidimensionales declarados con la palabra reservada array:

¿Cómo insertamos valores en una tabla con un tipo En el siguiente ejemplo puedes ver la creación de una tabla con una
estructurado? Se puede hacer de dos formas: columna de tipo array de varchar y como se insertan y consultan
valores:
 Pasando el valor del campo estructurado entre comillas
simples (lo que obliga a encerrar entre comillas dobles /*Añadir imagenes
cualquier valor de cadena dentro), y paréntesis para
encerrar los subvalores separados por comas: Debes conocer
/*Añadir información
INSERT INTO afiliados (nombre, apellidos, direccion)
VALUES ('Onorato', 'Maestre Toledo', '(“Calle
de Rufino”, 56, 98080)'); 7.7 Funciones del gestor
 Mediante la función ROW que permite dar valor a un desde Java
tipo compuesto o estructurado. Recuerda que el estándar SQL99 introduce la posibilidad de crear
funciones de usuario que puedan quedar almacenadas en el gestor
INSERT INTO afiliados (nombre, apellidos, direccion) de bases de datos, utilizando un Lenguaje Procedural (PL). Estas
funciones pueden definir el comportamiento de ciertos objetos y
VALUES ('Onorato', 'Maestre Toledo',
entonces, se llaman métodos. Oracle soporta métodos en este
ROW('Calle de Rufino', 56, 98080));
sentido, no así el gestor PostgreSQL.
¿Cómo se referencia una subcolumna de un tipo estructurado? Lo que si podremos hacer en PostgreSQL es crear funciones con
prestaciones para los nuevos tipos de datos, tipos estructurados y
 Se emplea la notación punto, '.' , tras el nombre de la array, y llamarlas desde una aplicación Java.
columna entre paréntesis, (tanto en consultas de
selección, como de modificación) . Por ejemplo: En PostgreSQL se pueden construir funciones mediante diferentes
lenguajes:
SELECT (domicilio).calle FROM afiliados WHERE
(domicilio).codigo _postal=98080  Funciones de lenguaje de consultas o funciones SQL
(Escritas en lenguaje SQL)
devolvería el nombre de la calle Maestre Toledo. Los  Funciones de lenguaje procedural (Escritas en lenguaje
paréntesis son necesarios para que el gestor no confunda PL/pgSQL, PL/Java, etc)
el nombre del campo compuesto con el de una tabla.  Funciones de lenguaje de programación (Escritas en
un lenguaje de compilado, como C o C++),
Y ¿cómo se elimina el tipo estructurado?
Veremos algún ejemplo de funciones en SQL. Sobre estas
 Se elimina con DROP TYPE, por ejemplo DROP TYPE funciones debes saber que:
direccion;
 Los parámetros de la función pueden ser cualquier tipo

7.6 Consulta y actualización de dato admitido por el gestor (un tipo básico, un tipo
compuesto, un array o alguna combinación de ellos).

de tipos array  El tipo devuelto puede ser un tipo básico, un array o un


tipo compuesto.
PostgreSQL permite especificar vectores multidimensionales  Su estructura general tiene la forma:
como tipo de dato para las columnas de una tabla. La única
condición es que todos sus elementos sean del mismo tipo. CREATE FUNCION nombre_funcion(tipo_1,tipo_2,...)
RETURN tipo AS $$sentencia_sql$$
Por ejemplo:
LANGUAJE SQL
 Declaración de una columna de tipo vector:
nombre_columna tipo_dato[] Y debes tener en cuenta que:
 Declaración de una columna de tipo matriz
multidimensional: nombre_columna tipo_dato[][]
 Los argumentos de la función SQL se pueden referenciar  Isolation (Aislamiento). Las transacciones sobre la
en las consultas usando la sintaxis $n:, donde $1 se refiere al misma información deben ser independientes, para que
primer argumento, $2 al segundo, y así sucesivamente. Si un no interfieran sus operaciones y no se produzca ningún
argumento es un tipo compuesto, entonces se usará la tipo de error.
notación '.' para acceder a sus subcolumnas.  Durabilidad. Cuando la transacción termina el resultado
 Por último, al final de la función hay que especificar que de la misma perdura, y no se puede deshacer, aunque
la función se ha escrito en lenguaje SQL mediante las falle el sistema.
palabras clave LENGUAJE SQL.
Algunos sistemas proporcionan también puntos de salvaguarda
Por ejemplo, desde Java podemos crear una función que convierte (savepoints) que permiten descartar selectivamente partes de la
un tipo estructurado, por ejemplo el tipo direccion, en una cadena. transacción, justo antes de acometer el resto. Así, después de
Para ello, ejecutaremos un comando Statement (sta) con el código definir un punto como punto de salvaguarda, puede retrocederse al
SQL de creación de la función: mismo. Entonces se descartan todos los cambios hechos por la
transacción después del punto de salvaguarda, pero se mantienen
sta.execute (“CREATE FUNCTION todos los anteriores.
cadena_direccion(direccion)”+ Originariamente, los puntos de salvaguarda fueron una aportación
“RETURNS varchar AS 'SELECT $1.calle||' '|| CAST($1.numero del estándar SQL99 de las Bases de Datos Objeto-Relacionales.
AS varchar)”+ Pero con el tiempo, se han ido incorporando también a muchas
Bases de Datos Relaciones como MySQL (al menos cuando se
“LANGUAGE SQL”;)
utiliza la tecnología de almacenamiento InnoDB).
Si una función tiene algún parámetro de tipo estructurado, no se
podrá eliminar el tipo hasta que no se elimine la función. Se puede
usar DROP C nb_tipo CASCADE para eliminar de manera
4.1 Transacciones en una
automática las funciones que utilizan ese tipo.
base objeto-relacional
En el siguiente enlace te puedes descargar un ejemplo donde se
Los SGBDOR gestionan transacciones mediante las sentencias
crean funciones del gestor y se invocan desde una aplicación Java.
COMMIT (confirmar transacción) y ROLLBACK (deshacer
transacción).
/* Añadir imagen
JDBC permite agrupar instrucciones SQL en una sola transacción.

6. Gestión de Así, podemos asegurar las propiedades ACID usando las


facilidades transaccionales del JDBC.

transacciones El control de la transacción lo realiza el objeto Connection. Cuando


se crea una conexión, por defecto es en modo AUTO COMMIT= TRUE.
Como en cualquier otro Sistema de Bases de datos, en un Sistema Esto significa que cada instrucción individual SQL se trata como
de bases de objetos u objeto relacional, una transacción es un una transacción en sí misma, y se confirmará en cuanto que la
conjunto de sentencias que se ejecutan formando una unidad de ejecución termine.
trabajo, esto es, en forma indivisible o atómica, o se ejecutan todas
o no se ejecuta ninguna. Por tanto, si queremos que un grupo de sentencias se ejecuten
como una transacción, tras abrir una conexión Connection conn; habrá
Mediante la gestión de transacciones, los sistemas gestores que:
proporcionan un acceso concurrente a los datos almacenados,
mantienen la integridad y seguridad de los datos, y proporcionan  Poner autocommit=false de la siguiente manera:
un mecanismo de recuperación de la base de datos ante fallos.
if (conn.getAutoCommit() )
Un ejemplo habitual para motivar la necesidad de transacciones es conn.setAutoCommit( false );
el traspaso de una cantidad de dinero (digamos 10000€) entre dos
cuentas bancarias. Normalmente se realiza mediante dos  Mediante un bloque try-catch controlar si se deshace
operaciones distintas, una en la que se decrementa el saldo de la conn.rollback o confirma conn.commit la transacción iniciada
cuenta origen y otra en la que incrementamos el saldo de la cuenta con esa conexión.
destino.
En el siguiente enlace puedes ver como se controlan una secuencia
Para garantizar la integridad del sistema (es decir, para que no de insert como una transacción en PostgreSQL.
aparezca o desaparezca dinero), las dos operaciones tienen que
completarse por completo, o anularse íntegramente en caso de que /*Añadir imagen
una de ellas falle.

Las transacciones deben cumplir el criterio ACID. 4.2 Transacciones en un


 Atomicidad. Se deben cumplir todas las operaciones de
la transacción o no se cumple ninguna; no puede quedar a
gestor de objetos
Las transacciones en un sistema de objetos puro, se gestionan
medias.
mediante COMMIT y ROLLBACK.
 Consistencia. La transacción solo termina si la base de
datos queda en un estado consistente. Un fallo causa un rollback de los datos, como normalmente sucede
en las bases de datos relacionales. En cuanto a la concurrencia, las
bases de objetos verifican en qué momento permiten el acceso en  Enlaces con lenguajes Orientados a Objetos como C++,
paralelo a los datos. Este acceso concurrente implica que más de Java, Smaltalk.
una aplicación o hilo podrían estar leyendo o actualizando los
mismos objetos a la vez. Esto se suele denominar commit de dos El modelo de objeto ODMG es el modelo de datos en el que están
fases (dos procesos pueden trabajar sobre el mismo objeto basados el ODL y el OQL. Este modelo de objeto proporciona los
concurrentemente). Para ello se utiliza normalmente bloqueo de tipos de datos, los constructores de tipos y otros conceptos que
datos para lecturas y escrituras. pueden utilizarse en el ODL para especificar el esquema de la base
de datos de objetos.
Veamos un ejemplo sencillo con la base de objetos db4o. En
Db4o: Vamos a destacar algunas de las características más relevantes
del estándar ODMG:
 Siempre se trabaja dentro de una transacción.
 Al abrir un ObjectContainer se crea e inicia implícitamente  Las primitivas básicas de modelado son los objetos y los
una transacción. literales.
 Las transacciones se gestionan explícitamente mediante  Un objeto tiene un Identificador de Objeto (OID) y un
commit y rollback. estado (valor actual) que puede cambiar y tener una
 La transacción actual hace commit implícitamente cuando estructura compleja. Un literal no tiene OID, pero si un
se cierra el ObjectContainer. valor actual, que es constante.
 El estado está definido por los valores que el objeto toma
Por ejemplo, podemos deshacer una transacción con rollback, para un conjunto de propiedades. Una propiedad puede
restaurando la base de objetos al estado anterior, justo al estado ser:
después del último commit o rollback. o Un atributo del objeto.
o Una interrelación entre el objeto y otro u otros
En el siguiente ejemplo, al ejecutar db.rollback después de db.store(p3) y objetos.
db.store(p4), hará que los objetos p3 y p4 no se almacenen en la base  Objetos y literales están organizados en tipos. Todos los
de objetos. objetos y literales de un mismo tipo tienen un
comportamiento y estado común.
/*Añadir imagen  Un objeto queda descrito por cuatro características:
identificador, nombre, tiempo de vida y estructura.

7. Anexo I.- Estándar  Los tipos de objetos se descomponen en atómicos,


colecciones y tipos estructurados.
o Tipos atómicos o básicos: constan de un único
ODMG-93 u ODMG. elemento o valor, como un entero.
o Tipos estructurados: compuestos por un
El estándar ODMG (Object Database Management Group) trata número fijo de elementos que pueden ser de
de estandarizar conceptos fundamentales de los Sistemas Gestores distinto tipo, como por ejemplo una fecha.
de Bases de Datos Orientados a Objetos (SGBDOO) e intenta o Tipos colección: número variable de
definir un SGBDOO como un sistema que integra las elementos del mismo tipo. Entre ellos:
capacidades de las bases de datos con las capacidades de los  Set: grupo desordenado de elementos
lenguajes de programación orientados a objetos, de manera que y sin duplicados.
los objetos de la base de datos aparezcan como objetos del lenguaje  Bag: grupo desordenado de
de programación. elementos que permite duplicados.
 List: grupo ordenado de elementos
Fue desarrollado entre los años 1993 y 1994 por representantes de que permite duplicados.
un amplio conjunto de empresas relacionadas con el desarrollo de  Array: grupo ordenado de elementos
software y sistemas orientados a objetos. que permite el acceso por posición.

Arquitectura del estándar ODMG La arquitectura propuesta por Algunos fabricantes sólo ofrecen vinculaciones de lenguajes
ODMG consta de: específicos, sin ofrecer capacidades completas de ODL y OQL
 Un modelo de objetos que permite que tanto los diseños,
como las implementaciones, sean portables entre los
sistemas que lo soportan.
 Un sistema de gestión que soporta un lenguaje de bases
de datos orientado a objetos, con una sintaxis similar a un
lenguaje de programación también orientado a objetos.
 Un lenguaje de base de datos que es especificado
mediante:
o Un Lenguaje de Definición de Objetos (ODL)
o Un Lenguaje de Manipulación de Objetos
(OML)
o Un Lenguaje de Consulta (OQL)

siendo todos ellos portables a otros sistemas con el


fin de conseguir la portabilidad de la aplicación
completa.
Tema 6. Bases de datos xml.
1 Introducción 6.5 Documentos XML
Atendiendo al nivel de estructuración, podemos decir que existen
tres tipos de datos: centrados en datos y
 Datos estructurados. Son los que tienen un formato centrados en texto
estricto. Toda la información recogida se ajusta al mismo Como te hemos comentado antes, los tipos de documentos XML
formato, como, por ejemplo: los datos tabulados en filas que nos podemos encontrar son:
y columnas de una tabla.
 Datos desestructurados. No tienen ninguna estructura,  Documentos centrados en datos, con las siguientes
como un documento de texto o un archivo de vídeo. características:
 Datos semi-estructurados. Tienen cierta estructura, pero o Muchos elementos de datos de pequeño
no toda la información recogida tiene la misma forma, y tamaño.
además puede ir variando de manera dinámica. o Con estructura regular y bien definida.
o Datos muy estructurados o semi-estructurados.
Las bases de datos tradicionales, como las Bases de Datos o Dirigidos a utilización automática (por
Relacionales (BDR) son apropiadas para almacenar datos máquinas). E
estructurados, pero la cuestión es que, en la actualidad, son muchas o jemplos: Facturas, Pedidos Ficha de alumno.
las situaciones en las que interesa almacenar grandes volúmenes de  Documentos centrados en texto, contenido o
datos no estructurados, e incluso integrarlos con datos documentos con las siguientes características:
estructurados. Pero ¿cómo hacerlo? Aquí es donde entra en juego o Pocos elementos.
XML (eXtensible Markup Language). o Con grandes cantidades de texto.
o Con estructuras impredecibles en tamaño y
XML define un conjunto de reglas semánticas que permiten la
contenido.
organización de información de distintas maneras. Es un estándar
o Datos poco estructurados.
definido por el W3C y ofrece muchas ventajas, entre ellas:
o Orientados a ser interpretadas por humanos.
 Es un lenguaje bien formado. No puede haber etiquetas o Enfocados a sistemas documentales y de
sin finalizar. gestión de contenidos.
 Extensible. Permite ampliar el lenguaje mediante nuevas o Ejemplos: Libros, Informes, Memorias,
etiquetas y la definición de lenguajes nuevos. Artículos bibliográficos.
 Fácil de leer.
En la siguiente imagen ampliable puedes apreciar las características
 Autodescriptivo. La estructura de la información de
indicadas para estos dos tipos de documentos.
alguna manera está definida dentro del mismo
documento
/*Añadir imagen
 Intercambiable.
 Portable entre distintas arquitecturas. Para su lectura e
En el siguiente enlace tienes un ejemplo de cada tipo de documento
interpretación es necesario un parser, y hay productos y
versiones libres.
/*Añadir imagen
Debido fundamentalmente a estas ventajas y a su sencillez, el
estándar XML ha sido ampliamente aceptado y adoptado para
el almacenamiento e intercambio de información, y como
6.6 Opciones de
consecuencia de este uso se ha creado la necesidad de almacenar
dicha información.
almacenamiento
Para almacenar documentos XML tenemos las siguientes opciones:
Y ¿cómo se almacena la información en formato XML de cara a su
 Almacenamiento directo del fichero. Es una opción
recuperación y consulta? Existen varias aproximaciones para
organizar y almacenar información XML que fundamentalmente pobre ya que las operaciones que podemos hacer sobre
ellos son limitadas, las que proporcione el sistema de
van a depender de los diferentes archivos o documentos XML que
nos podemos encontrar (centrados en datos y centrados en texto). archivos.
 Almacenar el documento en una base de datos
Pero, en definitiva, lo que se busca es una estrategia que permita existente (base de datos relacional, orientada a objetos u
almacenar y recuperar datos poco estructurados con la eficiencia de objeto-relacional). En este caso existen las siguientes
las Bases de Datos convencionales, y es por ello que surgen las posibilidades:
Bases de Datos XML.
o Directamente como una columna tipo Las Bases de Datos nativas XML NXD (Native XML Database)
binario grande (BLOB) dentro de una tabla. aunque existen desde hace años, en la actualidad siguen
En este caso se almacena el documento intacto. evolucionando, por lo que existen ciertas diferencias entre los
Es una buena estrategia si el documento XML productos de este tipo que podemos encontrar en el mercado. Lo
contiene contenido estático, que solo será que, si está bastante claro, es que una NXD o BD XML debe
modificado cuando se reemplaza el documento cumplir las siguientes propiedades:
completo. Almacenar el documento completo
en formato de texto es fácil de implementar  Define un modelo lógico de datos XML, estableciendo
dado que no se necesita mapeo o traducción, los elementos que son significativos, de forma que el
pero limita las consultas y búsquedas de documento XML se pueda almacenar y recuperar de
contenido. manera intacta, esto es, con todos sus componentes. Por
o Mediante mapeo basado en tablas, o basado tanto, el modelo, como mínimo, debe tener en cuenta: los
en objetos. En ambos casos hay que realizar elementos, atributos, texto, secciones CDATA, y
una transformación para ajustarlo a la preservar el orden en el documento.
estructura de la BD antes de almacenarlo, y  El documento XML es la unidad lógica de
normalmente esto conlleva prescindir de cierta almacenamiento, esto es, la unidad mínima de
información, que supondrá que el documento y almacenamiento.
su formato no se almacena y recupera de  No tiene ningún modelo de almacenamiento físico
manera intacta. Además, en el caso de subyacente concreto. Pueden ser construidas sobre
documentos centrados en texto, no podemos bases de datos relacionales, jerárquicas, orientadas a
controlar todas las posibles estructuras del objetos o bien mediante formatos de almacenamiento
documento, y por tanto realizar un mapeo sobre propietarios.
la base de datos será prácticamente imposible.
 Almacenar el documento en una base de datos nativa Lo que realmente cambia en estas BD respecto a las
XML. El documento, tanto si es centrado en datos como convencionales, es el formato que soportan, ya que, están
en texto, se almacena y recupera de forma intacta. Como especializadas en almacenar documentos XML, almacenarlos y
veremos, será la mejor opción, sobre todo si el recuperarlos con todos sus componentes.
documento está basado en texto.
Otras características de las BD Nativas XML son las siguientes:
La siguiente imagen ampliable ilustra las anteriores opciones de
almacenamiento:  Documentos y colecciones. Los documentos se pueden
agrupar en unidades denominadas colecciones.
/*Añadir imagen  Indexación. Permiten la creación de índices para acelerar
las consultas realizadas frecuentemente.
En la actualidad, cada vez más, las BD convencionales ofrecen  Identificador único. A cada documento XML se le
posibilidades de almacenamiento XML, por lo que se habla de BD asocia un identificador único, por el que será reconocido
XML-compatible o BD XML-enabled. Por tanto, podemos hablar dentro del repositorio.
de dos tipos de Sistemas de Bases de Datos que soportan  Consultas. Soportan uno o más lenguajes de consulta.
documentos XML: Entre ellos, uno de los más populares es XQuery (XML
Query)
 BD XML-compatibles: desglosan un documento XML  Actualizaciones. Poseen diferentes estrategias para
en su correspondiente modelo relacional o de objetos. actualizar documentos, entre ellas la más popular es
 BD XML Nativas: respetan la estructura del documento, Update XQuery.
permiten hacer consultas sobre dicha estructura y  Validación. No siempre se realiza validación de
recuperan el documento tal y como fue insertado documentos, esto es, no necesitan un DTD o un XML
originalmente Schema (W3C) para almacenar documentos, basta con
que los documentos sean XML bien formados.
Las principales diferencias entre ambos tipos de BD XML son las  Soportan transacciones, accesos concurrentes, control de
siguientes: accesos y backup como cualquier otro sistema de bases
de datos.
 Una BD XML nativa proporciona un modelo de datos
propio, mientras que un BD XML-compatible tiene ya un Y ¿en qué situaciones puede resultar imprescindible su uso?
modelo de datos y añade una capa de software que Fundamentalmente en las siguientes situaciones:
permite de alguna manera almacenar documentos XML y
recuperar los datos generando nuevos documentos XML.  Existencia de documentos con anidamientos profundos.
 Una BD XML nativa debe manejar todos los tipos de  Importancia de preservar la integridad de los
documentos posibles, mientras que una BD XML- documentos.
compatible solo puede manejar y almacenar los  Frecuentes búsquedas de contenido.
documentos que encajan dentro del modelo definido para
ellos
8.1 Estrategias de
8. Bases de Datos almacenamiento
Nativas XML
Podemos diferenciar o clasificar las BD XML nativas en función
del tipo de almacenamiento que utilicen, que puede ser:

 Almacenamiento basado en texto


 Almacenamiento basado en el modelo
 Soluciones desarrolladas específicamente para la gestión Un documento:
de documentos XML
 Información XML
¿En qué consiste el almacenamiento basado en texto y basado en  Información de otro tipo y entonces se le denomina non-
modelo? XML data (Datos no-XML)

 El almacenamiento basado en texto consiste en Comparando con una base de datos relacional o un sistema de
almacenar el documento XML entero en forma de texto archivos:
(fichero de texto), y proporcionar alguna funcionalidad
de base de datos para acceder a él. Se suelen aplicar  Las colecciones juegan en las bases de datos nativas el
técnicas de compresión para reducir el espacio de papel de las tablas en las DB relacionales, o de un
almacenamiento, utilizar índices adicionales para mejorar directorio en un sistema de archivos.
el acceso a la información, y se pueden definir sobre BD  Los documentos juegan el papel de las filas de una tabla
tradicionales o sistemas de ficheros. Básicamente existen de una BD relacional o un fichero en un sistema de
dos posibilidades: archivos.
o Almacenar el documento como un binario
largo (BLOB) en una base de datos relacional, Aunque depende de cada implementación, en muchos casos:
o mediante un fichero, y proporcionar algunos
índices sobre el documento que aceleren el  Cada colección puede tener más de un DOCTYPE
acceso a la información. asociado.
o Almacenar el documento en un almacén  El elemento raíz del documento XML define a que
adecuado con índices, soporte para DOCTYPE estará asociado el documento, en caso de no
transacciones, etc. poseer ninguno, éste se crea dinámicamente. Esto
 El almacenamiento basado en modelo consiste en posibilita el almacenamiento de documentos sin formato
definir un modelo de datos lógico, como DOM, para la definido.
estructura jerárquica de los documentos XML y  La colección también puede tener asociado un Schema
almacenar el modelo binario del documento en un con información tanto física como lógica de la colección.
almacén existente o bien específico. En este caso las La parte lógica define las relaciones y propiedades de los
posibilidades que existen son: documentos XML y la física contiene información sobre
o Traducir el DOM a tablas relacionales como el almacenamiento e indexación de los mismos.
elementos, atributos, entidades, etc.  También se pueden almacenar documentos no-XML,
o Traducir el DOM a objetos en una BDOO. para estos existe un DOCTYPE especial llamado non-
o Utilizar un almacén creado especialmente para XML.
esta finalidad

A continuación, te indicamos algunos ejemplos de BD XML 8.3 Gestores nativos XML


nativas clasificadas según su sistema de almacenamiento:
 Sistema propietario: XIndice, Virtuoso, Tamino XML comerciales y libres
Server. Te indicamos a continuación algunos ejemplos de gestores nativos
 Sistema relacional: eXist, DBCOM, XDB XML clasificados según sean de código libre o código propietario.
 Sistema orientado a objetos: Ozone, MindSuite XDB. Los comerciales, generalmente ofrecen versiones de prueba con
limitaciones de tiempo de uso y de funcionalidades. Los libres, a
¿Y qué ventajas proporcionan las BD XML nativas sobre otros veces también ofrecen dualidad de licencia, comercial y libre.
sistemas de almacenamiento? Las principales ventajas son las
siguientes: Algunos de estos gestores nativos XML son los siguientes:

 No necesitan mapeos adicionales. Gestores nativos XML comerciales o de código propietario son:
 Conservan la integridad de los documentos.  TaminoXML Server. Es un gestor nativo XML de la
 Permiten almacenar documentos heterogéneos empresa SoftwareAG. Es un producto comercial de alto
rendimiento y disponibilidad, además de ser uno de los
primeros SGBD XML nativos disponibles. Algunas de
8.2 Colecciones y sus características son las siguientes:
o Los documentos se almacenan en una base de
documentos datos propia y no se transforman en otro
modelo.
/*Añadir imagen
o Existe un espacio separado para documentos y
En general, una BD XML tiene una estructura jerárquica para índices.
organizada en colecciones y documentos XML. La estructura o Soporta el lenguaje de consultas XQuery y
jerárquica comienza con un nodo raíz ('/'), del que parten APIs para Java, C, y .NET, entre otras.
colecciones y documentos.  TEXTML de Isiasoft. Los documentos se almacenan en
su formato nativo, sin ser mapeados.
Una colección: o Permite almacenar documentos sin DTD o
esquema.
 Es un conjunto de documentos agrupados, normalmente, o Proporciona índices de acuerdo a la propia
en función de la información que contienen. estructura del documentos.
 Puede contener otras colecciones.
o Permite la utilización de varios índices al Qizx fue lanzado de nuevo por Qualcomm a finales de 2014 on
mismo tiempo. Amazon Web Services.
o Incluye API para Java, WebDAV, OLE DB
y .NET.
Gestores nativos XML libres o de código abierto son: a. Gestionar la base de
 Qizx. Es una base de datos nativa XML escrita en Java.
Almacena los datos utilizando una representación que se datos XML mediante
basa en el modelo de XPath 2,0.
o La representación utiliza compresión de QizxStudio
manera que un documento y sus índices suelen Una BD XML Qizx está organizada como una estructura jerárquica
utilizar menos espacio que el original XML. de colecciones, que a su vez contienen documentos, similar a un
o Los documentos se almacenan en una jerarquía sistema de archivos, donde las colecciones juegan el papel de los
de colecciones. directorios y los documentos XML desempeñan el papel de los
o Permite almacenar documentos sin DTD o archivos planos. Dentro de una colección pueden almacenarse
esquema. documentos de cualquier tipo.
o Soporta el lenguaje de consulta XQuery y sus
extensiones, como XUpdate, así como API Te detallamos a continuación la terminología utilizada por Qizx:
para Java.
 eXist. Utiliza un sistema de almacenamiento propio  XML Library. Es el equivalente a una base de datos XML.
(árboles B + y archivos paginados). Se puede ejecutar Físicamente, una BD o Library se almacena en un
como un servidor de base de datos independiente, como directorio en un disco, y no hay límite en el número de
una biblioteca de Java embebida, o en el motor servlet de bases de datos que se pueden crear con Qizx.
una aplicación Web.  Su estructura jerárquica siempre comienza con un nodo
o Los documentos se almacenan en una jerarquía raíz, '/', del que parten documentos XML y/o colecciones.
de colecciones.  XML Library Group. Es un conjunto de BD XML,
o Permite almacenar documentos sin DTD o agrupadas dentro de un directorio en disco.
esquema.
o Soporta el lenguaje de consulta XQuery y sus Por ejemplo, la imagen ampliable de la derecha muestra:
extensiones, como XUpdate, así como API
para Java.  XML Library Group at C:\dxml. Es el grupo de BD XML
situado en el directorio físico c:\dbxml.
 XML Library 'Libros'. Es la BD XML de nombre Libros.
9. Instalación del 

'/'. Es el nodo raíz de la BD o Library
Las colecciones Publisher, Authors y Books dentro de la BD

gestor Qizx 
XML de nombre Libros.
Diferentes documentos (archivos XML) dentro de la
colección Authors, como por ejemplo iasimov.xml.
En los siguientes apartados trabajaremos con la base de datos
nativa XML Qizx, especialmente diseñada para integrarse en una Podemos trabajar directamente con Qizx a través de la herramienta
aplicación Java independiente, esto es, para trabajar en modo gráfica denominada QizxStudio, la cual nos permite entre otras
embebido (embedded). Como tal, se utiliza principalmente como acciones las siguientes:
una biblioteca de clases, lo que supone que para utilizarla en una
aplicación habrá que añadir los correspondientes archivos .jar.
 Crear la BD XML
También se puede utilizar en un entorno JEE, Servlets o EJB.
 Explorar colecciones y documentos XML de la base de
datos
Algunas características de Qizx, que iremos viendo en los
 Importar, crear y eliminar colecciones
siguientes apartados, son las siguientes:
 Importar y eliminar documentos, así como copiar o
exportar a fichero
 Consultas e indexación optimizadas. A diferencia de
otras bases de datos nativas XML, que están optimizadas  Consultar documentos
para la actualización masiva de documentos XML, Qizx
optimiza las búsquedas y consultas de documentos Antes de comenzar a trabajar con Qizx y Java, y con el objetivo de
mediante un sistema de indexación muy eficiente. Sin que te familiarices con esta BD XML, verás algunos ejemplos de
embargo, la actualización de documentos de gran tamaño cómo gestionar colecciones y documentos mediante QizxStudio.
no es tan eficiente.
En el siguiente recurso didáctico encontrarás ejemplos de todo ello.
 Compatible con estándares. Es totalmente compatible
con el lenguaje XQuery y sus extensiones Full-Text
/*Añadir imagen
XQuery y Update XQuery.
 No necesita DTD o Esquemas predefinidos, siempre y


cuando el documento XML esté bien formado.
Indexado Automático. Los documentos son indexados
4 El lenguaje de consultas
automáticamente, aunque permite también personalizar
los índices. XQuery
Qizx fue inicialmente desarrollado por Xavier Franc of Axyana y XQuery es un lenguaje de consulta diseñado para extraer
fue comprado por Qualcomm in 2013. información de colecciones de datos expresadas en XML. Entre las
principales características de XQuery vamos a destacar las  Nodo atributo. Un nodo elemento puede tener etiquetas
siguientes: que complementen la información de ese elemento. Esto
sería un nodo atributo.
 Está basado en el lenguaje XPath, (XML Path
Language), y se fundamenta en él para realizar la Debes conocer
selección de información y la iteración a través del /*Añadir imagen
conjunto de datos XML.
 Es un lenguaje declarativo, lo que significa que, en vez
de ejecutar una lista de comandos como un lenguaje 4.2 Caminos de localización
procedimental clásico, cada consulta es una expresión ¿Cómo se localiza cada uno de esos nodos en al árbol XML?
que es evaluada y devuelve un resultado, al igual que en Mediante una expresión XPath conocida como camino o ruta de
SQL. localización. Un camino de localización:

Podemos decir que XQuery es a XML lo mismo que SQL es a  Selecciona un conjunto de nodos relativo al nodo de
las bases de datos relacionales. Sin embargo, aunque XQuery y contexto.
SQL puedan considerarse similares, el modelo de datos sobre el  Puede contener recursivamente expresiones utilizadas
que se sustenta XQuery es muy distinto del modelo de datos para filtrar conjuntos de nodos.
relacional sobre el que sustenta SQL, ya que XML incluye  Al ser evaluado, devuelve el conjunto de nodos
conceptos como jerarquía y orden de los datos que no están seleccionados por el camino de localización.
presentes en el modelo relacional.  Se construye siguiendo unas reglas de sintaxis y
semántica.
Por ejemplo, a diferencia de SQL, en XQuery es importante y
determinante el orden en que se encuentren los datos, ya que no es Hay dos tipos de caminos de localización:
lo mismo buscar una etiqueta nombre dentro de una etiqueta autor
que todas las etiquetas nombre del documento (que pueden estar  Caminos relativos. Son una secuencia de uno o más
anidadas dentro de una etiqueta autor o fuera). pasos de localización separados por /.
o Los pasos se componen de izquierda a derecha.
Los principales tipos de expresiones de XQuery son:
 Caminos absolutos. Consiste en / seguido,
opcionalmente, por un camino de localización relativo.
 Expresiones XPath, para navegar por los documentos. o Una / por si misma selecciona el nodo raíz del
 Expresiones FLWOR (For, Let, Where, Order, Return) para documento que contiene al nodo contextual.
iterar por los elementos de un conjunto de datos.
Los siguientes, son algunos ejemplos de caminos de localización:
Pero XQuery también admite:
 cuadro selecciona los elementos cuadro hijos del nodo
 Constructores para generar nodos y contenido dinámico. contextual.
 Condicionales (IF, THEN ELSE) para construir el resultado  cuadro//titulo selecciona los elementos titulo descendientes de
en base a alguna condición. los elementos cuadro hijos del nodo contextual.
 Cuantificadores (SOME, ANY) para chequear la existencia  * selecciona todos los elementos hijos del nodo
de algún elemento que cumpla una condición. contextual.
 Listas a las que se pueden aplicar operadores ( UNION,...)  @año selecciona el atributo año del nodo contextual
y funciones de agregación (AVG, COUNT,...).
 @* selecciona todos los atributos del nodo contextual
 cuadro[1] selecciona el primer hijo cuadro del nodo

4.1 Modelo de datos 


contextual
cuadro[@año=1907] selecciona todos los hijos cuadro del nodo
modelo de datos en que se sustenta XQuery es el modelo de datos contextual que tengan un atributo año con valor 1907.
de XPath.
Debes conocer
XPath modela un documento XML como una estructura /*Añadir contenido
jerárquica en forma de árbol. El árbol está formado por nodos,
y hay siete tipos de nodos: raíz, elemento, texto, atributo, espacio
de nombres, instrucción de procesamiento y comentario. 4.3 Primeras consultas
/*Añadir imagen XQuery
Una consulta XQuery es una expresión que lee una secuencia
Los principales nodos de la estructura jerárquica o en árbol en un de datos en XML y devuelve como resultado otra secuencia de
documento XML son: datos en XML, donde:

 Nodo raíz o /. Es el primer nodo del documento.  Una secuencia es un conjunto ordenado de cero o más
 Nodo elemento. Cualquier elemento de un documento ítems.
XML. Cada nodo elemento posee un padre y puede o no  Un ítem es cualquier tipo de nodo del árbol XML o un
tener hijos. En el caso de que no tenga hijos, es un nodo valor atómico.
hoja.
 Nodo texto. Cualquier elemento del documento que no Las funciones que se pueden invocar para referirnos a colecciones
esté marcado con una etiqueta de la DTD del documento y documentos dentro de la BD son las siguientes:
XML.
 collection(camino de la colección)
 doc(camino del documento) /* Añadir imagen

Así por ejemplo: En el siguiente recurso didáctico dispones de más ejemplos de


consultas XQuery, utilizando expresiones FLOWR.
 La consulta collection(/Books): devuelve el contenido de
la colección de ruta absoluta /Books. /*Añadir imagen
 La consulta doc(/Empresa.xml): devuelve el documento
/Empresa.xml completo.
4.5 XQuery Update Facility
Otros ejemplos de consultas XQuery basadas en expresiones El lenguaje XQuery solo proporciona expresiones para la
XPath son los siguientes: realización de consultas sobre documentos XML, pero no su
actualización (inserción, modificación o eliminación de nodos).
 La consulta collection(/Books)//book/title devuelve los
nodos title de todos los libros ( book) de la colección XQuery Update Facility es una extensión de XQuery que permite
/Books la actualización de documentos mediante las cláusulas insert,
 Si se utilizan espacios de nombres o namespaces, entonces delete, replace y rename.
la consulta anterior se redactaría de la siguiente forma:
declare namespace t = El funcionamiento de las cláusulas de XQuery Update es el
http://www.qizx.com/namespace/Tutorial; siguiente:
collection(/Books)//t:book/t:title
 La consulta doc(/Empresa.xml)//nombre devuelve todos  insert. Permite la inserción de uno o varios nodos antes
los nodos nombre del documento /Empresa.xml (before) o después (after) del nodo indicado. También se
puede insertar al principio (as first into) o al final del
Diferentes ejemplos de consultas XQuery ejecutadas directamente documento (as last into).
sobre una sencilla BD XML denominada 'Cursillos'  delete. Elimina uno o varios nodos del documento.
 replace. Tiene dos funciones:
/*Añadir ejemplos o Modificar el valor del nodo
4.4 Expresiones FLWOR 
o Modificar el nodo completo
rename. Renombra un nodo (elemento, atributo o
Los ejemplos de consultas XQuery vistos en el apartado anterior,
instrucciones de proceso) sin afectar a su contenido.
son la manera más sencilla de realizar búsquedas y selecciones de
nodos concretos en una BD XML. Pero existe otra manera mucho
A continuación, te mostramos dos ejemplos sencillos, uno de insert y
más potente de realizar este trabajo, mediante lo que se denomina
otro de delete:
consultas o expresiones FLWOR (leído como flower), siendo
FLWOR las siglas de For, Let, Where, Order y Return.
 Eliminar la empresa de id=2 en el documento
Empresa.xml:
Se trata de una expresión que permite la unión de variables
delete node doc(Empresa.xml)//empresa[@id=2]
sobre conjuntos de nodos y la iteración sobre el resultado. Las
diferentes cláusulas de una expresión FLWOR son:  Insertar el nodo tipoAccesible/tipo al final del documento
/Aulas/aula3 insert node tipoAccesible/tipo as last into
doc(Aulas/aula3.xml)//aula
 For. Permite seleccionar los nodos que se quieren
consultar, guardándose su valor en una variable
(identificador que comienza por $). Al conjunto de /*Añadir imagen
valores de la variable se le llama tupla.
Ejemplos de actualizaciones usando XQuery Update:
 Let. (opcional). Asocia valores a variables.
 Where (opcional). Permite filtrar los resultados según una
/*Añadir contenido
condición.
 Order (opcional). Permite ordenar la secuencia de valores
Para saber más
o resultados. /*Añadir resumen
 Return. Genera los valores de salida o devueltos.

En la siguiente imagen, puedes ver un ejemplo de una consulta


(izquierda) donde aparecen las 5 cláusulas. La consulta devuelve
5 Trabajar con colecciones
los nombres de los cursos con 20 plazas, ordenados por nombre de
curso (derecha). y documentos desde Java
/*Añadir imagen El API principal para trabajar con una base de datos XML de
Qizx en un entorno de desarrollo Java, la proporciona el paquete
Una expresión FLWOR vincula variables a valores con las com.qizx.api, que permite, entre otras cosas, realizar las siguientes
cláusulas for y let y utiliza esos vínculos para crear nuevas tareas:
estructuras de datos XML.
 crear la BD XML,
A continuación, se muestra otro ejemplo de consulta XQuery. La  abrir y cerrar conexiones a la BD,
siguiente consulta (izquierda) devuelve los nombres de los cursos  importar/crear colecciones y documentos, y
con cuota mensual (derecha). Como cuota es un atributo del  realizar consultas con XQuery.
elemento precio, recuerda que se le antecede con un carácter @.
A continuación, te indicamos algunas de las clases e interfaces del
paquete com.qizx.api de más interés: En el siguiente ejemplo puedes ver un método que realiza la
conexión o apertura a una base de datos XML, y si no existe la crea
 Interface Library. Representa una BD XML o una y después la abre.
conexión a una BD XML.
 Interface LibraryManager. Representa el gestor de las BDs. /*Añadir imagen
Permite gestionar grupos de BDs XML.
 Clase Configuration. Inicializa y configura un LibraryManager, Si observas el ejemplo anterior (valor devuelto por el método),
permitiendo su creación, apertura, etc.. verás que en Qizx, un objeto Library representa dos cosas:
 Interface LibraryMember. Representa un miembro de una
BD XML, esto es, colección o documento.  La base de datos XML
o Algunas sub_interfaces son: Collection, Document,  Una conexión concreta a la base de datos o Library XML
NonXMLDocument.
 Interface Collection. Para gestionar colecciones y Debes conocer
sub_colecciones que contienen documentos XML.
 Interface Document. Representa documentos XML bien En el paquete API (com.quizx.api) encontrarás una explicación
formados y almacenados en una BD XML. más detallada de la dualidad del interface Library: como Base de
o Al ser un LibraryMember (miembro de una datos y como conexión en el apartado Library
Library), puede tener propiedades (metadatos)
que pueden consultarse.
 Clase Index. Para crear índices en una BD XML y 5.2 Cerrar conexiones
especificar sus parámetros. Podemos cerrar la conexión de una BD o Library concreta, mediante
el método close() de la interface Library, o cerrar todas las conexiones
Otros paquetes de interés son: a las bases de datos de un grupo, mediante el método
closeAllLibraries() de la interface LibraryManager.
 El paquete org.xml.sax. Proporciona las clases e interfaces
para el API SAX, que es un componente de la API de Te detallamos cada caso:
Java para el procesamiento de documentos XML, como
por ejemplo el interface XMLReader.  Cerrar una conexión. El método Library.close() cierra la
 El paquete com.qizx.xdm. Proporciona clases e interfaces conexión a una BD particular. Si ha comenzado alguna
para el análisis y procesamiento de documentos XML, transacción, no se podrá invocar close(), solo se podrá
como por ejemplo la clase DocumentParser. invocar commit() o rollback(), por lo que antes de invocar
close(), debemos comprobar mediante el método
En el siguiente recurso didáctico encontrarás un tutorial con los Library.isModified() si la base de datos está inmersa en una
pasos a seguir para la integración de Qizx en el IDE NetBeans, y transacción.
poder hacer uso de las clases e interfaces comentadas  Cerrar todas las conexiones. El método
anteriormente. LibraryManager.closeAllLibraries(int tiempo) cierra todas las
conexiones a BD del mismo grupo y libera los recursos.
/*Añadir imagen Mediante el parámetro int tiempo, se le puede indicar el
tiempo en milisegundos que debe esperar el sistema antes

5.1 Creación de la BD de realizar la desconexión de aquellas Library o bases de


datos en las que haya alguna transacción sin finalizar.

XML. Establecer Pasado ese tiempo, se generará de forma automática un


rollback(), se deshacen las operaciones, en aquellas
transacciones que no hayan finalizado aún.
conexiones
En general, la conexión de una aplicación Java a una base de datos En el siguiente ejemplo, puedes ver cómo realizar la desconexión o
XML se realizará mediante el API proporcionado por el propio cierre tanto de una BD particular, como de todo un grupo de bases
gestor XML. de datos o Library.

Para crear una BD XML y establecer una conexión se utilizan /*Añadir imagen
métodos del interface LibraryManager.

 Crear la BD XML. El método createLibrary(String nombreBD,


File directorioBD) crea la BD de nombre nombreBD
5.3 Crear colecciones
localizada físicamente en el directorio directorioBD, Para crear colecciones se usan los métodos:
directorio que debe existir y estar vacío. Si el
parámetro directorioBD se pasa como valor null, la BD se  createCollection(String ruta).Método de la interface Library.
creará en un subdirectorio del grupo con nombre Crea una colección en la BD, cuya posición dentro de la
nombreBD. base de datos es la que indica el parámetro ruta, siendo ruta
 Establecer conexión. El método openLibrary(String un camino o path absoluto en la BD.
nombreBD) abre una nueva sesión o conexión a la BD de  createChildCollection(String nombre). Método de la interface
nombre nombreBD. También es posible, indicar parámetros Collection. Crea una sub_colección dentro de una
de autentificación de usuario, si se ha establecido un colección, denominada nombre.
Control de Accesos a la Library o BD.
/*Añadir imagen
/*Añadir imagen
Por ejemplo, en el siguiente segmento de código se estaría creando
dentro de la Library o base de datos bd una colección situada dentro 5.5 Creación de una BD
de la base de datos en la posición indicada por ruta. Observa que,
previamente se comprueba si ya existe esa colección dentro de la XML e importación de
base de datos.
colecciones y
/*Añadir imagen
documentos
Otros métodos útiles al llenar una Library con colecciones y
5.4 Añadir documentos documentos, o bien trasladar colecciones y documentos de una
Library a otra son los siguientes:
Para añadir documentos se utiliza el método:
 Library.getMember(String rutaAbsoluta): devuelve el miembro
 importDocument(String documentoRuta, Tipo fuente). Método
de la
especificado en esa ruta de la BD, un LibraryMember
interface Library. Existen diferentes métodos para importar
(documento o colección), o bien null si no existe ese
documentos XML a una BD XML, que se diferencian
miembro.
fundamentalmente en el Tipo de los documentos fuente
 Library.getDocument(String rutaAbsoluta): devuelve el documento
indicados como segundo parámetro: java.io.File, java.net.URL,
especificado en esa ruta de la BD, un Document o bien null
org.xml.sax.InputSource, etc. En todos los casos, la fuente
si no existe.
debe contener un documento XML bien formado. Uno de
 Library.getCollection(String rutaAbsoluta): devuelve colección
estos métodos es:
o importDocument(String documentoRuta, File fichero). especficada en esa ruta de la BD, una Collection o bien null
Importa un documento a la base de datos si no existe.
mediante un análisis o parsing de un fichero de  Library.getName(): devuelve el nombre de la Library o base de

texto XML ubicado en fichero. datos.


 Si ya existe un documento con la  LibraryMember.getPath(): devuelve la ruta completa del

misma ruta en la BD, se sustituye por miembro en esa BD.


los nuevos contenidos.  LibraryMember.getName(): devuelve el nombre del miembro
 Si la colección que contiene este dentro de su colección sin '/', excepto si es la colección
documento no existe, se crea raíz.
automáticamente.  LibraryMember.isDocument(): devuelve verdadero si el
miembro es un documento.
/* Añadir imagen  LibraryMember.isCollection(): devuelve verdadero si el
miembro es una colección.
El siguiente código Java, es un ejemplo de cómo importar  Collection.getChildren(): devuelve un iterador, un
documentos mediante el método importDocument(): LibraryMemberIterator, sobre los miembros de esa colección
(documentos o colecciones).
/* Añadir imagen  LibraryMemberIterator.iter.moveToNextMember(): devuelve
verdadero si accede al siguiente miembro.
Qizx necesita analizar un documento XML con el fin de poder  LibraryMemberIterator.getCurrentMember(): devuelve el mimbro
importarlo a la base de datos. El primer paso del análisis consiste actual.
en comprobar que se trata de un documento bien formado.
También se puede realizar su validación, mediante la En este apartado, verás el ejemplo completo de cómo crear una
comprobación del DTD. Si falla este paso, fallará la importación. base de datos XML desde un entorno Java, y llenarla con
Con Qizx, se puede utilizar lo que se conoce como catálogo XML colecciones y documentos existentes, esto es, importando
para realizar este análisis o comprobaciones, sin necesidad de colecciones y documentos a la base de datos.
acceder a direcciones externas u otras localizaciones que puedan
suponer un fallo si no las encuentra en el sistema local. Recuerda tener desconectado el Library Group en QizxStudio
cuando ejecutes tus programas Java.
Qizx incluye la biblioteca resolver.jar, conocida como resolución
del catálogo XML, que forma parte del proyecto Apache XML En el siguiente recurso didáctico se explica cómo crear desde Java
Commons, de manera que todos los métodos una BD XML y llenarla con colecciones y documentos.
Library.importDocument() son catálogos XML habilitados. Por lo
tanto, basta con especificar el correspondiente importDocument() y /*Añadir contenido
dejar que mediante resolver.jar se realice la resolución, análisis o
parsing.

Debes conocer 5.6 Eliminar colecciones y


Consulta el API para conocer los diferentes métodos
documentos
Para eliminar colecciones y documentos se pueden utilizar los
importDocument() que puedes utilizar. Lo encontrarás en el
métodos:
apartado Library
 Método de la interface Library.
deleteMember(String ruta).
Elimina el miembro de la BD indicado mediante el
parámetro ruta, que será la ruta absoluta dentro de la BD.
Si se trata de una colección, elimina también de forma
recursiva todos sus documentos y sub_colecciones.
 Método de la interface LibraryMember. Es
delete().
equivalente al método anterior, es decir, es equivalente a  El método Item.getNode() que obtiene el valor de un nodo
Library.deleteMember(getPath()). XML (objeto tipo Node) tras la evaluación de una consulta
XQuery compilada.
Al igual que otras operaciones de actualización, para que tenga  El método XMLSerializer.serializeToString() que permite
efecto permanente, debe ir seguida de una confirmación o commit(). serializar como una cadena un nodo XML.
 El método Expression.bindImplicitCollection() que permite
Por ejemplo, si bdNombre vale Libros (BD creada anteriormente con escribir consultas con rutas o paths las cuales no van
qizxStudio, el siguiente segmento de código borra cada una de las precedidas por las expresiones collection(XXX) o doc(YYY).
colecciones de esta base de datos que se hayan indicado en el array
String[] coleccionNombre = {"/Authors","/Books"}
Por ejemplo, usando bindImplicitCollection() se puede utilizar como
/*Añadir imágenes expresión: //book/title en vez de collection(/Books) //book/title

Si por ejemplo, ruta vale /Publishers/Pocket.xml, lo que estaríamos  El método Expression.bindVariable() que permite vincular una
borrando con la sentencia bd.deleteMember(ruta); sería exactamente el secuencia de Items a una variable.
documento Pocket.xml.
A continuación, dispones de un ejemplo detallado de consultas
¿Y cómo eliminar toda la base de datos? Para ello, puedes XQuery desde una aplicación Java. Las consultas se realizan sobre
utilizar: la BD Cursillos que creaste anteriormente. Las consultas que se
ejecutan están almacenadas como scripts en ficheros de extensión .xq
 el método de la interface
deleteLibrary(String bdNnombre)
dentro del directorio C:\BDCursillosXML\cursillos_query\.
LibraryManager, que elimina físicamente la BD. También puedes probar con este mismo programa las consultas 7.xq
y 8.xq que vienen con la distribución Qizx Free Engine Edition y
que encontrarás en la carpeta de instalación dentro del directorio
\docs\samples\book_queries\. En este caso, la BD a utilizar será
5.7 Consultar documentos Tutorial.
¿Se utiliza el lenguaje XQuery para realizar consultas a la BD
XML desde una aplicación Java? La respuesta es sí, pero será /* Proyecto java
necesario realizar los siguientes pasos para procesar una
consulta desde Java: Debes conocer

 Compilar la consulta o expresión XQuery mediante el Es importante que conozcas las posibilidades del interface Expression
método Library.compileExpression(). Si la compilación se y del interface ItemSequence. Consulta el API (com.quizx.api)
realiza sin errores (CompilationException), devolverá un
objeto Expression.
 Evaluar la expresión o consulta compilada mediante el
método Expression.evaluate(). Si la evaluación se realiza sin 5.8 Actualizar documentos.
errores (EvaluationException), devolverá el resultado en Aunque dependiendo del sistema de BD XML pueden existir
forma de un ItemSequence. diferentes formas de actualizar documentos, la manera más sencilla
 Iterar sobre la secuencia obtenida. Un ItemSequence de hacerlo es mediante Update XQuery, la extensión del lenguaje
permite iterar sobre una secuencia de Items, donde un XQuery que permite inserciones, eliminaciones y
Item es un valor atómico o un nodo XML. modificaciones de nodos de los documentos XML.

Por ejemplo: Con Qizx, independientemente del método utilizado para la


actualización, ésta siempre implica sustituir el documento
 Expresión 3+4 : se evalúa como el valor atómico 7 prácticamente en su totalidad. Esto es así debido a que de esta
 Expresión collection("/Books")//book/title: se evalúa como una forma se consigue optimizar la velocidad de las consultas.
secuencia de nodos title
Para ejecutar una consulta de actualización desde Java se
Un iterador siempre tiene un método moveToNextItem() que mueve la siguen básicamente los mismos pasos que para una consulta normal
posición del cursor al siguiente elemento y un getCurrentItem() que XQuery:
devuelve el elemento encontrado en la posición actual del cursor.
 Compilar la consulta de actualización mediante
Por tanto, los pasos anteriores suponen las siguientes sentencias de Library.compileExpression() obteniendo un objeto Expression.
código:  Evaluar la consulta de actualización compilada mediante
Expression.evaluate() obteniendo un ItemSequence.
Expression exprcompilada =
bd.compileExpression(scriptConsulta); A continuación dispones de un ejemplo detallado de actualización
ItemSequence resultado = exprcompilada.evaluate(); XQuery desde una aplicación Java. La actualización consiste en
añadir dos nodos empresa al documento /Empresa.xml de la BD
while (resultado.moveToNextItem()) {
Cursillos. La consulta de actualización está almacenada como un
Item resul = resul.getCurrentItem();
script en el fichero 12update_insert.xq dentro del directorio
/* Manipular resultado*/ C:\BDCursillosXML\cursillos_query\.
} En ese directorio dispones de otros scripts de actualización para
realizar eliminaciones y modificaciones, que puedes probar desde
Otros métodos útiles en el procesamiento de una consulta son el mismo programa. (13update_delete.xq, 14update_replace_node_value.xq,
los siguientes: 15update_rename_varios_nodos.xq)
Podemos asociar una especificación de indexado a una BD XML,
/*Añadir contenido de manera que ésta, se aplicará a todos sus documentos. Una
especificación de indexado puede contener:
El siguiente ejemplo actualiza un documento de la colección
Authors, insertando un nuevo pseudónimo al autor que se pasa como  Valores para parámetros generales.
parámetro al script. El script de actualización está almacenado dentro  Especificaciones para índices full-text.
del directorio de instalación de Qizx:  Reglas para el reconocimiento de valores numéricos y de
docs\samples\programming\edit\pseudonym.xq.
fecha en el contenido de elementos y atributos.
La BD utilizada es Tutorial. Para esta actualización se usa la
interface QName, que permite gestionar nombres calificados.
Pero ¿qué es realmente una especificación de indexado? Una
Observa el script pseudoynm.xq, que viene con tu distribución
especificación de indexado es un documento XML con la
descargada, para comprobar que todas las referencias a QName lo
siguiente estructura:
hacen con Q mayúscula. Además, observa cómo se utiliza una
consulta de actualización con sentencias alternativas if-else para
 El elemento raíz tiene el nombre indexing.
detectar errores en el proceso de actualización.
 El elemento indexing contiene los atributos que definen las
condiciones generales.
/*Añadir contenido
 Contiene una lista de reglas aplicables a los elementos o
atributos.

6 Indexación En el manual del paquete de instalación puedes ver un ejemplo de


especificación de indexado en la ruta
Como cualquier otra BD XML, Qizx utiliza índices para optimizar docs/manual/indexing.html#d0e4192.
y aumentar la velocidad de las consultas realizadas a la BD.
Qizx proporciona una especificación de indexado por defecto, que
De manera predeterminada, Qizx indexa la mayor parte de la se puede editar con QizxStudio y personalizar.
información disponible en documentos XML: elementos,
atributos, nodos, y texto completo. Esto se realiza Si creamos una especificación de indexado nueva para una BD:
automáticamente, por lo tanto, en la mayoría de los casos no hay
necesidad de especificar explícitamente nuevos índices.  Habrá que guardar el documento XML de la
especificación junto a la BD o Library, de manera que
Qizx soporta los siguientes tipos de índices: ésta se iniciará al crear la BD, utilizándose de forma
automática cuando se añaden documentos.
 Índices elemento. Dado un nombre de elemento, este  Se deben incluir en ella las reglas que pone Qizx en su
índice devuelve todos los elementos XML en todos los especificación por defecto, ya que, en otro caso, éstas se
documentos de una BD con este nombre. perderán
 Índices de atributos. Dado un nombre de atributo y un
valor, este índice devuelve todos los elementos que Debes conocer
tienen un atributo con este nombre y valor. Hay tres Las reglas de especificación de indexado por defecto de Qizx las
tipos de índices de atributos, de acuerdo con el tipo del puedes ver en la siguiente ruta del paquete de instalación:
valor del atributo: texto, numéricos y de fecha / hora. docs/manual/indexing.html#d0e4615
o Texto. Por defecto, todos los valores de los
atributos están indexados como cadenas o En la imagen ampliable, puedes ver las diferentes opciones que
texto. proporciona QizxStudio para gestionar índices en una BD:
o Numérico. Si el valor se puede convertir al
tipo double, entonces se añade como índice  Modificar la especificación de indexado actual.
atributo numérico.
 Exportar la especificación de indexado a un fichero .xml.
o Fecha/Hora. Si el valor se puede convertir al
 Reconstruir los índices.
tipo date-time, entonces se añade como índice
 Optimizar la BD, esto es, optimiza su almacenamiento y
date/time.
los índices de la BD.
 Índices de contenido simple. Dado un nombre de
 Optimizar de forma rápida la BD, esto es, en un tiempo
elemento y un valor, este índice devuelve todos los
limitado.
elementos que tienen un contenido simple
correspondiente a este valor.
/*Añadir imagen
 Índices Full-text. Dada una palabra, este índice devuelve
todos los nodos de texto que contienen una ocurrencia de
esta palabra.
6.2 Re-Indexar una BD
Para utilizar índices diferentes a los predeterminados, habrá que
establecer lo que se denomina una especificación de indexado. Esto
lo vamos a ver en el siguiente apartado
desde Java
Para reindexar una BD XML de Qizx será necesario un objeto de la
clase com.qizx.api.Indexing.

6.1 Especificaciones de  Cada objeto Indexing es una especificación de indexado


con las reglas y parámetros necesarios para construir
indexado índices en una BD o Library.
 El método Indexing.parse(InputSource source) analiza la o Desbloquea todos los objetos de la BD,
especificación de indexado contenida en el texto XML previamente bloqueados.
del parámetro source. o Después de un rollback() se refresca o actualiza
el estado de la BD, de manera que se reflejan
Además, se necesitan los siguientes métodos de Library: los cambios realizados por otras transacciones.

 Define las reglas de indexado


Library.setIndexing(Indexing ind). En Qizx, todas las operaciones de actualización sobre una BD o
para esa BD o Library, especificadas en el parámetro ind. Library, para que tengan efecto permanente, deben ir seguidas de una
Normalmente va seguida de un reindexado, que se realiza confirmación o commit(). Por ejemplo, después de realizar una
mediante el método reIndex(). consulta de actualización, para que permanezcan los cambios es
 Library.reIndex(). Reconstruye y reorganiza los índices de necesario realizar un commit(), tal y como refleja el siguiente código.
una BD
/* Añadir imagen
En el siguiente enlace tienes un ejemplo de reindexado de la BD
Tutorial. Las especificaciones de indexado están escritas en el Por otra parte, al cerrar una conexión a una BD es necesario
archivo indexing.xml que viene con el paquete de instalación y que comprobar si hay alguna transacción en curso, de manera que, si
encontrarás en la carpeta de instalación dentro del directorio hay alguna en curso, para poder cerrar la BD habrá que cancelar la
docs\samples\programming\reindex\. transacción actual.

El código que refleja de forma clara este hecho es el siguiente:


13. Gestión de transacciones
/*Añadir imagen
En muchos de los ejemplos que has visto, ha estado presente el
concepto de transacción: conjunto de sentencias que se ejecutan
formando una unidad de trabajo, de forma indivisible, de manera 14. Tratamiento de excepciones
que se ejecutan todas o no se ejecuta ninguna.
Una excepción es un suceso excepcional que ocurre durante la
Mediante la gestión de transacciones, los gestores XML ejecución de un programa y que interrumpe su ejecución o flujo
proporcionan un acceso concurrente a los datos almacenados, normal de sentencias. El origen o causa de una excepción es un
mantienen la integridad y seguridad de los datos, y proporcionan error en el programa.
un mecanismo de recuperación de la base de datos ante fallos.
Gestionando de manera adecuada las posibles excepciones del
Qizx soporta transacciones que cumplen el criterio ACID: programa, podemos construir programas robustos, que pueden
continuar su ejecución sin que el problema les afecte, o bien
 Atomicidad: Se deben cumplir todas las operaciones de finalizar de manera no abrupta.
la transacción o no se cumple ninguna; no puede quedar a
medias. En Qizx, la clase que contiene los diferentes tipos de
 Consistencia: La transacción solo termina si la base de excecpiones es QizxException del paquete com.qizx.api. Esta clase
datos queda en un estado consistente. extiende a Exception, superclase de todas las excepciones del API
 Isolation (Aislamiento): Las transacciones sobre la y sus constructores son:
misma información deben ser independientes, para que
no interfieran sus operaciones y no se produzca ningún  QizxException(String message).Construye un mensaje con la
tipo de error. razón o causa de excepción. El código del error es
 Durabilidad. Cuando la transacción termina el resultado indefinido.
de la misma perdura, y no se puede deshacer, aunque  QizxException(String message, Throwable cause). Construye un
falle el sistema. mensaje con la razón o causa de excepción, y la
excepción. El código del error es indefinido.
 QizxException(QName errorCode, String message). Construye un

6.3 Los métodos commit() y mensaje con la razón de la excepción y un código de


error XQuery.

rollback() En el siguiente segmento de código, puedes ver el ejemplo de un


/*Añadir imagen método que puede generar excepciones que deben ser capturadas.
En este caso, se utiliza throws, de manera que si se produce un error
Los métodos para gestionar transacciones en Qizx los proporciona en la ejecución del método, error que puede ser originado al
la interface Library y son: intentar cerrar la conexión de un objeto Library o bien todas las
Library de un grupo, el método no se encarga de resolverlo, sino que
 commit(). Confirma la transacción actual. Si este método se deja el tratamiento de la excepción al bloque desde donde se hace
completa sin errores, las actualizaciones realizadas en la la llamada.
transacción garantizan la persistencia, y se hacen visibles
a otras sesiones. /*Añadir imagen
o Una vez confirmada, desbloquea todos los
objetos de la BD, previamente bloqueados. Tres subclases directas de QizxExcepction son:
o Finalizada la transacción, el estado de la BD
también refleja los cambios realizados  CompilationException.Excepciones debidas a errores en la
posiblemente por otras transacciones. compilación de consultas a la BD
 rollback(). Cancela la transacción actual.  DataModelException. Excepciones debidas a manipulación de
documentos XML en la BD.
 EvaluationException.
Excepciones debidas a errores en la
ejecución de una consulta.

En el siguiente apartado verás un ejemplo de captura de


excepciones CompilationException.

Tratamiento de excepciones en Java


/*Añadir imagen

6.4 Excepciones en el
procesamiento de
consultas
Cuando se procesa una consulta XQuery o una consulta de
actualización XQuery, pueden ocurrir errores en el proceso de
compilación y evaluación de la expresión de consulta, que suponen
el lanzamiento de excepciones.

Estas excepciones las puedes gestionar mediante dos subclases


directas de la clase QizxException:

 CompilationException .Se lanza cuando hay errores de


compilación en una expresión de consulta. Los mensajes
asociados pueden ser: el error, una advertencia o
warning, y la descripción o detalle del error. Podemos
gestionar esos errores mediante los siguientes métodos
o getErrorCount() devuelve el número actual de
errores.
o getMessages() devuelve una lista de errores o
warnings
 EvaluationException. Se lanza cuando hay errores en la
ejecución de una expresión XQuery.

Por ejemplo, el siguiente código muestra un método que compila


una expresión de consulta y controla posibles errores, almacenando
en un array de tipo Message los posibles errores de compilación,
Observa que en este caso, el tratamiento de la excepción se realiza
mediante un bloque try-catch, y que en caso de que se produzca se
captura la lista de errores.

/*Añadir imagen
Tema 7. Creación de componentes
visuales
1. Concepto de Las propiedades son un tipo específico de atributos que representan
características de un componente que afectan a su apariencia o a su
componente. comportamiento. Son accesibles desde fuera de la clase y forman
parte de su interfaz. Suelen estar asociadas a un atributo interno.

Características Una propiedad no es exactamente un atributo público, sino que


tiene asociados ciertos métodos que son la única manera de poder
Un componente software es una clase creada para ser reutilizada y modificarla o devolver su valor y que pueden ser de dos tipos:
que puede ser manipulada por una herramienta de desarrollo de
aplicaciones visual. Se define por su estado que se almacena en un  getter: permiten leer el valor de la propiedad. Tienen la
conjunto de propiedades, las cuales pueden ser modificadas para estructura:
adaptar el componente al programa en el que se inserte. También
tiene un comportamiento que se define por los eventos ante los public <TipoPropiedad> get<NombrePropiedad>( )
que responde y los métodos que ejecuta ante dichos eventos.
si la propiedad es el método getter se implementa así:
Los componentes tienen una interfaz bien definida formada por sus
propiedades y métodos, y se distribuyen mediante un paquete
instalable que contiene todo lo necesario para su funcionamiento. public boolean is<NombrePropiedad>()
Además, deben ser independientes de otras bibliotecas o
componentes.  setter: permiten establecer el valor de la propiedad. Tiene
la estructura:
Para que una clase sea considerada un componente debe cumplir
ciertas normas: public void set<NombrePropiedad>(<TipoPropiedad>
valor)
 Debe poder modificarse para adaptarse a la aplicación en
la que se integra. Si una propiedad no incluye el método set entonces es
 Debe tener persistencia, es decir, debe poder guardar el una propiedad de sólo lectura.
estado de sus propiedades cuando han sido modificadas.
 Debe tener introspección, es decir, debe permitir a un Por ejemplo, si estamos generando un componente para
IDE que pueda reconocer ciertos elementos de diseño crear un botón circular con sombra, podemos tener, entre
como los nombres de las funciones miembros o métodos otras, una propiedad de ese botón que sea color, que
y definiciones de las clases, y devolver esa información. tendría asociados los siguientes métodos:
 Debe poder gestionar eventos.
public void setColor(String color)
El desarrollo basado en componentes tiene, además, las siguientes public String getColor()
ventajas:
Función principal de un componente: La principal
 Es mucho más sencillo y se realiza en menos tiempo y función de un componente es recoger en una entidad que
con un coste inferior. sea fácilmente reutilizable un segmento que código con
 Se disminuyen los errores en el software ya que los una funcionalidad cerrada. Aporta ventajas como la
componentes se deben someter a un riguroso control de reutilización, disminución de costes al utilizar código ya
calidad antes de ser utilizados. hecho y mejorar la robustez y tolerancia a fallos de los
nuevos programas ya que suelen estar ampliamente
probados.

2 Propiedades y atributos
Como en cualquier clase, un componente tendrá definido un estado 3 Editores de propiedades
a partir de un conjunto de atributos. Los atributos son variables
definidas por su nombre y su que toman valores concretos. Una de las principales características de un componente es que, una
Normalmente los atributos son privados y no se ven desde fuera de vez instalado en un entorno de desarrollo, éste debe ser capaz de
la clase que implementa el componente, se usan sólo a nivel de identificar sus propiedades simplemente detectando parejas de
programación. tipo de datos
operaciones get/ set, mediante la capacidad denominada
introspección. 4 Eventos. Asociación de
El entorno de desarrollo podrá editar automáticamente cualquier
propiedad de los tipos básicos o de las clases Color y Font. Aunque
acciones a eventos
no podrá hacerlo si el tipo de datos de la propiedad es algo más
complejo, por ejemplo, si usamos otra clase, como Cliente. Para Se puede programar un componente para que reaccione ante
poder hacerlo tendremos que crear nuestro propio editor de determinadas acciones del usuario, como un clic del ratón o la
propiedades. pulsación de una tecla del teclado. Cuando estas acciones se
producen, se genera un evento que el componente puede capturar y
Un editor de propiedad es una herramienta para personalizar un procesar ejecutando alguna función. Pero no solo eso, un
tipo de propiedad en particular. Los editores de propiedades se componente puede también lanzar un evento cuando sea necesario
utilizan en la ventana Propiedades, que es donde se determina el y que su tratamiento se realice en otro objeto.
tipo de la propiedad, se busca de un editor de propiedades
apropiado, y se muestra el valor actual de la propiedad de una Los eventos que lanza un componente se reconocen en las
manera apropiada. herramientas de desarrollo y se pueden usar para programar la
realización de acciones.
La creación de un editor de propiedades usando tecnología Java
Para que el componente pueda reconocer el evento y responder
supone programar una clase que implemente la interfaz
ante el tendrás que hacer lo siguiente:
PropertyEditor, que proporciona métodos para especificar cómo se
debe mostrar una propiedad en la hoja de propiedades. Su nombre
 Crear una clase para los eventos que se lancen.
debe ser el nombre de la propiedad seguido de la palabra Editor:
 Definir una interfaz que represente el oyente (listener)
public Editor implements PropertyEditor {…} asociado al evento. Debe incluir una operación para el
procesamiento del evento.
Por defecto la clase PropertyEditorSupport que implementa  Definir dos operaciones, para añadir y eliminar oyentes.
PropertyEditor proporciona los editores más comúnmente Si queremos tener más de un oyente para el evento
empleados, incluyendo los mencionados tipos básicos, Color y Font. tendremos que almacenar internamente estos oyentes en
una estructura de datos como ArrayList o LinkedList:
Una vez que tengamos todos los editores, tendremos que
empaquetar las clases con el componente para que use el editor que public void addListener(Listener l)
hemos creado cada vez que necesite editar la propiedad. Así, public void removeListener(Listener l)
conseguimos que cuando se añada un componente en un panel y lo
seleccionemos, aparezca una hoja de propiedades, con la lista de  Finalmente, recorrer la estructura de datos interna
las propiedades del componente y sus editores asociados para cada llamando a la operación de procesamiento del evento de
una de ellas. El IDE llama a los métodos getters, para mostrar en todos los oyentes registrados. En resumen:
los editores los valores de las propiedades. Si se cambia el valor de
una propiedad, se llama al método setter, para actualizar el valor de /*Añadir imagen
dicha propiedad, lo que puede o no afectar al aspecto visual del
componente en el momento del diseño.

5 Introspección. Reflexión
3.1 Ejemplo de creación de Un componente, como cualquier otra clase dispone de una interfaz,
que es el conjunto de métodos y propiedades accesibles desde el
un componente entorno de programación. Normalmente, la interfaz la forman los
atributos y métodos públicos.
JavaBean con NetBeans
Para ilustrar cómo se implementa un componente con una La introspección es una característica que permite a las
herramienta como NetBeans, crearemos uno que permita almacenar herramientas de programación visual arrastrar y soltar un
la información de una persona, guardaremos por ejemplo, su componente en la zona de diseño de una aplicación y determinar
nombre, apellidos, teléfono y dirección: dinámicamente qué métodos de interfaz, propiedades y eventos del
componente están disponibles.
 El nombre se puede representar como una propiedad de
tipo String. Esto se puede conseguir de diferentes formas, pero en el nivel más
 Los apellidos también se pueden representar como una bajo se encuentra una característica denominada reflexión, que
propiedad de tipo String. busca aquellos métodos definidos como públicos que empiezan por
 El teléfono también puede ser una cadena de caracteres o get o set, es decir, se basa en el uso de patrones de diseño, es decir,
String. en establecer reglas en la construcción de la clase de forma que
 La dirección será una propiedad compuesta, por la mediante el uso de una nomenclatura específica se permita a la
dirección propiamente dicha, la población y la provincia. herramienta encontrar la interfaz de un componente. reflexión

Dado que la última propiedad no es simple, será necesario En JavaBeans la introspección se puede conseguir de varias
implementar un editor de propiedades para modificarla desde maneras:
NetBeans.
 Reflexión de bajo nivel, que utiliza patrones de diseño
para descubrir las características del componente por
medio de las posibilidades de reflexión del paquete Los componentes que implementarás en esta unidad emplearán la
java.lang.reflect. serialización por defecto por lo que debes tener en cuenta lo
 Examinando una clase asociada de información del siguiente:
componente (BeanInfo) que describe explícitamente sus
características para que puedan ser reconocidas.  La clase debe implementar la interfaz Serializable.
 Es obligatorio que exista un constructor sin argumentos.

6 Persistencia del
7 Propiedades simples e
componente
A veces, necesitamos almacenar el estado de una clase para que
indexadas
perdure a través del tiempo. A esta característica se le llama /*Añadir imagen
persistencia. Para implementar esto, es necesario que pueda ser
almacenada en un archivo y recuperado posteriormente. Una propiedad simple representa un único valor, un número,
verdadero o falso o un texto por ejemplo.
El mecanismo que implementa la persistencia se llama
serialización. Al proceso de almacenar el estado de una clase en un Tiene asociados los métodos getter y setter para establecer y rescatar
archivo se le llama serializar. ese valor. Por ejemplo, si un componente de software tiene una
propiedad llamada peso de tipo real susceptible de ser leída o
/*Añadir imagen escrita, deberá tener los siguientes métodos de acceso:

Al de recuperarlo después deserializar public real getPeso()


public void setPeso(real nuevoPeso)
/*Añadir imagen
Una propiedad simple es de sólo lectura o sólo escritura si falta uno
Todos los componentes deben persistir. Para ello, siempre desde el de los mencionados métodos de acceso.
punto de vista Java, deben implementar los interfaces
java.io.Serializable o java.io.Externalizable que te ofrecen la posibilidad de Una propiedades indexadas representa un conjunto de elementos,
serialización automática o de programarla según necesidad: que suelen representarse mediante un vector y se identifica
mediante los siguientes patrones de operaciones para leer o escribir
 Serialización Automática: el componente implementa la elementos individuales del vector o el vector entero (fíjate en los
interfaz Serializable que proporciona serialización corchetes del vector):
automática mediante la utilización de las herramientas de
Java Object Serialization. Para poder usar la interfaz public <TipoProp>[] get<NombreProp>()
Serializable debemos tener en cuenta lo siguiente: public void set<NombreProp> (<TipoProp>[] p)
o Las clases que implementan Serializable deben public <TipoProp> get<NombreProp>(int posicion)
tener un constructor sin argumentos que será public void set<NombreProp> (int posicion, <TipoProp> p)
llamado cuando un objeto sea "reconstituido"
desde un fichero .ser. Aquí tienes un ejemplo de propiedad indexada. El componente
o Todos los campos excepto static y transient son almacena un conjunto de miembros, a los que puedes acceder en
serializados. Utilizaremos el modificador conjunto o de uno en uno.
transient para especificar los campos que no
queremos serializar, y para especificar las /* Añadir imagen
clases que no son serializables (por ejemplo
Image no lo es).
o Se puede programar una serialización propia
si es necesario implementando los siguientes
métodos (las firmas deben ser exactas):
8 Propiedades compartidas y
private void
restringidas
writeObject(java.io.ObjectOutputStream out)
Los objetos de una clase que tiene una propiedad compartida o
throws IOException;
ligada notifican a otros objetos oyentes interesados, cuando el
private void
valor de dicha propiedad cambia, permitiendo a estos objetos
readObject(java.io.ObjectInputStream in)
realizar alguna acción. Cuando la propiedad cambia, se crea un
throws IOExcept;
objeto (de una clase que hereda de ObjetEvent) que contiene
información acerca de la propiedad (su nombre, el valor previo y el
 Serialización programada: el componente implementa nuevo valor), y lo pasa a los otros objetos oyentes interesados en el
la interfaz Externalizable, y sus dos métodos para guardar el cambio.
componente con un formato específico. Características:
o Precisa de la implementación de los métodos
La notificación del cambio se realiza a través de la generación de
readExternal () y writeExternal ().
o Las clases Externalizable también deben tener un un PropertyChangeEvent. Los objetos que deseen ser notificados del
cambio de una propiedad limitada deberán registrarse como
constructor sin argumentos.
auditores. Así, el componente de software que esté implementando
la propiedad limitada suministrará métodos de esta forma:
El BeanBox también puede verse como una demostración de cómo
public void addPropertyChangeListener (PropertyChangeListener deben comportarse las herramientas de desarrollo compatibles con
l) los JavaBeans. El BeanBox es una buena herramienta para
public void removePropertyChangeListener aprender a trabajar con Beans, aunque hoy en día ha sido sustituida
(PropertyChangeListener l) por NetBeans.

Los métodos precedentes del registro de auditores no identifican Bean Builder


propiedades limitadas específicas. Para registrar auditores en el En una versión mejorada del BeanBox. Con esta aplicación se
PropertyChangeEvent de una propiedad específica, se deben comenzó a dar un enfoque al proyecto que se desarrollaba, puesto
proporcionar los métodos siguientes: que al igual que el BeanBox permitía el enlazado de componentes
de manera gráfica y ver sus propiedades en tiempo que diseño, pero
a diferencia de él y lo que más interesante resultaba era que no
public void addPropertyNameListener (PropertyChangeListener l)
creaba archivos .ser para la serialización de los objetos sino que
public void removePropertyNameListener
utiliza archivos XML que podían ser entendidos por cualquier
(PropertyChangeListener l)
aplicación.
En los métodos precedentes, PropertyName se sustituye por el nombre
de la propiedad limitada. Los objetos que implementan la interfaz
Netbeans
PropertyChangeListener deben implementar el método propertyChange().
Es la apuesta actual de Oracle para crear y utilizar Beans.
Este método lo invoca el componente de software para todos sus
Proporciona una base completa para todo el ciclo de vida de
auditores registrados, con el fin de informarles de un cambio de
creación del Bean, y ayudas para la escritura de código para añadir
una propiedad.
propiedades, métodos getter y setter en propiedades simples,
complejas, compartidas o ligadas, o para la generación de eventos.
Una propiedad restringida es similar a una propiedad ligada salvo Además desde el administrador de la paleta es extremadamente
que los objetos oyentes que se les notifica el cambio del valor de la sencillo incorporar nuevos beans desde sus archivos .jar, e
propiedad tienen la opción de vetar cualquier cambio en el valor de incorporarlos a una aplicación solo precisa de un par de clics.
dicha propiedad.
Una de las características que aporta NetBeans es la creación de la
Los métodos que se utilizan con propiedades simples e indexadas clase BeanInfo para el componente. Una clase BeanInfo puede
que veíamos anteriormente se aplican también a las propiedades gestionar el modo en que el componente aparece en la herramienta
restringidas. Además, se ofrecen los siguientes métodos de registro de desarrollo de aplicaciones, indicando que propiedades deben
de eventos: aparecer, en primer lugar, cual es deben estar ocultas, si existe un
editor de propiedades asociado, etc, siendo además una de las bases
public void addPropertyVetoableListener (VetoableChangeListener de la introspección en Java.
l)
public void removePropertyVetoableListener Puedes generar un BeanInfo automáticamente desplegando el menú
(VetoableChangeListener l) contextual de la clase que implementa el componente en el
public void addPropertyNameListener (VetoableChangeListener l) inspector de proyectos de NetBeans y seleccionar Editor BeanInfo,
public void removePropertyNameListener si no existe te preguntará si quieres crearlo, cuando lo hagas se
(VetoableChangeListener l) creará la clase BeanInfo y se mostrará el código, si cambias al
diseño visual verás un panel que te permite gestionar gráficamente
Los objetos que implementa la interfaz VetoableChangeListener deben las propiedades de tu componente.
implementar el método vetoableChange(). Este método lo invoca el
componente de software para todos sus auditores registrados con el La principal ventaja de utilizar este método es que cuando nuestro
fin de informarles del cambio en una propiedad. componente hereda de una clase del tipo JPanel o JFrame, que son
bastante complejas, el manejo de las propiedades heredadas es
Todo objeto que no apruebe el cambio en una propiedad puede automático en el BeanInfo.
arrojar una PropertyVetoException dentro del método vetoableChange(),
para informar al componente cuya propiedad restringida hubiera

10 Empaquetado de
cambiado de que el cambio no se ha aprobado.

9 Herramientas para el componentes


desarrollo de componentes Una vez creado el componente, es necesario empaquetarlo para
poder distribuirlo y utilizarlo después. Para ello necesitarás el
paquete jar que contiene todas las clases que forman el
visuales. componente:

BeanBox  El propio componente.


Es la primera herramienta que se creó para trabajar con  Objetos BeanInfo.
componentes de JavaBeans y se podría definir como un contenedor  Objetos Customizer.
de Beans. Se proporcionaba desde la página web de Sun, y la  Clases de utilidad o recursos que requiera el componente,
documentación sobre JavaBeans se basaba en esta herramienta. etc.

En BeanBox se pueden escribir los Beans, para luego arrastrarlos Puedes incluir varios componentes en un mismo jar.
dentro de BeanBox y comprobar si funcionan como se esperaba.
El paquete jar debe incluir un fichero de manifiesto (con extensión
.mf) que describa su contenido, por ejemplo: /*Añadir imagen

Manifest-Version: 1.0 La base de datos se compone de una sola tabla de alumnos. Para
Name: demo/Componente.class cada alumno almacenamos su DNI, nombre, apellidos, dirección y
Java-Bean: True fecha de nacimiento
Name: demo/ComponenteBeanInfo.class
Java-Bean: False
Name: demo/ClaseAuxiliar.class
Java-Bean: False
11.2 Controlador o lógica del
Name: demo/Imagen.png
Java-Bean: False
modelo
En el entorno de la arquitectura MVC el controlador representa la
lógica de negocio de una aplicación. Encapsula las reglas de
Observa, en el fichero de manifiesto como la clase del componente
negocio en componentes que son fáciles de probar, permiten
va acompañada de Java-Bean: True, indicando que es un JavaBean.
mejorar la calidad del software y promueven la reutilización.

La forma más sencilla de generar el archivo jar es utilizar la El estado define el conjunto actual de valores del modelo e incluye
herramienta Limpiar y construir del proyecto en NetBeans, que métodos para cambiar estos valores. Estos métodos recogen parte
deja el fichero .jar perfectamente en el directorio /dist del proyecto, de la lógica de negocio. Deberían de ser independientes del
aunque siempre puedes recurrir a la orden jar y crearlo tu protocolo que se utilizara para acceder a ellos. Si resumimos la
directamente: encapsulación, calidad del software, reutilización e independencia
jar cfm Componente.jar manifest.mf Componente.class del protocolo obtenemos que los JavaBeans son la elección lógica
ComponenteBEanInfo.class ClaseAuxiliar.class Imagen.png para implementar estos componentes.
proyecto.jar
El componente se encarga de conectar con la base de datos y
ejecutar la sentencia deseada. A través de los métodos puede

11 Elaboración de un posicionarse en cada fila de la consulta y almacena en las


propiedades cada uno de los campos.

componente de ejemplo Las acciones definen los cambios permitidos para los estados en
respuesta a los eventos.
En el ámbito del acceso a datos que estudiamos en este módulo
formativo el uso de componentes está muy relacionado con el
mundo de la creación de aplicaciones web.
11.3 Estructura del JavaBean
La tecnología JSP utiliza una arquitectura denominado MVC Para la elaboración de un componente, debes tener muy claros
(Modelo-Victa-Controlador) cuya misión fundamental es separar el los pasos que debes dar.
desarrollo de la base de datos (Modelo), creada por ejemplo en
MySQL o cualquier otro gestor de bases de datos, de la interfaz 1. Creación del componente.
(Vista), que puede hacerse usando HTML en combinación con JSP, 2. Adición de propiedades.
de la lógica de negocio (Controlador) cuya implementación más 3. Implementación de su comportamiento.
sencilla y fácil de gestionar por JSP es un JavaBean que acceda a la 4. Gestión de los eventos.
base de datos y permita recuperar fácilmente la información que 5. Uso de componentes ya creados en NetBeans.
contiene.
En las siguientes secciones verás cómo se realizan estos pasos con
/* Añadir imagen el ejemplo que se acaba de exponer.

En el esquema el modelo sería la base de datos, la vista el apartado El componente a crear dispondrá de un constructor con las
de presentación de datos y el controlador está formado por la lógica siguientes características:
de la aplicación y acceso a datos.
 Propiedades que se corresponden con los campos de la
Para saber más tabla alumnos.
/*Añadir imagen  Clase auxiliar llamada Alumno que usaremos para crear
un vector de alumnos donde cargaremos el contenido de
Para ejemplificar el uso de componentes JavaBean de acceso a la tabla.
datos, supondremos que queremos crear una aplicación web que  Vector de alumnos.
muestre información de los alumnos del ciclo que mantendremos  Constructor (sin argumentos):
almacenados en una base de datos. De momento, nos encargaremos o Realiza la conexión a la base de datos.
de los apartados Modelo y Controlador, dejando la vista para otros o Realiza la consulta.
módulos del ciclo. o Guarda los resultados en una estructura local al
componente.
o Establece los valores de las propiedades.
11.1 Modelo o base de datos 
o Cierra la conexión.
Métodos para recorrer los resultados, recargando las
Nos basaremos en una base de datos muy sencilla que tendremos
almacenada en un servidor MySql. El código SQL para crear la propiedades cada vez que cambie. Usaremos los
base de datos sería: siguientes métodos:
o obtenerFilas():hace la consulta sobre la base de propiedad y su tipo, e insertar los métodos get y set de manera
datos y almacena los resultados sobre un vector automática:
interno actualizando los valores de las
propiedades. /*Añadir imagen
o SeleccionarFilas/(i): se posiciona en el elemento i
del vector y actualiza los valores de las Fíjate que si quisieras crear una propiedad indexada o restringida es
propiedades. muy sencillo de hacer, sólo hay que marcar la opción
o seleccionarDNI(String DNI): busca en el vector correspondiente y la herramienta genera el código base de los
interno el registro que coincide con el valor del métodos necesarios.
DNI y actualiza los valores de las propiedades.

11.6 Implementar el
11.4 Creación del
comportamiento
componente Con las propiedades listas, tenemos que programar el
Comenzamos creando un proyecto NetBeans nuevo de tipo Java comportamiento del componente. En principio la idea es que al
Application. Nos aseguramos de desmarcar las opciones Crear crear el componente se cargue el contenido de la tabla alumno de la
clase principal y Configurar como proyecto principal y ponemos de base de datos en un vector de uso interno que nos va a servir para
nombre al proyecto AlumnoBean, por ejemplo. no tener que estar conectándonos constantemente, recuerda que
estos componentes se usan en entornos cliente servidor con gran
Una vez creado el proyecto, le añadimos un archivo nuevo de tipo cantidad de accesos por parte de múltiples usuarios que pueden
Componente JavaBeans (si no lo encuentras en la lista que sale en llegar a saturar la base de datos. Por este motivo programaremos el
el menú contextual, haz clic en la opción Otros... para acceder al constructor para que realice la carga de datos. En un primer
resto de tipos de archivos). Puedes llamar a la clase AlumnoBean y momento los valores de las propiedades serán los del primer
al paquete en el que se ubicará Alumno. alumno recuperado.

/*Añadir imagen También generaremos un par de métodos para recuperar


información de un registro según su posición o según su clave.
Para que una clase se pueda considerar un componente debe
implementar la interfaz Serializable y, además, tener un A continuación, tienes el enlace al código de la clase con lo visto
constructor sin argumentos que vimos eran requisitos para la hasta el momento:
creación de componentes.
Añadiremos el siguiente código:
El proyecto cuenta con una propiedad de ejemplo que puedes
eliminar (su declaración y los métodos get y set de la propiedad), así /*Añadir imagen
como un gestor de escuchadores de cambio de propiedades que no
necesitaremos, quedando el siguiente código para empezar:

public class AlumnoBean implements Serializable {


11.7 Gestión de eventos
private PropertyChangeSupport propertySupport; Los componentes usan los eventos para generar acciones en
respuesta a los cambios del estado permitidos
public TemporizadorBean() {
propertySupport = new /* Añadir imagen
PropertyChangeSupport(this);
} Los componentes Java utilizan el modelo de delegación de eventos
} para gestionar la comunicación entre objetos como hemos visto.
Para ilustrar el uso de los eventos en un componente JavaBean le
añadiremos un comportamiento extra que añadirá un nuevo alumno

11.5 Añadir propiedades. a la base de datos. Tendrá como especial característica que cada
vez que se inserte un alumno nuevo que generará un evento que
El componente tendrá como propiedades las mismas que los alerte de esta modificación. Esto que en principio puede parecer
campos de la base de datos: DNI, nombre, apellidos, dirección y redundante no lo es en un entorno multiusuario en el que varios
fecha de nacimiento. clientes se conecten simultáneamente a la base de datos. Para poder
implementar esto necesitarás varias cosas:
La adición de propiedades en una clase Java se realiza simplemente
escribiendo el código de declaración del atributo privado (o  Una clase que implemente los eventos. Esta clase hereda
protegido) y los métodos getter y setter que son la base de la de java.util.EventObject. En el ejemplo se llamará
instrospección. BDModificadaEvent.
 Una interfaz que defina los métodos a usar cuando se
Si bien NetBeans proporciona una ayuda especial para realizar esta genere el evento. Implementa java.util.EventListener. En este
tarea. Con el cursor posicionado dentro de la clase (puedes reservar caso la gestión del evento se hará a través del método
capturarBDModificada de la interfaz BDModificadaListener.
una zona para el código de propiedades), haz clic con el botón
secundario y selecciona la opción Insertar Código..., en la lista También tenemos un objeto de tipo DBModificadaListener
que te saldrá elige Agregar propiedad. Se desplegará el siguiente llamado receptor que representa aquellos programas que
cuadro de diálogo en el que puedes escribir el nombre de la contienen al componente AlumnosBean susceptibles de
recibir el evento.
 Dos métodos, addEventoListener y removeEventoListener que
permitan al componente añadir oyentes y eliminarlos. En
principio se deben encargar de que pueda haber varios
oyentes. En nuestro caso sólo vamos a tener un oyente,
pero se suele implementar para admitir a varios.
 Implementar el método que lanza el evento,
asegurándonos de todos los oyentes reciban el aviso. En
este caso lo que se ha hecho es lanzar el método que se
creó en la interfaz que describe al oyente.

Finalmente, el código de la clase componente queda como aparece


a continuación:

/* Añadir imagen

11.8 Uso de componentes


previamente elaborados
en NetBeans
Una vez construido el componente es sencillo incorporarlo a la
paleta de NetBeans. Podemos hacerlo de diferentes formas:

 Si lo hemos desarrollado nosotros mismos (con


NetBeans) basta con utilizar Limpiar y Construir para
generar el fichero .jar con el componente.
 Si es un componente generado por otras personas, es
preciso disponer de la distribución en un fichero .jar.

Para probar el componente tendrás que importar el fichero .jar desde


las propiedades del proyecto con la nueva aplicación.

La gestión de eventos pasa por crear una clase que implemente la


interfaz BDModificadaListener.

public class AccedeBD implements BDModificadaListener{

en el constructor indicamos que vamos a estar escuchando si se


produce el evento:

AccedeBD(){
alumnos = new AlumnoBean();
alumnos.addBDModificadaListener((BDModificadaListener)t
his );
}

y sobreescribimos el método capturarBDModificada(BDModificadaEvent ev)


para escribir un mensaje cuando se produzca el evento.

public void capturarBDModificada(BDModificadaEvent ev) {


System.out.println("Se ha añadido un elemento a la base
de datos");
}

También podría gustarte