El proyecto con el que estamos trabajando esta en GitHub en la siguiente URL: https://github.com/tecnificados/boot
Hoy vamos a empezar a trabajar con bases de datos, la configuración ya la establecimos en el anterior post, así que hoy vamos empezar a utilizar esa conexión.
Los cambios que vamos a comentar se corresponden con los commits del 12 de Marzo de 2021:
Clases de acceso a datos, modelo, servicio y script de BBDD (Commit 92a6848)
El objetivo de hoy es crear un tabla y trabajar con ella (insertando, borrando,...), así que lo primero que tenemos que hacer es crear esa tabla a través de un script, lo tenéis en el fichero 'incidencia.sql' en la carpeta 'scripts':
CREATE TABLE incidencia (
id int(11) NOT NULL,
titulo varchar(255) DEFAULT NULL,
descripcion varchar(2000) DEFAULT NULL,
estado int(20) NOT NULL,
autor varchar(50) NOT NULL
);
ALTER TABLE incidencia
ADD PRIMARY KEY (id);
Ahora vamos a crear las clases necesarias para trabajar con esa tabla, gracias al framework que utilizamos la cantidad de código que utilizamos es muy pequeña, pero no os asustéis que funciona. Estas son las clases que necesitamos:
Empezamos por el modelo, la clase 'Incidencia.java' es la clase que se corresponde con nuestra tabla. A nivel de código no hay mucho misterio, tiene los atributos que se corresponden con nuestras columnas, y los métodos get y set, un bean de los de toda la vida, pero con anotaciones:
@Entitypublic class Incidencia {
@Id private Long id;
@Column private String titulo;
@Column private String descripcion;
@Column private Integer estado;
@Column private String autor;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getTitulo() { return titulo; }
public void setTitulo(String titulo) { this.titulo = titulo; }
public String getDescripcion() { return descripcion; }
public void setDescripcion(String descripcion) { this.descripcion = descripcion; }
public Integer getEstado() { return estado; }
public void setEstado(Integer estado) { this.estado = estado; }
public String getAutor() { return autor; }
public void setAutor(String autor) { this.autor = autor; }
}
Ahora vamos a ver la clase DAO (Data Access Object), esta es la clase que encarga de realizar las comunicaciones directamente con la Base de Datos.
public interface IncidenciaDAO extends CrudRepository<Incidencia, Long> {
@Query(value = "SELECT coalesce(max(id), 0) FROM Incidencia") Long getMaxTransactionId();
}
Como podéis ver no tiene casi código ya que a través de la clase que hereda ya obtiene las operaciones básicas.
He añadido el método "getMaxTransactionId()" que se corresponde con la consulta que se puede leer. Lo que hace es sacar el id más alto de la tabla, en caso de no existir devuelve 0.
Ahora tenemos que ver las clases que están dentro del paquete "service". Estas clases son las encargadas de trabajar con las DAO. La verdad es que no tienen mucho que explicar, os recomiendo que las veáis siguiendo este orden:
- GenericService.java: interfaz genérica (que nos sirve para cualquier tabla).
- GenericServiceImp.java: implementación de la anterior.
- IncidenciaService.java: interfaz para Incidencia (aquí nos definimos las particularidades de nuestra clase).
- IncidenciaServiceImpl.java: implementación.
Ya tenemos las clases listas para operar con nuestra tabla.
Configuración del pool de conexiones (Commit 1b9d186)
Este es un cambio rápido: vamos a activar el pool de conexiones.
Necesitamos configurarlo para que haya más de una conexión disponible, de manera que si tenemos más de un usuario, haya conexiones para todos y no se ralentice nuestra aplicación en caso de llevar parada mucho tiempo y que de repente aparezcan varios usuarios a la vez.
Se configura muy fácilmente añadiendo estas líneas en nuestro 'application.properties':
#Configuración del Pool de conexionesspring.datasource.initial-size=10spring.datasource.max-active=20spring.datasource.max-idle=5spring.datasource.min-idle=1
Cambios en el controlador que utilizan la BBDD (Commit e55a9aa)
En este cambio lo que hemos hecho es cambiar nuestro controlador inicial con nuevos métodos y modificando el inicial para trabajar con BBDD.
El cambio fundamental son estas líneas:
@Autowired
private IncidenciaService incidenciaService;
Gracias a ellas se inyecta el servicio que nos permite trabajar con nuestra tabla.
El método inicial ahora se llama index(), y hace una llamada al listado de incidencias, pasando el resultado al modelo:
@RequestMapping(DEFAULT) public ModelAndView index() {
List<Incidencia> list = incidenciaService.getAll(); ModelAndView model = new ModelAndView(); model.addObject("list", list); model.setViewName("index");
return model; }
DEFAULT es una constante que se corresponde con "/" que es la página por defecto: localhost:8080
He añadido el método add() que añade una incidencia (siempre la misma) cada vez que se le invoca:
@RequestMapping(ADD) @ResponseBody public String add() { Long id=incidenciaService.maxId()+1; Incidencia incidencia = new Incidencia(); incidencia.setId(id); incidencia.setAutor("Juan Carlos"); incidencia.setTitulo("Incidencia "+incidencia.getId()); incidencia.setDescripcion("La aplicación no arranca"); incidencia.setEstado(0); incidenciaService.save(incidencia);
return "added"; }
ADD es una constante que se corresponde con "/add": localhost:8080/add
Con @ResponseBody indicamos que lo que se devuelve y debe aparecer directamente en la salida html.
El método empty() lo que hace es borrar todas incidencias creadas, siguiendo la misma lógica.
Para que todo funcione hay que añadir las nuevas operaciones en nuestro 'WebSecurityConfig' e indicarle que no requieren autenticación:
.antMatchers(StartController.DEFAULT, StartController.ADD, StartController.EMPTY, "/login", /resources/**").permitAll() .anyRequest().authenticated()
Cambios en la página inicial para mostrar la información de Incidencias (Commit 8a10cf3)
En este commit solo hemos modificado la JSP para que en caso de existir incidencias en la tabla las muestre en la página inicial, en caso contrario nos indicará que no hay incidencias:
Ahora con logs (Commit f342578)
Y para terminar, he añadido un sistema de log en la aplicación, realmente ya estaba, solo lo he añadido como atributo estático en el controlador:
Logger logger = LoggerFactory.getLogger(StartController.class);
Y un fichero de configuración (logback-spring.xml) para elegir, si consola, fichero o ambos.
En este punto ya tenemos nuestra aplicación trabajando con BBDD, ahora lo ideal sería generar un CRUD con diferentes pantallas y securizando el acceso a través de una página de login. Veremos como hacerlo próximamente.
Nos vemos pronto.