Cuando una aplicación guarda información en una base de datos, entonces aparece la pregunta de como guardar los datos de la memoria RAM en la base de datos. Aquí quiero presentar como poder transformar esta información de objetos a tablas y columnas en una base de datos.

Correspondencia entre tablas y clases

La creación de una tabla consiste en definir los tipos que se guardan en cada columna o campo como se denomina también. Una tabla es, por lo tanto, algo similar a una clase en un lenguaje de programación: un tipo compuesto. Una línea en una tabla se llama registro (record en inglés). Un registro contiene los datos y es, por lo tanto, parecido a una instancia de una clase.

Porque una tabla y sus registros tienen una relación similar a una clase y las instancias de esta clase, se encapsula a menudo una tabla de la base de datos con una clase en el lenguaje de programación. Esta correspondencia surge de forma natural si has diseñado bien tu programa. Cada objeto guarda “sus” datos; sólo que las guarda en la base de datos en lugar de la memoria RAM. Lo lógico es que los datos de todas las instancias de una clase se encuentran en una tabla y todas las instancias de otra clase en otra tabla.

Clave primaria

Un concepto importante en las bases de datos son las claves primarias. Una clave primaria es un identificador único a cada registro. Un objeto de programa que guarda sus datos en una base de datos meramente necesita guardar este identificador para obtener un acceso rápido a sus datos.

Es una buena práctica en la programación de guardar cada dato en sólo un sitio. Por eso, un objeto, que encapsula un registro de una a tabla, no debería guardar los datos en variables miembro sino solamente en la base de datos – excepto la clave primaria, por supuesto. Excepciones se pueden justificar por un aumento de la velocidad o porque el objeto usa los datos para calcular algo.

Hay pocas situaciones en que una tabla no tiene una o varias columnas que representan la clave primaria igual como hay pocos objetos dentro de un proyecto a que no se hace referencia alguna. No sorprende que un nombre popular y recomendable para la columna que contiene la clave primaria es “Id”.

Una clave primaria es normalmente un número entero. A veces este número es también un índice. Por ejemplo, el número de una orden de compra puede ser la clave primaria en una tabla. En tablas con poco tráfico también puede ser recomendable usar cadenas de texto, ya que son más inteligibles. Un ejemplo puede ser una tabla de configuración con atributos y valores.

Estructuras jerárquicas

Como ya hemos dicho, cada tabla en la base de datos corresponde normalmente a una clase. Un problema surgen con las variables miembro de una clase que no tienen un tipo simple, ya que no se pueden definir tipos propios para un campo en una base de datos. No puedo definir que una columna que contenga otra tabla. Esta falta de jerarquía es una restricción importante de las base de datos relacionales. Hay formas de guardar datos que no tienen esta limitación. Por ejemplo, un elemento XML puede contener muchos otros elementos anidados.

Si nos enfrentamos con estructuras de datos complejos, podemos tener tres soluciones posibles:

  1. Un objeto contiene otro objeto por orden y claridad y podemos “aplanar” la estructura de datos.
  2. Dos objetos “colaboran” y guardan referencias entre sí.
  3. Un objeto es contenedor del otro.

A continuación detallaremos como se pueden implementar estas estructuras en una base de datos.

Aplanar la jerarquía

Un objeto contiene otro objeto por orden y claridad y podemos “aplanar” la estructura de datos. Por ejemplo, una clase coche puede contener una clase motor. La clase motor contiene los elementos tipo de combustible y cilindrada. Como cada coche sólo usa un tipo de combustible y tiene una cilindrada, podemos considerar que estas características del motor son también características del coche. Una tabla que corresponde a la clase coche tendría una columna para el tipo de combustible y otra para la cilindrada. El nivel de jerarquía de la clase motor ya no aparece. La hemos aplanado.

Colaboración de objetos

Otro caso tenemos cuando no guardamos los datos dentro de nuestro objeto sino meramente una referencia a otro objeto que contiene estos datos. Por ejemplo, tenemos una clase combustible que guarda las características del combustible. La clase coche, en lugar de guardar estos datos, sólo guarda una referencia, es decir, un puntero a una instancia de combustible. Esta construcción se usa típicamente cuando la relación de datos no es uno a uno. Un coche usa un tipo de combustible, pero un tipo de combustible puede ser usado por varios coches.

Otra característica de esta construcción es que un componente puede cambiarse de forma independiente. Si cambiamos el tipo de motor, entonces la referencia de combustible de este coche apuntaría a otra instancia de la clase combustible. En cambio, si cambiamos la composición del combustible, todos los coches usarían esta nueva versión sin ningún cambio en sus datos. En términos de programación orientado a objetos se diría que la clase coche y combustiblecolaboran“: sus instancias pueden existir de forma independiente pero mantienen enlaces.

La implementación de una estructura de colaboración se hace mediante dos tablas. Cada tabla representa los datos de una clase. La referencia se establece por un campo en que se guarda la clave primaria del registro relacionado en la otra tabla. Por ejemplo, en la tabla COCHES hay una columna combustible_id que guarda el valor del campo id de la tabla COMBUSTIBLES. El campo COMBUSTIBLES.id es la clave primaria de la tabla COMBUSTIBLES. De esta forma, un registro que guarda los datos de un coche tiene un enlace con los datos del combustible que usa.

Mediante el siguiente comando en SQL se pueden obtener los datos de las dos tablas como se fuera una:

select * from COCHES, COMBUSTIBLES
        where COCHES.id = <aquí mi id de coche guardado en la memoria RAM>
          and COMBUSTIBLE.id = COCHES.combustible_id

Contenedor de objetos

Ya hemos visto un tipo de contenedor trivial: el coche contiene un motor. Es trivial porque la relación es uno a uno. Sin embargo, un contenedor generalmente contiene un número variable de elementos. Nuestra clase coche puede contener una lista de factura. Cada vez que el coche sale del taller, se añade una nueva factura a la lista.

La relación entre contenedor es uno a n. A contrario de una colaboración, el contenedor no guarda referencias sino alberga las instancias de los elementos que contiene. Muchas veces no tiene sentido que uno de estos elemento exista fuera del contenedor. Por ejemplo, las facturas están asociados al coche que fue reparado.

La implementación en la base de datos sería también mediante dos tablas: la tabla COCHES para la clase coche y otra tabla FACTURAS para la clase factura. La tabla COCHES no guardaría nada sobre las facturas. Lo que, sí, debe tener es un identificador para cada coche. Esto sería la clave primaria de esta tabla. En la tabla FACTURAS se guardarían las facturas de todos los coches. (Recuerda que una tabla guarda todas las instancias de un objeto.) Una de las columnas de esta tabla guarda la clave primaria del coche. Este datos sería obligatorio ya que una factura no puede existir sin coche.

Nótese una diferencia entre el lenguaje de programación y la base de datos: En el lenguaje de programación es el contenedor que tiene una referencia a sus elementos – en forma de una variable miembro. En la base de datos es al revés: es el elemento que tiene una referencia al contenedor. Esta referencia es la clave primario del contenedor del elemento.

En esta construcción se encuentra a menudo, que la clave primaria de un elemento está constituido por varios campos. Cada coche tiene uno a n facturas. Así los números de facturas está repetido en varios coches – muchos coches tendrán al menos una factura con el número de factura uno. Sin embargo, cada coche sólo tiene cada número de factura una vez. Así la clave primaria de la tabla FACTURAS, que identifica un registro particular, sería la unión de la clave primaria del coche a que se refiere la factura y el número de factura de este coche.

Conclusión

Hemos visto que la correspondencia entre tablas en la base de datos y datos de objetos es relativamente directa. Una tabla es como una clase que sólo permite tipos simples para las variables miembro. Una jerarquía de datos se establece mediante las claves primarias. Las bases de datos relacionales obligan a que esta referencia va del contenido al contenedor y no al revés como en un lenguaje de programación.

Referencias

Anuncios