====== 10.5 Base de datos ====== En este tema por fin vamos a tratar el tema del acceso a la base de datos. Todo lo que vamos a explicar en este tema es la parte mínima de mi otro curso de [[http://cursohibernate.es/doku.php|Hibernate con Spring]]. Es decir que aquí vamos a hacer lo mínimo necesario para que funcione la capa de acceso a datos pero la forma correcta está explicada en el [[http://cursohibernate.es/doku.php|Curso de Hibernate con Spring]]. Obviamente no lo explicamos aquí ya que es material para un curso entero. Así que si este tema queda poco claro, recomiendo leerse el curso de [[http://cursohibernate.es/doku.php|Hibernate con Spring]], especialmente la unidad de [[http://cursohibernate.es/doku.php?id=unidades:07_arquitectura:00_start|Arquitectura]] aunque en diversas ocasiones voy a hacer referencias al curso de [[http://cursohibernate.es/doku.php|Hibernate con Spring]] por si algo no queda claro del todo. ===== MySQL ===== Lo primero es preparar la base de datos, para ello debes seguir los siguientes pasos: * Instalar MySQL. Tienes un tutorial detallado de como instalarlo lo tienes en [[http://cursohibernate.es/doku.php?id=unidades:01_introduccion_orm:03_mysql|Instalar MySQL 5.5]] * En MySQL deberás lanzar el siguiente script: [[https://raw.githubusercontent.com/logongas/cursoangularjs/master/basedatos/scripts/seguromedico.sql|seguromedico.sql]] * En MySQL crear el siguiente usuario : "seguromedico" con contraseña "seguromedico". * El usuario "seguromedico" deberá tener todos los permisos sobre la base de datos "seguromedico". * Añadir el driver JDBC de MySQL. Tienes un tutorial detallado de como hacerlo en [[http://cursohibernate.es/doku.php?id=unidades:01_introduccion_orm:05_driver_mysql|Driver MySQL]] El script anterior creará una única tabla con los datos del seguro médico: class seguromedico <> { idSeguroMedico INT(11) nif VARCHAR(10) nombre VARCHAR(50) ape1 VARCHAR(50) edad INT(11) sexo VARCHAR(1) casado TINYINT(4) numhijos INT(11) embarazada TINYINT(4) coberturaoftalmologica TINYINT(4) coberturadental TINYINT(4) coberturafecundacioninvitro TINYINT(4) enfermedadcorazon TINYINT(4) enfermedadestomacal TINYINT(4) enfermedadrinyones TINYINT(4) enfermedadalergia TINYINT(4) nombrealergia VARCHAR(50) } note right of seguromedico idSeguroMedico es la clave primaria y es autoincremental end note Recuerda crear el usuario "seguromedico" con contraseña "seguromedico" ===== Modelo de datos ===== La tabla "seguromedico" que acabamos de crear se mapeará a las siguientes clases Java que serán las que tengan los datos que se obtienen/envian de/a la base de datos. class SeguroMedico { int idSeguro String nif String nombre String ape1 int edad Sexo sexo boolean casado int numHijos boolean embarazada Coberturas coberturas Enfermedades enfermedades } class Enfermedades { boolean corazon boolean estomacal boolean rinyones boolean alergia String nombreAlergia } class Coberturas { boolean oftalmologia boolean dental boolean fecundacionInVitro } class Sexo <> { H M } SeguroMedico -- Coberturas SeguroMedico -- Enfermedades SeguroMedico - Sexo Como vemos las clases son iguales al sistema de clases que teníamos en el modelo de JavaScript , por lo que transformando la clase ''SeguroMedico'' a JSON obtendremos exactamente el JSON que necesitamos para nuestra aplicación de AngularJS ===== Interfaz DAO ===== ¿Recuerdas que al tratar con la librería de JSON llamada Jackson encapsulamos su funcionamiento bajo un interfaz?. Para el acceso a la base de datos vamos a hacer lo mismo por ello vamos a crear el interfaz ''SeguroMedicoDAO''. El siguiente diagrama en UML muestra los métodos y relaciones del interfaz: class SeguroMedicoDAO <> { void insert(SeguroMedico seguroMedico) throws BussinessException void update(int idSeguroMedico,SeguroMedico seguroMedico) throws BussinessException SeguroMedico get(int idSeguroMedico) throws BussinessException void delete(int idSeguroMedico) throws BussinessException List findAll() throws BussinessException } class BussinessException { List bussinessMessages } class BussinessMessage { String fieldName String message } SeguroMedicoDAO -> BussinessException SeguroMedicoDAO --> SeguroMedico BussinessException --> "*" BussinessMessage Exception <|-- BussinessException Lo interesante de la clase ''SeguroMedicoDAO'' es que todos los métodos lanzan una excepción llamada ''BussinessException''. Esta excepción tiene una propiedad que es una lista de objetos ''BussinessMessage''. Esta última clase la vimos en el [[http://www.cursoangularjs.es/doku.php?id=unidades:10_servidor:01_rest#tratamiendo_de_errores|tratamiento de errores]] de los servicios REST. Es decir que cuando cualquiera de los métodos quiera comunicarnos que ha habido algún problema para procesar la petición ((que no un error de programación)) se lanzará una ''BussinessException'' que contendrá la lista de //problemas// que ha habido. Ya veremos como hacerlo en el siguiente tema. La clase que implementa el interfaz ''SeguroMedicoDAO'' es ''SeguroMedicoDAOImplJDBC'' que realiza el acceso a la base de datos usando directamente el API de JDBC. class SeguroMedicoDAO <> { } SeguroMedicoDAO <|.. SeguroMedicoDAOImplJDBC Ahora le tenemos que decir a Spring que existe esa clase para que pueda inyectarla cuando sea necesario, por ello en el fichero ''applicationContext.xml'' tendremos que añadir la siguiente línea: Ya que la clase ''SeguroMedicoDAOImplJDBC'' se encontrará en el paquete ''es.cursohibernate.basedatos.persistencia.impl''. Ahora en los controladores de Spring ya podremos hacer lo siguiente @Autowired SeguroMedicoDAO seguroMedicoDAO; Y por lo tanto tener acceso al DAO sin estar acoplados a una implementación concreta del DAO en el código del controlador. Lo que nos permitiría en un futuro cambiar la implementación a Hibernate, a JPA, etc. sin tener que tocar nada de los controladores. ===== Pool de conexiones ===== Ya hemos configurado la base de datos y creado todas las clases Java necesarias, pero nos falta una última cosa por hacer: Configurar el pool de conexiones. Dicho de forma que se entienda rápido , el pool de conexiones lo podríamos ver simplemente como una cache de conexiones para tener acceso rápidamente a una conexión cada vez que llega una petición al servidor web. Es decir es una funcionalidad delservidor Web que nos ayuda a mejorar el rendimiento de la aplicación. La forma de activar el pool de conexiones es añadiendo al fichero ''META_INF/context.xml'' dentro del tag ''Context'' el siguiente fragmento: Si quieres una información detalla sobre el pool de conexiones e información sobre como se configura y utiliza, la tienes en [[http://cursohibernate.es/doku.php?id=patrones:pool_conexiones|Pool de conexiones]]. ===== Ejemplo ===== El ejemplo de esta unidad es exactamente lo que acabamos de contar pero en un nuevo proyecto llamado "basedatos". Para aclarar mas el ejemplo vamos a hacer un pequeño resumen de los cambios en el proyecto respecto al ejemplo del tema anterior: * Se han añadido las siguientes clases referidas al modelo de datos: * SeguroMedico * Coberturas * Enfermedades * Sexo * Se han añadido las siguientes clases para el acceso a datos mediante el DAO * SeguroMedicoDAO * SeguroMedicoDAOImplJDBC * BussinessException * BussinessMessage * Se ha modificado el fichero ''applicationContext.xml'' para poder inyectar la clase ''SeguroMedicoDAOImplJDBC'' * Se ha modificado el fichero ''context.xml'' para configurara el pool de conexiones. * Se ha instalado la base de datos junto con la tabla ''seguromedico'' * Se han reorganizado los paquetes Java para que se organicen según la siguiente estructura: * Paquete ''modelo'': Las clases con el modelo de datos. Ej. ''SeguroMedico'' * Paquete ''persistencia'': Las clase que permiten acceder a la base de datos. Ej. ''SeguroMedicoDAO''. * Paquete ''presentacion'': Todo lo referido a Web y REST , como el controlador, la clases de JSON ,etc. Se muestra ahora la imagen con la estructura del proyecto: {{:unidades:10_servidor:estructura_proyecto.png?nolink|}} Los paquetes Java empiezan por ''es.cursohibernate.basedatos'' ya que este proyecto es para configurar todo lo relativo a la base de datos. No confundirlo con los paquetes para acceso a datos que aqui se llaman ''persistencia'' Por último hemos modificado el controlador para usar ahora como ejemplo la clase del modelo ''SeguroMedico'' en vez de la clase ''Usuario'', haciendo los siguientes cambios: * El controlador ahora se llama ''SeguroMedicoController'' y ahora se accede a él mediante la URL [[http://localhost:8084/basedatos/api/SeguroMedico]]. * Hemos usado el DAO para obtener los datos realmente de la base de datos en vez de ponerlos directamente en el código como se hacía en el tema anterior. El código Java de ''SeguroMedicoController'' es el siguiente: @Controller public class SeguroMedicoController { @Autowired private JsonTransformer jsonTransformer; @Autowired SeguroMedicoDAO seguroMedicoDAO; @RequestMapping(value = {"/SeguroMedico"}) public void prueba(HttpServletRequest httpRequest, HttpServletResponse httpServletResponse) throws Exception { SeguroMedico seguroMedico=seguroMedicoDAO.get(1); String jsonSeguroMedico=jsonTransformer.toJson(seguroMedico); httpServletResponse.getWriter().println(jsonSeguroMedico); } } * Línea 7: Esta línea le dice a Spring que debe buscar una implementación del interfaz que hay a continuación y asignarle una instancia a la propiedad. * Línea 8: Declaramos ahora la propiedad privada seguroMedicoDAO pero no indicamos el objeto que lo implementa. Spring inyectará una instancia de la clase ''es.cursohibernate.basedatos.persistencia.impl.SeguroMedicoDAOImplJDBC'' tal y como lo hemos definido en el fichero ''applicationContext.xml'' * Línea 12: Hacemos uso del DAO para obtener los datos del seguro médico identificado por el ''IdSeguroMedico=1''. Si ahora navegamos a la URL [[http://localhost:8084/basedatos/api/SeguroMedico]] se mostrará lo siguiente: {"idSeguro":1,"nif":"12345678Z","nombre":"Patata","ape1":"Cano","edad":41,"sexo":"H","casado":true,"numHijos":3,"embarazada":false,"coberturas":"oftalmologia":true,"dental":false,"fecundacionInVitro":false},"enfermedades":{"corazon":true,"estomacal":false,"rinyones":false,"alergia":true,"nombreAlergia":"Acaros"}} Este ejemplo se encuentra en git en [[https://github.com/logongas/cursoangularjs/tree/master/basedatos]] ===== Referencias ===== * [[http://cursohibernate.es/doku.php|Curso de Hibernate con Spring]] * [[http://cursohibernate.es/doku.php?id=unidades:01_introduccion_orm:03_mysql|Instalar MySQL]] * [[http://cursohibernate.es/doku.php?id=unidades:01_introduccion_orm:05_driver_mysql|Driver JDBC de MySQL]] * [[http://cursohibernate.es/doku.php?id=patrones:pool_conexiones|Pool de conexiones]] * [[http://cursohibernate.es/doku.php?id=unidades:07_arquitectura:00_start|Arquitectura]] * [[http://cursohibernate.es/doku.php?id=unidades:07_arquitectura:03_dao|DAO]]