viernes, 3 de marzo de 2017

Base de datos orientados a objetos

7.1. VISIÓN GENERAL


En una base de datos orientada a objetos, la información se representa mediante objetos como los presentes en la programación orientada a objetos. Cuando se integra las características de una base de datos con las de un lenguaje de programación orientado a objetos, el resultado es un sistema gestor de base de datos orientada a objetos (ODBMS, object data base management system). Un ODBMS hace que los objetos de la base de datos aparezcan como objetos de un lenguaje de programación en uno o más lenguajes de programación a los que dé soporte. Un ODBMS extiende los lenguajes con datos persistentes de forma transparente, control de concurrencia, recuperación de datos, consultas asociativas y otras capacidades.
Las bases de datos orientadas a objetos se diseñan para trabajar bien en conjunción con lenguajes de programación orientados a objetos como Java, C#, Visual Basic.NET y C++. Los ODBMS usan exactamente el mismo modelo que estos lenguajes de programación.
Los ODBMS son una buena elección para aquellos sistemas que necesitan un buen rendimiento en la manipulación de tipos de dato complejos.
Los ODBMS proporcionan los costes de desarrollo más bajos y el mejor rendimiento cuando se usan objetos gracias a que almacenan objetos en disco y tienen una integración transparente con el programa escrito en un lenguaje de programación orientado a objetos, al almacenar exactamente el modelo de objeto usado a nivel aplicativo, lo que reduce los costes de desarrollo y mantenimiento.
Los orígenes del término orientados a objetos (abreviado OO) se remontan a los lenguajes de programación orientadas a objetos. Los lenguajes de programación OO tienen sus raíces en el lenguaje SIMULA 67, propuesto a finales de la década de 1960. En Simula, el concepto de clase agrupa la estructura de datos interna de un objeto en una declaración de clase, es decir, introduce en el lenguaje Algol los conceptos de objeto y de clase. Como Algol, Simula es un lenguaje fuertemente tipado para entornos compilados. Sin embargo, el primer lenguaje que popularizó la aproximación a objetos fue Smalltalk (1976); este puede considerarse una síntesis de años del lenguaje Liso, que ofrece una gran flexibilidad gracias a la interpretación, y de Simula, añadiendo el concepto de metaclase. Smalltalk ha podido responder a las necesidades de flexibilidad presentadas por el desarrollo de entornos de programación gráficos, favoreciendo la rápida creación de prototipos de interfaces de usuarios amigables. Fue utilizado con éxito en la primera estación gráfica de Xerox.
Con la llegada de las estaciones de trabajo en los años 80, han crecido numerosos lenguajes orientados a objetos inspirados en Simula o Smalltalk. Entre los lenguajes compilados, los más celebres son C++, Objective C y Eiffel, debido a la compatibilidad del lenguaje o del código producido con el lenguaje de programación C. La mayor parte de los lenguajes interpretados son extensiones del Lisp; por ejemplo, Loops y CLOS. Es interesante notar que la mayor parte de los lenguajes populares existentes se encuentran en curso de ampliación para convertirse en orientados a objetos, incluyendo al Cobol y Ada (más exactamente Ada 9X, que aporta la herencia).
En años recientes, han aparecido muchos prototipos experimentales y sistemas de bases de datos comerciales orientados a objetos. Entre los primeros se encuentran los sistemas ORION, OpenOODB, IRIS, ODE y el proyecto ENCORE/ObServer. Y entre los sistemas disponibles en el mercado están: GEMSTONE/OPAL de ServicLogic, ONTOS de Ontologic, Objectivity de Objectivity Inc., Versant de Versant Technologies, ObjecStore de Object Design y O2 de O2 Technology. Esta es solo una lista parcial de los prototipos experimentales y de los sistemas de bases de datos comerciales orientados a objetos. Desafortunadamente, es aún demasiado pronto para saber cuáles sistemas se instalarán como líderes en este campo.

7.2. TIPOS DE DATOS COMPLEJOS


Estos son los tipos de datos que soporta el SQL. Los sinónimos son palabras equivalentes al tipo de dato indicado. El tamaño indica cuánto ocupará una columna del tipo indicado.
Tipo de dato
Sinónimos
Tamaño
Descripción
BINARY
VARBINARY
BINARY VARYING
BIT VARYING
1 byte por carácter
Se puede almacenar cualquier tipo de datos en un campo de este tipo. Los datos no se traducen (por ejemplo, a texto). La forma en que se introducen los datos en un campo binario indica cómo aparecerán al mostrarlos.
BIT
BOOLEAN
LOGICAL
LOGICAL1
YESNO
1 byte
Valores Sí y No, y campos que contienen solamente uno de dos valores.
TINYINT
INTEGER1
BYTE
1 byte
Un número entero entre 0 y 255.
COUNTER
AUTOINCREMENT
Se utiliza para campos contadores cuyo valor se incrementa automáticamente al crear un nuevo registro.
MONEY
CURRENCY
8 bytes
Un número entero comprendido entre
– 922.337.203.685.477,5808 y 922.337.203.685.477,5807.
DATETIME
DATE
TIME 
8 bytes
Una valor de fecha u hora entre los años 100 y 9999
UNIQUEIDENTIFIER
GUID
128 bits
Un número de identificación único utilizado con llamadas a procedimientos remotos.
DECIMAL
NUMERIC
DEC
17 bytes
Un tipo de datos numérico exacto con valores comprendidos entre 1028 - 1 y - 1028 - 1. Puede definir la precisión (1 - 28) y la escala (0 - precisión definida). La precisión y la escala predeterminadas son 18 y 0, respectivamente.
REAL
SINGLE
FLOAT4
IEEESINGLE
4 bytes
Un valor de coma flotante de precisión simple con un intervalo comprendido entre – 3,402823E38 y – 1,401298E-45 para valores negativos, y desde 1,401298E-45 a 3,402823E38 para valores positivos, y 0.
FLOAT
DOUBLE
FLOAT8
IEEEDOUBLE
NUMBER 
8 bytes
Un valor de coma flotante de precisión doble con un intervalo comprendido entre – 1,79769313486232E308 y – 4,94065645841247E-324 para valores negativos, y desde 4,94065645841247E-324 a 1,79769313486232E308 para valores positivos, y 0.
SMALLINT
SHORT
INTEGER2
2 bytes
Un entero corto entre – 32.768 y 32.767.
INTEGER
LONG
INT
INTEGER4
4 bytes
Un entero largo entre – 2.147.483.648 y 2.147.483.647.
IMAGE
LONGBINARY
GENERAL
OLEOBJECT
Lo que se requiera
Desde cero hasta un máximo de 2.14 gigabytes.
Se utiliza para objetos OLE.
TEXT
LONGTEXT
LONGCHAR
MEMO
NOTE
NTEXT 
2 bytes por carácter. (Consulte las notas).
Desde cero hasta un máximo de 2.14 gigabytes.
CHAR
TEXT(n)
ALPHANUMERIC
CHARACTER
STRING
VARCHAR
CHARACTER VARYING
NCHAR
NATIONAL CHARACTER
NATIONAL CHAR
NATIONAL CHARACTER VARYING
NATIONAL CHAR VARYING 
2 bytes por carácter. (Consulte las notas).
Desde cero a 255 caracteres.

Un campo LONGTEXT se almacena siempre en el formato de representación Unicode.
Si se utiliza el nombre del tipo de datos TEXT sin especificar la longitud opcional (TEXT(25), por ejemplo), se crea un campo LONGTEXT. Esto permite escribir instrucciones CREATE TABLE que producirán tipos de datos coherentes con Microsoft SQL Server.
Un campo CHAR se almacena siempre en el formato de representación Unicode, que es el equivalente del tipo de datos NATIONAL CHAR del SQL de ANSI.
Si se utiliza el nombre del tipo de datos TEXT y se especifica la longitud opcional (TEXT(25), por ejemplo), el tipo de datos del campo es equivalente al tipo de datos CHAR. De ese modo, se mantiene la compatibilidad con versiones anteriores para la mayoría de las aplicaciones de Microsoft Jet, a la vez que se habilita el tipo de datos TEXT (sin especificación de longitud) para la alineación con Microsoft SQL Server.
Los caracteres de los campos definidos como TEXT (también conocidos como MEMO) o CHAR (también conocidos como TEXT(n) con una longitud específica) se almacenan en el formato de representación Unicode. Los caracteres Unicode requieren siempre dos bytes para el almacenamiento de cada carácter. Para las bases de datos de Microsoft Jet ya existentes que contengan principalmente datos de tipo carácter, esto puede significar que el tamaño del archivo de base de datos sea casi el doble cuando se convierta al formato Microsoft Jet 4.0. Sin embargo, la representación Unicode de muchos juegos de caracteres, antes denominados juegos de caracteres de un solo byte (SBCS), puede comprimirse fácilmente a caracteres de un solo byte. Si define una columna CHAR con el atributo COMPRESSION, los datos se comprimirán automáticamente a medida que se almacenen y se descomprimirán cuando se recuperen de la columna.

  

7.3. TIPOS ESTRUCTURADOS

 

Antes de SQL: 1999 el sistema de tipos de SQL consistía en un conjunto bastante sencillo de tipos predefinidos. SQL: 1999 añadió un sistema de tipos extenso a SQL, lo que permite los tipos estructurados y la herencia de tipos.
Los tipos estructurados permiten representar directamente los atributos compuestos de los diagramas E-R. Por ejemplo, se puede definir el siguiente tipo estructurado para representar el atributo compuesto nombre con los atributos componentes nombre pila y apellidos:


create type Nombre as 
(nombre_pila varchar(20), 
apellidos varchar(20))
final

De manera parecida, el tipo estructurado siguiente puede usarse para representar el atributo compuesto dirección:
create type Direccion as
(calle varchar(20),
ciudad varchar(20),
codigo_postal varchar(9))
not final

En SQL estos tipos se denominan tipos definidos por el usuario. La especificación final indica que no se puede crear subtipos de nombre, mientras que la especificación not final de dirección indica que se pueden crear subtipos de dirección. Ahora se pueden usar estos tipos para crear atributos compuestos en las relaciones, con sólo declarar que un atributo es de uno de estos tipos. Por ejemplo, se puede crear una tabla cliente de la siguiente manera.
create table cliente (
nombre Nombre,
direccion Direccion,
fecha_nacimiento date)

O bien, realizando una estructura más del tipo Cliente y generar la tabla a partir de ella:
create type TipoCliente as
(nombre Nombre,
direccion Direccion,
fecha_nacimiento date)
not final

create table client of TipoCliente

Se puede tener acceso a los componentes de los atributos compuestos usando la notación “punto”; por ejemplo, nombre.nombre_pila devuelve el componente nombre de pila del atributo nombre. El acceso al atributo nombre devolvería un valor del tipo estructurado Nombre.
La siguiente consulta ilustra la manera de tener acceso a los atributos componentes de los atributos compuestos. La consulta busca el apellido y la ciudad de cada cliente.


select nombre.apellido, direccion.ciudad
from cliente

En SQL: 1999 se usan funciones constructoras para crear valores de los tipos estructurados. Las funciones con el mismo nombre que un tipo estructurado son funciones constructoras de ese tipo estructurado. Por ejemplo, se puede declarar una función constructora para el tipo Nombre de esta manera:


create functionNombre(nombre_pila varchar(20), apellidos varchar(20))
returns Nombre
begin
set self.nombre_pila = nombre_pila;
set self.apellidos = apellidos;
end

De manera predeterminada, cada tipo estructurado tiene una función sin argumentos que configura los atributos con sus valores predeterminados. Cualquier otra función constructora hay que crearla de manera específica.
La instrucción siguiente ilustra la manera de crear una nueva tupla de la relación Cliente. Se da por supuesto que se ha definido una función constructora para Direccion, igual que la función constructora que se definió para Nombre.


insert into Cliente
values
(new Nombre(‘Martín’, ‘Gómez’),
new Direccion(‘Calle Mayor 20’, ‘Madrid’, ‘28045’),
date ‘22-8-1960’)


 
Herencia de tipos:
Supóngase que se tiene la siguiente definición de tipo para las personas:


create type Persona
(nombre varchar(20),
direccion varchar(20))

Puede que se desee almacenar en la base de datos información adicional sobre las personas que son estudiantes y sobre las que son profesores. Dado que los estudiantes y los profesores también son personas, se puede usar la herencia para definir en SQL los tipos estudiante y profesor:
create typeEstudiante
under Persona
(grado varchar(20),
departamento varchar(20))

create typeProfesor
under Persona
(sueldo Integer,
departamento varchar(20))

Tanto Estudiante como Profesor heredan los atributos de Personas.

Herencia de tablas:
Las subtablas de SQL se corresponden con el concepto de especialización / generalización de E-R Por ejemplo, supóngase que se define la tabla personas de la siguiente manera:



create tablepersonas of Persona

A continuación se puede definir las tablas estudiantes y profesores como subtablas de personas, de la manera siguiente:
create tableestudiantes of Estudiante
under personas
create tableprofesores of Profesor
under personas

Los tipos de las subtablas deben ser subtipos del tipo de la tabla madre. Por tanto, todos los atributos presentes en personas también están presentes en las subtablas.
Además, cuando se declaran estudiantes y profesores como subtablas de personas, todas las tuplas presentes en estudiantes y profesores pasan a estar también presentes de manera implícita en personas. Por tanto, si una consulta usa la tabla personas, no sólo encuentra tuplas directamente insertadas en esa tabla, sino también tuplas insertadas en sus subtablas, es decir, estudiantes y profesores. No obstante, esa consulta sólo puede tener acceso a los atributos que están presentes en personas.
SQL permite hallar tuplas que se encuentran en personas pero no en sus subtablas usando en las consultas “only personas” en lugar de personas. La palabra clave only también puede usarse en las sentencias delete y update. Sin la palabra clave only, la instrucción delete aplicada a una supertabla, como personas, también borra las tuplas que se insertaron originalmente en las subtablas (como estudiantes); por ejemplo, la instrucción:

delete from personas where P


Borrará todas las tuplas de la tabla personas, así como de sus subtablas estudiantes y profesores, que satisfagan P. Si se añade la palabra clave only a la instrucción anterior, las tuplas que se insertaron en las subtablas no se ven afectadas, aunque satisfagan las condiciones de la cláusulawhere.
SQL soporta dos tipos de conjuntos: arrays y multiconjuntos; los tipos array se añadieron en SQL:1999, mientras que los tipos multiconjuntos se agregaron en SQL:2003. Un multiconjunto es un conjunto no ordenado, en el que cada elemento puede aparecer varias veces.
Supóngase que se desea registrar información sobre libros, incluido un conjunto de palabras clave para cada libro. Supóngase también que se deseara almacenar almacenar el nombre de los autores de un libro en forma de array; a diferencia de los elementos de los multiconjuntos, los elementos de los arrays están ordenados, de modo que se puede distinguir el primer autor del segundo autor, etc. El ejemplo siguiente ilustra la manera en que se puede definir en SQL estos atributos como arrays y como multiconjuntos.
create type Editor as
(nombre varchar(20),
sucursal varchar(20))

create type Libro as
(titulo varchar(20),
array_autores varchar(20) array[10],
fecha_publicacion date,
editor Editor,
conjunto_palabras_clave varchar(20) multiset)

create table libros of Libro

Creación y acceso a los valores de los conjuntos:
En SQL:1999 se puede crear un array de valores de esta manera:
array[‘Silberschartz’, ‘Korth’, ‘Sudarshan’]
De manera parecida, se puede crear un multiconjunto de palabras clave de la manera siguiente:
multiset[‘Silberschartz’, ‘Korth’, ‘Sudarshan’]

Por lo tanto, se puede crear una tupla definido por la relación libros como:


insert into libros
values
(‘Compiladores’, array[‘Gómez’, ‘Santos’’],
new Editor(‘McGraw-Hill’, ‘Nueva York’),
multiset[‘análisis sintáctico’, ‘análisis’])

Se puede tener acceso a los elementos del array o actualizarlos especificando el índice del array, por ejemplo, array_autores[1].
Consulta de los atributos valorados como conjuntos
Ahora se considerará la forma de manejar los atributos que se valoran como conjuntos. Las expresiones que se valoran como conjuntos pueden aparecer en cualquier parte en la que pueda aparecer el nombre de una relación, como las cláusulas from.
Si se desea averiguar todos los libros que contengan las palabras “base de datos” entre sus palabras clave, se puede usar la consulta siguiente:
select titulo
form libros
where ‘base de datos’ in
(unnest(conjunto_palabras_clave))


Identidad de los objetos y tipos de referencia en SQL:

Los lenguajes orientados a objetos ofrecen la posibilidad de hacer referencia a objetos. Los atributos de un tipo dado pueden servir de referencia para los objetos de un tipo concreto. Por ejemplo, en SQL se puede definir el tipo Departamento con el campo nombre y el campo director, que es una referencia al tipo Persona, y la tabla departamentos del tipo Departamento, de la manera siguiente:


irecc type Departamento(
nombre varchar(20),
director ref(Persona) scope personas)

irecc table departamentos of Departamento

En este caso, la referencia está restringida a las tuplas de la tabla personas. La restricción del ámbito de referencia a las tuplas de una tabla es obligatoria en SQL, y hace que las referencias se comporten como las claves externas.

La tabla a la que hace referencia debe tener un atributo que guarde el identificador para cada tupla. Ese atributo, denominado atributo autorreferenciable (self-referential attribute), se declara añadiendo una cláusula irecc a la instrucción irecc table:

create table personas of Persona
ref is id_persona system generated

En este caso, id_persona es el nombre del atributo, no una palabra clave, y la instrucción system generated especifica que la base de datos genera de manera automática el identificador.
Para inicializar el atributo de referencia hay que obtener el identificador de la tupla a la que se va a hacer referencia. Se puede conseguir el valor del identificador de la tupla mediante una consulta. Por tanto, para crear una tupla con el valor de referencia, primero se puede crear la tupla con una referencia nula y luego definir la referencia de manera independiente:
insert into departamentos
values (‘CS’, null)
update departamentos set director = (select p.id_persona
from persona as p
where nombre = ‘Martín’)
where nombre = ‘CS’

Una alternativa a los identificadores generados por el sistema es permitir que los usuarios generen los identificadores. El tipo del atributo autoreferencial debe especificarse como parte de la definición de tipos de la tabla a la que se hace referencia, y la definición de la tabla debe especificar que la referencia está generada por el usuario (user generated):
irecc type Persona
(nombre varchar(20),
irección varchar(20))
ref using varchar(20)

create table personas of Persona
ref is id_persona user generated

Al insertar tuplas en personas hay que proporcionar el valor del identificador:
insert intopersonas (id_persona, nombre, irección) values
(‘01284567’, ‘Martín’, ‘Av del Segura, 23’)

Implementación de las características O-R:
Los sistemas de bases de datos relacionales orientadas a objetos son básicamente extensiones de los sistemas de bases de datos relacionales ya existentes. Las modificaciones resultan claramente necesarias en muchos niveles del sistema de base de datos.
Las interfaces de programas de aplicación como ODBC y JDBC se han extendido para recuperar y almacenar tipos estructurados; por ejemplo, JDBC ofrece el método getObject() que devuelve un objeto Java Struct, a partir del cual se pueden extraer los componentes del tipo estructurado. También es posible asociar clases de Java con tipos estructurados de SQL, y JDCB puede realizar conversiones entre los tipos.

Lenguajes de programación persistentes:

Los lenguajes de las bases de datos se diferencian de los lenguajes de programación tradicionales en que trabajan directamente con datos que son persistentes; es decir, los datos siguen existiendo una vez que el programa que los creó haya concluido. Las relaciones de las bases de datos y las tuplas de las relaciones son ejemplos de datos persistentes.
El acceso a las bases de datos es sólo un componente de las aplicaciones del mundo real. Mientras que los lenguajes para el tratamiento de datos como SQL son bastante efectivos en el acceso a los datos, se necesita un lenguaje de programación para implementar otros componentes de las aplicaciones como las interfaces de usuario o la comunicación con otras computadoras. La manera tradicional de realizar las interfaces de las bases de datos con los lenguajes de programación es incorporar SQL dentro del lenguaje de programación.

Los lenguajes de programación persistentes son lenguajes de programación extendidos con estructuras para el tratamiento de los datos persistentes. Los lenguajes de programación persistentes pueden distinguirse de los lenguajes con SQL incorporado, al menos, de dos maneras:
En los lenguajes incorporados el sistema de tipos del lenguaje anfitrión suele ser diferente del sistema de tipos del lenguaje para el tratamiento de los datos. Los programadores son responsables de las conversiones de tipo entre el lenguaje anfitrión y SQL. Hacer que los programadores lleven a cabo esta tarea presenta varios inconvenientes:
El código para la conversión entre objetos y tuplas opera fuera del sistema de tipos orientado a objetos y, por lo tanto, tiene más posibilidades de presentar errores no detectados.
La conversión en la base de datos entre el formato orientado a objetos y el formato relacional de las tuplas necesita gran cantidad de código. El código para la conversión de formatos, junto con el código para cargar y descargar datos de la base de datos, puede suponer un porcentaje significativo del código total necesario para la aplicación.
Por el contrario, en los lenguajes de programación persistentes, el lenguaje de consultas se halla totalmente integrado con el lenguaje anfitrión y ambos comparten el mismo sistema de tipos. Los objetos se pueden crear y guardar en la base de datos sin ninguna modificación explícita del tipo o del formato; los cambios de formato necesarios se realizan de manera transparente.
Los programadores que usan lenguajes de consultas incorporados son responsables de la escritura de código explícito para la búsqueda en la memoria de los datos de la base de datos. Si se realizan actualizaciones, los programadores deben escribir explícitamente código para volver a guardar los datos actualizados en la base de datos.
Por el contrario, en los lenguajes de programación persistentes, los programadores pueden trabajar con datos persistentes sin tener que escribir explícitamente código para buscarlos en la memoria o volver a guardarlos en el disco.
Sin embargo, los lenguajes de programación persistentes presentan ciertos inconvenientes que hay que tener presentes al decidir su conviene usarlos. Dado que los lenguajes de programación suelen ser potentes, resulta relativamente sencillo cometer errores de programación que dañen las bases de datos. La complejidad de los lenguajes hace que la optimización automática de alto nivel, como la reducción de E/S de disco, resulte más difícil. En muchas aplicaciones el soporte de las consultas declarativas resulta de gran importancia, pero los lenguajes de programación persistentes no soportan bien actualmente las consultas declarativas (SQL es un ejemplo).

Persistencia de objetos:
Los lenguajes de programación orientados a objetos ya poseen un concepto de objeto, un sistema de tipos para definir los tipos de los objetos y constructores para crearlos. Sin embargo, esos objetos son transitorios; desaparecen en cuanto finaliza el programa, igual que ocurre con las variables de los programas en C o Pascal. Si se desea transformar uno de estos lenguajes en un lenguaje para la programación de base de datos, el primer paso consiste en proporcionar una manera de hacer persistentes los objetos. Se han propuesto varios enfoques.
o   Persistencia por clases. El enfoque más sencillo, pero el menos conveniente, consiste en declarar que una clase es persistente. Todos los objetos de la clase lo son, por tanto, persistentes de manera predeterminada.
o   Persistencia por creación. En este enfoque se introducen una sintaxis nueva para crear los objetos persistentes mediante la extensión de la sintaxis nueva para la creación de los objetos transitorios. Por tanto, los objetos son persistentes o transitorios en función de la forma de crearlos. Varios sistemas de bases de datos orientados a objetos siguen este enfoque.
o   Persistencia por marcas. Una variante del enfoque anterior es marcar los objetos como persistentes después de haberlos creado. Todos los objetos se crean como transitorios pero, si un objeto tiene que persistir más allá de la ejecución del programa, hay que marcarlo como persistente de manera explícita antes de que éste concluya.
o   Persistencia por alcance. Uno o varios objetos se declaran objetos persistentes (objetos raíz) de manera explícita. Todos los demás objetos serán persistentes si (y sólo sí) se pueden alcanzar desde algún objeto raíz mediante una secuencia de una o varias referencias.
Por tanto, todos los objetos a los que se haga referencia desde (es decir, cuyos identificadores de objetos se guarden en) los objetos persistentes raíz serán persistentes. Pero también lo serán todos los objetos a los que se haga referencia desde ellos, y los objetos a los que éstos últimos hagan referencia serán también persistentes, etc.
Una ventaja de este esquema es que resulta sencillo hacer que sean persistentes estructuras de datos complejas con sólo declarar como persistente su raíz. Sin embargo, el sistema de base de datos sufre la carga de tener que seguir las cadenas de referencias para detectar los objetos que son persistentes, y eso puede resultar costoso.


Sistemas Java persistentes:

En años recientes el lenguaje Java ha visto un enorme crecimiento en su uso. La demanda de soporte de la persistencia de los datos en los programas de Java se incrementado de manera acorde. Los primeros intentos de creación de una norma para la persistencia en Java fueron liderados por el consorcio ODMG; posteriormente, el consorcio concluyó su esfuerzo, pero transfirió su diseño al proyecto Java Database Object (JDO), que coordibaba Sun Microsystems.
Entre sus características se hallan:
o   Persistencia por alcance. Los objetos no se crean explícitamente en la base de datos. El registro explícito de un objeto como persistencia hace que el objeto sea persistente. Además, cualquier objeto alcanzable desde un objeto persistente pasa a ser persistente.
o   Mejora del código de bytes. En lugar de declarar en el código Java que una clase es persistente, se especifica en un archivo de configuración (con terminación .jdo) las clases cuyos objetos se pueden hacer persistentes. Se ejecuta un programa mejorador específico de la implementación que lee el archivo de configuración y lleva a cabo dos tareas. En primer lugar, puede crear estructuras en la base de datos para almacenar objetos de esa clase. En segundo lugar, modifica el código de bytes (generado al compilar el código Java) para que maneje tareas relacionadas con la persistencia.
o   Asignación de base de datos. JDO no define la manera en que se almacenan los datos en la base de da datos subyacente. Por ejemplo, una situación frecuente es que los objetos se almacenen en una base de datos relacional. Por ejemplo, una situación frecuente es que los objetos se almacenen en una base de datos relacional. El programa mejorador puede crear en la base de datos un esquema adecuado para almacenar los objetos de las clases. La manera exacta en que lo hace depende de la implementación y no está definida por JDO. Se puede asignar algunos atributos a los atributos relacionales, mientras que otros se pueden almacenar de forma serializada, que la base de datos trata como si fuera un objeto binario. Las implementaciones de JDO pueden permitir que los datos relacionales existentes se vean como objetos mediante la definición de la asignación correspondiente.
o   Extensiones de clase. Las extensiones de clase se crear y se conservan de manera automática para cada clase declarada como persistente. Todos los objetos que se hacen persistentes se añaden de manera automática a la extensión de clase correspondiente a su clase. Los programas de JDO pueden tener acceso a las extensiones de clase e iterar sobre los miembros seleccionados. La interfaz iteradora ofrecida por Java se puede usar para crear iteradores sobre las extensiones de clase y avanzar por los miembros de cada extensión de clase. JDO también permiten que se especifiquen selecciones cuando se crea una extensión de clase y que sólo se capturen los objetos que satisfagan la selección.
La norma JDO se halla todavía en una etapa preliminar y sometida a revisión. Varias empresas ofrecen implementaciones de JDO.

Sistemas orientados a objetos y sistemas relacionales orientados a objetos


Las extensiones persistentes de los lenguajes de programación y los sistemas relacionales orientados a objetos se dirigen a mercados diferentes. La naturaleza declarativa y limitada potencia (comparada con la de los lenguajes de programación) del lenguaje SQL proporcionan una buena protección de los datos respecto de los errores de programación y hacen que las optimizaciones de alto nivel, como la reducción E/S resulte relativamente sencilla. Los sistemas relacionales orientados a objetos se dirigen a simplificar la realización de los modelos de datos y de las consultas mediante el uso de tipos de datos complejos. Entre las aplicaciones habituales están el almacenamiento y la consulta de datos complejos, incluidos los datos multimedia.
Los lenguajes declarativos como SQL, sin embargo, imponen una reducción significativa del rendimiento a ciertos tipos de aplicaciones que se ejecutan principalmente en memoria principal y realizan gran número de accesos a la base de datos. Los lenguajes de programación persistentes se dirigen a las aplicaciones de este tipo que tienen necesidad de un rendimiento elevado. Proporcionan acceso a los datos persistentes con poca sobrecarga y eliminan la necesidad de traducir los datos si hay que tratarlos con un lenguaje de programación. Sin embargo, son más susceptibles a deteriorar los datos debido a los errores de programación y no suelen disponer de gran capacidad de consulta. Entre las aplicaciones habituales están las bases de datos de CAD (Diseño asistido por computadora).
Los puntos fuertes de los diversos tipos de sistemas de bases de datos pueden resumirse de la manera siguiente:
Sistemas relacionales: tipos de datos sencillos, lenguajes de consultas potentes, protección elevada.
Bases de datos orientadas a objetos basadas en lenguajes de programación persistentes: tipos de datos complejos, integración con los lenguajes de programación, elevado rendimiento.
Sistemas relacionales orientados a objetos: tipos de datos complejos, lenguajes de consultas potentes, protección elevada.
Estas descripciones son válidas en general, pero hay que tener en cuenta que algunos sistemas de bases de datos no respetan estas fronteras. Por ejemplo, algunos sistemas de base de datos orientados a objetos construidos alrededor de lenguajes de programación persistentes se pueden implementar sobre sistemas de bases de datos relacionales o sobre sistemas de bases de datos relacionales orientados a objetos. Puede que estos sistemas proporcionen menor rendimiento que los sistemas de bases de datos orientados a objetos construidos directamente sobre los sistemas de almacenamiento, pero proporcionan parte de las garantías de protección más estrictas propias de los sistemas relacionales.


7.4. HERENCIA DE TABLAS

 

Herencia

La herencia puede hallarse en el nivel de los tipos o en el nivel de las tablas. En primer lugar se considerara la herencia de los tipos y después en   el nivel de las tablas.

Cada tabla almacena todos los atributos heredados y definidos localmente. Cuando se inserta una tupla se almacena solo en la subtabla en la que se inserta y su presencia se infiere en cada supertabla. El acceso a todos los atributos de una tupla es más rápido, dado que no   se requiere una reunión.
Ejemplo de herencia
Supóngase que se tiene la siguiente definición de tipo para las personas:
create type Persona
(nombre varchar(20),
direccion varchar(20))



Puede que se desee almacenar en la base de datos información adicional sobre las personas que son estudiantes y sobre las que son profesores. Dado que los estudiantes y los profesores también son personas, se puede usar la herencia para definir en SQL los tipos estudiante y profesor:
create type Estudiante
under Persona
(grado varchar(20),
departamento varchar(20))
create type Profesor
under Persona
(sueldo Integer,
departamento varchar(20))



Otro ejemplo:
Primer Método: Herencia de Tabla Única (Single Table Inheritance)
Una Tabla guarda todos los datos y se define una variable de Tipo.

Segundo Método: Herencia de Tablas Concretas (Concrete Table Inheritance)
Cada Clase utilizable se define en una tabla independiente con todas sus propiedades heredadas.

Tercer Método: Herencia de Tablas de Clases (Class Table Inheritance)
Se define una tabla para cada clase y no se incluyen sus propiedades heredadas.

Conclusión:
A lo que se refiere a la herencia de registros atreves de tablas tenemos que tener una tabla que se le denomina type (tipos) al que se le van a pasar los registros de otras tablas o subtablas.
Para comprender éste concepto muy interesante y útil para muchos casos veremos un ejemplo bastante sencillo. Crearemos una tabla llamada ciudades y otras capitales. Las capitales son también ciudades pero supongamos que necesitamos recuperar rápidamente los datos de las ciudades, sin pasar por un índice de tabla que contiene miles o millones de registros. Esa es la mayor virtud a mi punto de vista de las tablas heredades, si la usamos en los contextos correctos podríamos mejorar el rendimiento de una BD altamente concurrida que comience   a sufrir de bloqueos y retrasos importantes en el tiempo de lectura/escritura.
Comenzaremos creando la tabla padre con 3 campos
CREATE TABLE ciudades (
   nombre         text,
   poblacion     float,
   altura         int
);



Ya tenemos el padre, podemos crear un hijo a partir de él. Además le agregaremos 1 columna más que nos dirá a que departamento o estado pertenece ésa capital.
CREATE TABLE capitales (
   departamento           char(2)
) INHERITS (ciudades);

Procedemos a insertar los datos en las respectivas tablas
insert into ciudades values ('Fernando de la Mora', 24522, 25);
insert into ciudades values ('Lambaré', 34500, 135);
insert into ciudades values ('San Lorenzo', 16852, 120);

insert into capitales values ('Asuncion', 450000, 136, 'CN');
insert
into capitales values ('Encarnacion', 128000, 120, 'EN');

Seleccionando las tablas veremos los resultados y el comportamiento obtenido. El primer query retornará el siguiente conjunto de resultados.
"Fernando de la Mora";24522;25
"Lambaré";34500;135
"San Lorenzo";16852;120
"Asuncion";450000;136
"Encarnacion";128000;120

Obteniendo los siguiente con el segundo query
"Asuncion";450000;136;"CN"
"Encarnacion";128000;120;"EN"

Con esto obtenemos una reducción en la construcción del índice y ganaremos velocidad con ello además de un mejor orden conceptual de nuestras tablas. No sólo se puede heredar de un padre, es posible heredar de varias tablas, así teniendo la tabla hija todas las columnas de sus padres, y en caso que 2 o más padres tengan un columna con el mismo nombre éstas se fusionarán en la hija siempre y cuando sean del mismo tipo de dato.
Al utilizar ésta poderosa característica existen algunas consideraciones que hay que tener en cuenta para evitarnos sorpresas desagradables e inesperadas. Al crear tablas heredadas, no todas las características de la tabla se heredan. Por ejemplo, las claves primarias, foráneas, indices únicos. Según el roadmap se verá para implementarlo a futuro pero no es de prioridad alta por eso que viene retrasándose su implementación desde versiones antiguas.


  

7.5. TIPOS DE ARREGLOS EN MULTICONJUNTO en

 

SQL soporta dos tipos de conjuntos: arrays y multiconjuntos. Multiconjuntos es un conjunto no ordenado, en el que cada elemento puede aparecer varias veces. A diferencia de los elementos de los multiconjuntos, los elementos de los arrays están ordenados Por ejemplo se ilustra la manera en que se pueden definir en SQL, estos atributos valorados con arrays y multiconjuntos. create type Editor as (nombre varchar(20) sucursal vachar(20) create type Libro as (titulo vachar (20), array_autores vachar (20) array[10], fecha_publicacion date, editor Editor, conjunto_palabras_clave varchar(20) multiset) create table Los atributos multivalorados de los esquemas E-R se pueden asignar en SQL atributos valorados como multiconjuntos si el orden es importante se pueden usar los arrays de SQL en lugar de los multiconjuntos. • Creación y acceso a los valores de los conjuntos array[´silberschatz´,´Korth´, ´Sudarshan´] de manera parecida se puede crear un multiconjunto de palabras clave de la manera siguiente: multiset[´computadora´, ´base de datos´, ´SQL] Consulta de los atributos valorados como conjuntos´ Ahora se considerara la forma de manejar los atributos que se valoran como conjuntos. Las expresiones que se valoran como conjuntos pueden aparecer en cualquier parte en la que pueda aparecer el nombre de una relación, como las clausulas FROM. Al desanidar un arrays la consulta anterior pierde información sobre el orden de los elementos de consulta. Se pueden usar las clausulas UNESTED WITH ORDINALITY para obtener esta información. La clausulas WITH ORDINALITY genera un atributo adicional que se registra la posición del elemento en el arrays. Se puede usra una consulta parecida. Pero sin la cláusula WITH ORDINALITY, para generar la relación. Anidamiento y desanidamiento La transformación de una relación anidada en una forma con menos atributos de tipos relación (o sin ellos) se denomina desanidamiento.




7.6. IDENTIDAD DE LOS OBJETOS


Los lenguajes orientados a objetos ofrecen la posibilidad de hacer referencia a objetos. Los atributos de un tipo dado pueden servir de referencia para los objetos de un tipo concreto. Por ejemplo, en SQL se puede definir el tipo Departamento con el campo nombre y el campo director, que es una referencia al tipo Persona, y la tabla departamentos del tipo Departamento, de la manera siguiente:
create type Departamento(
nombre varchar(20),
director ref(Persona) scope personas)

create table departamentos of Departamento

En este caso, la referencia está restringida a las tuplas de la tabla personas. La restricción del ámbito de referencia a las tuplas de una tabla es obligatoria en SQL, y hace que las referencias se comporten como las claves externas.

La tabla a la que hace referencia debe tener un atributo que guarde el identificador para cada tupla. Ese atributo, denominado atributo autorreferenciable (self-referential attribute), se declara añadiendo una cláusula ref is a la instrucción create table:
create table personas of Persona
ref is id_persona system generated

En este caso, id_persona es el nombre del atributo, no una palabra clave, y la instrucción system generated especifica que la base de datos genera de manera automática el identificador.
Para inicializar el atributo de referencia hay que obtener el identificador de la tupla a la que se va a hacer referencia. Se puede conseguir el valor del identificador de la tupla mediante una consulta. Por tanto, para crear una tupla con el valor de referencia, primero se puede crear la tupla con una referencia nula y luego definir la referencia de manera independiente:

insert into departamentos
values (‘CS’, null)
update departamentos set director = (select p.id_persona
from persona as p
where nombre = ‘Martín’)
where nombre = ‘CS’

Una alternativa a los identificadores generados por el sistema es permitir que los usuarios generen los identificadores. El tipo del atributo autoreferencial debe especificarse como parte de la definición de tipos de la tabla a la que se hace referencia, y la definición de la tabla debe especificar que la referencia está generada por el usuario (user generated):
create type Persona
(nombre varchar(20),
direccion varchar(20))
ref using varchar(20)

create table personas of Persona
ref is id_persona user generated

Al insertar tuplas en personas hay que proporcionar el valor del identificador:

insert into personas (id_persona, nombre, direccion) values
(‘01284567’, ‘Martín’, ‘Av del Segura, 23’)


7.7. IMPLEMENTACIÓN DE LAS CARACTERÍSTICAS


Los sistemas de bases de datos relacionales orientadas a objetos son básicamente extensiones de los sistemas de bases de datos relacionales ya existentes. Las modificaciones resultan claramente necesarias en muchos niveles del sistema de base de datos.
Las interfaces de programas de aplicación como ODBC y JDBC se han extendido para recuperar y almacenar tipos estructurados; por ejemplo, JDBC ofrece el método getObject() que devuelve un objeto Java Struct, a partir del cual se pueden extraer los componentes del tipo estructurado. También es posible asociar clases de Java con tipos estructurados de SQL, y JDCB puede realizar conversiones entre los tipos.
La orientación a objetos constituye una nueva forma de pensar acerca de problemas empleando modelos que se han organizado tomando como base conceptos del mundo real.
Los modelos orientados a objetos son útiles para comprender problemas, comunicarse con expertos en esa aplicación, modelar empresas, preparar documentación y diseñar programas y bases de datos.
El beneficio principal no es un tiempo de desarrollo más reducido, el desarrollo orientado a objetos puede requerir más tiempo que el desarrollo convencional porque se pretende que promueva la reutilización futura y la reducción de los posteriores errores y el futuro mantenimiento.
Las bases de datos orientadas a objetos unen dos tecnologías:
La de las bases de datos y la de los lenguajes orientados a objetos. Los LPOO aportan gran capacidad en la manipulación de datos, pero no implementan el almacenamiento y consulta de grandes volúmenes de datos.
Por el contrario, las bases de datos convencionales aportan un dominio de las técnicas de almacenamiento y consulta de grandes volúmenes de datos, aunque su capacidad de manipulación es limitada.
Las bases de datos orientadas a objetos pretenden unir la capacidad de manipulación de datos de los LPOO con la capacidad de almacenamiento y consulta de los SGBD.



Desventajas de la BDOO

La inmadurez del mercado de BDOO constituye una posible fuente de problemas por lo que debe analizarse con detalle la presencia en el mercado del proveedor para adoptar una línea de producción sustantiva.
Es la falta de estándar en la industria orientado a objetos.

No hay comentarios:

Publicar un comentario