miércoles, 20 de febrero de 2013

Un proyecto en NetBeans de principio a fin (III). Diseño del modelo de datos

En esta emocionante tercera parte, nos centraremos en el modelado de datos; o dicho de otro modo, en el proceso de crear un modelo conceptual de nuestro sistema de almacenamiento mediante la identificación y definición de las entidades que requiere nuestro sistema, y de las relaciones entre esas entidades. El modelo de datos debe contener todos los parámetros del diseño lógico y físico necesarios para generar un script usando el Lenguaje de Definición de Datos (o DDL por sus siglas en inglés) que posteriormente usaremos para crear una base de datos.

DISEÑANDO EL MODELO DE DATOS

En esta parte del tutorial vamos a utilizar una interesante herramienta gráfica (que se instala con la distribución que elegimos de MySQL) llamada MySQL Workbench. Este software nos permite crear modelos de datos, conseguir representaciones visuales de scripts de SQL mediante ingeniería inversa, hacer ingeniería directa para obtener esquemas de base de datos a partir de modelos visuales y sincronizar modelos con un servidor MySQL en ejecución.

Empezaremos creando un modelo Entidad-Relación; y cuando hayamos identificado y definido las entidades y sus relaciones, obtendremos un script DDL para convertir el modelo en un esquema de base de datos que, posteriormente, conectaremos con el IDE de NetBeans.

Identificando entidades para el modelo de datos

Para comenzar a identificar las entidades que necesitaremos para el modelo de datos, vamos a tirar del caso de uso que planteamos cuando diseñamos la aplicación:

El cliente visita la página de bienvenida y selecciona una categoría de producto. El cliente navega por los productos en la página de la categoría seleccionada y añade un producto a su carrito. El cliente continúa comprando y selecciona otra categoría. El cliente añade varios productos de esta categoría a su carrito. El cliente selecciona la opción "ver carro" y actualiza las cantidades de los productos en la página de carro. El cliente verifica el contenido del carro y procede al pago. El cliente ve el precio del pedido y otras informaciones, rellena datos personales y envía sus detalles. El pedido se procesa y el cliente es llevado a página de confirmación. La página de confirmación proporciona un número de referencia único para el pedido y un resumen del pedido.

Los elementos destacados podrían ser los candidatos que consideremos en el modelo de datos. Aunque echando un vistazo más a fondo podríamos prescindir del carrito como entidad, ya que los datos que proporciona (productos y cantidades) se encuentran igualmente en el pedido una vez que éste es procesado. En realidad, como se verá más adelante, el carrito no es más que un mecanismo para retener una sesión de usuario temporalmente mientras el cliente hace su compra. Así pues nos quedaremos con la siguiente lista: cliente, categoría, producto y pedido. Pero como no tengo el ánimo suficiente para cambiar de idioma cada vez que hable del modelo de datos del tutorial original, en adelante nos referiremos a ellos como customer, category, product y order... que para eso hemos estudiado idiomas... Y así, con estos cuatro elementos podemos comenzar a construir un Diagrama Entidad-Relación.

Creando un Diagrama Entidad-Relación (ERD)

Para crear el esquema de affablebean seleccionamos "New Model" en el menú de Archivo. Luego pulsamos en icono "+" que se encuentra a la derecha de la cabecera Physical Schemata. Esto nos mostrará un nuevo panel en la parte inferior que nos permitirá especificar configuraciones para el nuevo esquema. Podemos introducir lo siguiente:

 Schema Name: affablebean
 Default Collation: utf8 – utf8_unicode_ci
 Comments: Esquema usado con la aplicación AffableBean

Queda creado así el nuevo esquema.

A continuación podemos empezar a crear entidades. Para ello podemos hacer doble click en el icono "Add Diagram" que aparece en la parte superior. Esto nos sitúa en un canvas sobre el que podemos ir arrastrando los elementos de nuestro esquema (tablas, relaciones...). Cuando hacemos doble click en estos elementos podemos acceder a su configuración (en la parte inferior de la pantalla).

Empezaremos así modelando las tablas de nuestro esquema (las entidades). Crearemos una tabla para cada entidad que hemos localizado en el caso de uso. En la primera pestaña de configuración pondremos su nombre y, adicionalmente una descripción. En el desplegable Engine seleccionamos "InnoDB". El motor InnoDB provee de soporte para claves externas. Deberíamos tener algo así en el área de diseño:


A continuación tendremos que añadir propiedades a las entidades. Para eso hacemos doble click en cada tabla, y en la parte inferior de la pantalla podremos acceder a la pestaña de Columnas. Para cada tabla configuraremos los siguientes atributos:

customer

Column Datatype PK NN UN AI
id INT
name VARCHAR(45)
email VARCHAR(45)
phone VARCHAR(45)
address VARCHAR(45)
city_region VARCHAR(2)
cc_number VARCHAR(19)

category

Column Datatype PK NN UN AI
id TINYINT
name VARCHAR(45)

customer_order

Column Datatype PK NN UN AI Default
id INT
amount DECIMAL(6,2)
date_created TIMESTAMP CURRENT_TIMESTAMP
confirmation_number INT

* Llamamos "customer_order" a esta tabla porque "order" es una palabra reservada de MySQL y no se puede usar para denominar a una tabla.

product

Column Datatype PK NN UN AI Default
id INT
name VARCHAR(45)
price DECIMAL(5,2)
description TINYTEXT
last_update TIMESTAMP CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

A estas alturas deberíamos ver algo así en pantalla:


Ha llegado el momento de identificar las relaciones entre nuestras entidades. Echando un vistazo a las entidades que aparecen actualmente en el diagrama, y teniendo en mente la problemática del negocio, podemos identificar un par de relaciones uno a muchos (1:n) y una o dos relaciones muchos a muchos (n:m).

Veamos primero las relaciones uno a muchos. Parecen bastante obvias un par de relaciones:
  • Una categoría debe tener uno o más productos
  • Un cliente puede haber realizado uno o más pedidos
Incorporar estas dos relaciones a nuestro diagrama ER no debería ser un problema. Tenemos un elemento visual (un botón con la leyenda "1:n") que podemos usar para incorporar las relaciones a nuestro esquema. Tenemos que pinchar primero en la tabla que contendrá la clave externa y luego pinchar sobre la tabla origen de la referencia. Por ejemplo, nosotros queremos que la tabla product tenga una foreign key (fk) a la tabla category, así que pinchamos sobre la tabla product y luego sobre la tabla category. La relación queda establecida, y en la tabla product aparece una nueva columna y un nuevo índice.

Haciendo doble click sobre la relación podemos editar sus características. Podemos cambiar el título que aparecerá en el diagrama y, en la pestaña de Foreign Key, podemos ver y modificar la cardinalidad, la ordinalidad y el tipo de la relación.

La Cardinalidad define si la relación entre dos objetos es 1:1 o 1:n.

La Ordinalidad determina si la relación entre dos entidades debe existir necesariamente para preservar la integridad del modelo.

El Tipo de la relación, que puede ser "identificativa" o "no identificativa", hace referencia al hecho de si el objeto hijo puede ser identificado independientemente del objeto padre. En el caso de nuestras dos relaciones 1:n, ambas son no identificativas porque tanto un producto como un cliente pueden ser perfectamente identificados, independientemente de su relación con categorías y pedidos respectivamente. Por su parte, una relación identificativa supone que un objeto hijo no puede ser identificado unívocamente sin su padre. Un poco más adelante, cuando veamos las relaciones muchos a muchos, veremos un ejemplo de esto.

Llegados a este punto debemos haber podido establecer las relaciones 1:n descritas un poco más arriba. Así que vamos a ver que pasa con las relaciones muchos a muchos.

Una relación muchos a muchos ocurre cuando a ambos lados de la relación puede haber numerosas referencias con el objeto relacionado. En el caso que nos ocupa se podrían considerar un par de relaciones n:m. Una de ellas (de la que por cierto vamos a prescindir) podría afectar a los productos y las categorías. Siendo un poco creativos no bastaría con que una categoría pudiera contener varios productos, deberíamos considerar que un mismo producto pudiera estar en varias categorías distintas (por ejemplo un pastel de carne o un helado de brócoli)... Sin embargo nos centraremos en otra relación n:m que surge al considerar cómo conservará la aplicación los pedidos de un cliente.

La entidad customer_order contiene una serie de propiedades tales como la fecha de creación de un pedido, el número de referencia, el precio o la referencia al cliente. Sin embargo no aparecen los productos del pedido ni su cantidad. Sería deseable contar con esta información sobre cada pedido, porque los clientes pueden especificar cantidades de producto en su carro de la compra. Indefectiblemente aquí hay una relación n:m:
  •  Un pedido puede tener uno o más productos y un producto puede estar en uno o más pedidos.
Como antes, tenemos un modo de incluir una relación muchos a muchos en nuestro entorno visual (precisamente un botón con la leyenda n:m). Pinchamos en la tabla customer_order y luego en la tabla product y... ¡o’tia, aparece otra tabla!

Efectivamente, para implementar una relación muchos a muchos en base de datos, es necesario dividir la relación en dos relaciones 1:n. Se hace necesaria entonces una nueva tabla intermedia cuya clave primaria viene definida por dos claves externas. En este caso una apunta a la tabla product y otra a la tabla customer_order. Las relaciones 1:n que se establecen entre las tablas son en este caso de tipo identificativas, puesto que los elementos de la nueva tabla (entidad hija) no pueden ser identificados sin las referencias a sus padres.

Finalmente podemos renombrar la nueva tabla como "ordered_product" y añadir un nuevo atributo "quantity" (también podemos renombrar las fk’s). Con esto podríamos dar por finalizado nuestro diagrama ER, y deberíamos tener algo parecido a esto:

Aplicando ingeniería directa a la base de datos 

Para poder incorporar el modelo de datos que hemos creado dentro de la base de datos de MySQL, vamos a usar Workbench para generar un script SQL (concretamente un script DDL) para obtener el esquema. El asistente que usaremos nos permite ejecutar directamente el script en nuestro servidor de base de datos. Por cierto, conviene comprobar que el servidor de base de datos de MySQL está ejecutándose antes de continuar...

Buscamos el menú de Preferencias de Workbench (en la versión 5.2 está en Edit>Preferences). En la pestaña "Model:MySQL" seleccionamos InnoDB como motor de almacenamiento por defecto.

A continuación accedemos al menú Database>Forward Engineer. En primer lugar podremos comprobar los parámetros de conexión con el servidor. Después, en el panel de opciones, marcaremos las opciones para borrar objetos antes de crearlos y generar borrado del esquema. Estas opciones serán útiles si queremos hacer modificaciones en el esquema o en las tablas. De este modo, se borrarán los objetos implicados en la modificación antes de generarlos de nuevo, con lo que nos ahorraremos algún que otro desaire del servidor al intentar crear objetos ya existentes.

A continuación podremos acceder al panel de selección de objetos, donde podremos elegir que objetos serán exportados con el script. Adicionalmente, en el siguiente paso, podremos comprobar de primera mano el script SQL que se ha generado. Luego el asistente ejecutará el script y ¡voila!, el esquema de affablebean está ahora creado, y vivito y coleando en el servidor de MySQL.

En el siguiente paso nos conectaremos con el esquema (o la base de datos) desde el IDE de NetBeans. Y se preguntarán ustedes ¿Pero hay alguna diferencia entre esquema y base de datos? Bueno, en realidad el comando de MySQL "CREATE SCHEMA" es sinónimo de "CREATE DATABASE", sin embargo hay sutiles diferencias conceptuales. Debemos pensar en el esquema como el modelo que define los contenidos de la base de datos, incluidas tablas, relaciones, vistas, etc. La base de datos, sin embargo, implementa el esquema conteniendo los datos ajustándose al modelo. El concepto es similar al paradigma de la programación orientada a objetos: Una clase define un tipo de objeto (algo así como su esquema), sin embargo, cuando el programa está en ejecución los objetos, como instancias de una clase son creados, gestionados o destruidos en el curso de la ejecución de un programa.

Conectando a la base de datos desde el IDE 

Ahora que el esquema de affablebean existe, es hora de cerciorarse de que podemos ver las tablas creadas en el ERD desde la ventana de Servicios del IDE de NetBeans.

Para comprobar esto debería ser suficiente con localizar el nodo de conexión a la base de datos para la instancia de affablebean que ya teníamos creada y refrescar la vista (en el menú contextual del botón derecho). Si todo ha ido bien, deberíamos poder expandir el nodo de las tablas y las columnas -así como los índices y claves primarias- de cada tabla.

Ya tenemos el IDE conectado con la base de datos. A partir de ahora podremos ver, modificar, borrar y añadir datos en las tablas. Más adelante podremos trastear con estas posibilidades.

Ahora ya estamos listos para crear las vistas de página y el servlet del controlador en la próxima y escalofriante entrega: "Un proyecto en NetBean de principio a fin. Parte IV".

No hay comentarios:

Publicar un comentario