Editar autor

Controlador

package com.trifulcas.SpringBootVistas.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.trifulcas.SpringBootVistas.model.Autor;
import com.trifulcas.SpringBootVistas.repository.AutorRepository;

// La anotación nos indica que es un controlador normal, que requerirá una vista
@Controller
// Nos indica la ruta de entrada general a este controlador
@RequestMapping("/autor")
public class AutorController {

	// Necesitamos acceder a los datos por lo tanto creamos el repositorio
	// el autowired nos hace inyección de dependencia automática
	@Autowired
	AutorRepository autorRepository;

	// Aquí especificamos que accedemos vía get
	@GetMapping("")
	// Pongo el parámetro Model que nos permita pasar datos a la vista
	public String getAutores(Model model) {
		try {
			// Obtengo los datos como en la API rest
			List<Autor> autores = autorRepository.findAll();
			// Paso la información a la vista vía model
			// La vista tendrá una variable 'autores' con la lista de autores
			model.addAttribute("autores", autores);
			// Le digo que me cargue la vista 'autores' la buscará en templates
			return "autores";
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			return "error";
		}
	}

	// Mapeo que me pasen un parámetro id
	@GetMapping("/{id}")
	// Tengo el parámetro id que me pasan y el model para pasar datos a la vista
	public String getAutor(Model model, @PathVariable Integer id) {
		try {
			// Recupero el autor
			Autor autor = autorRepository.findById(id).orElse(null);
			if (autor != null) {
				// Lo paso a la vista
				model.addAttribute("autor", autor);
				// Devuelvo la vista
				return "autor";
			} else {
				// Me he creado una vista para mostrar un error
				return "error";
			}
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			return "error";
		}
	}

	// El primer mapeo es con get para simplemente mostrar la vista
	@GetMapping("/add")
	// Pasamos como parámetro el autor para que la vista lo pueda tener disponible
	public String addAutor(Autor autor) {
		// Simplemente mostramos la vista
		return "addautor";
	}

	// Cuando desde la vista nos añaden el autor entramos por 'POST'
	@PostMapping("/add")
	// Con @Validated recuperamos los datos y los metemos dentro de una entidad,
	// spring lo hace solo
	// En result se guardan los datos de la validación, es decir ¿Lo que nos mandan
	// son datos válidos? Si es que sí, no dará error, en caso contrario
	// en result tenemos la lista de errores
	public String addAutorDatos(@Validated Autor autor, BindingResult result) {
		System.out.println(autor);
		System.out.println(result);
		try {
			// Si hay algún error volvemos a mostrar la vista y además
			// fields.error tendrá la información de los errores
			if (result.hasErrors()) {
				return "addautor";
			}
			// Si no hay ningún error guardamos el autor
			autorRepository.save(autor);
			// Y en vez de devolver una vista, redirigimos al índice
			return "redirect:/autor";
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			return "error";
		}
	}

	@GetMapping("/edit/{id}")
	// Usamos el model porque tenemos que recuperar al autor
	public String addAutor(@PathVariable Integer id, Model model) {
		try {
			// Primero, buscamos el autor que se quiere editar
			Autor autor = autorRepository.findById(id).orElse(null);
			if (autor != null) {
				// Añadimos el autor al modelo
				model.addAttribute("autor", autor);
				return "updateautor";
			} else {
				return "error";
			}
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			return "error";
		}

	}

	@PostMapping("/update/{id}")
	public String updateAutor(@PathVariable Integer id, @Validated Autor autor, BindingResult result) {
		System.out.println(autor);
		try {
			if (result.hasErrors()) {
				return "updateautor";
			}
			autorRepository.save(autor);
			return "redirect:/autor";
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			return "error";
		}
	}
}

Vistas

autores

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>Lista de autores</title>
	<!-- Latest compiled and minified CSS -->
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">

	<!-- Latest compiled JavaScript -->
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

</head>

<body>
	<h2>Autores</h2>
	<!-- El th:each es como un bucle foreach, en este caso le estamos diciendo 
que recorra la variable autores y lo guarde en una variable llamada autor
	-->
	<a class="btn btn-success" th:href="@{/autor/add}">Añadir autor</a>
	<div class="card w-50" th:each="autor: ${autores}">
		<!-- Si yo estoy guardando cada elemento en una variable llamada 'autor'
		puedo acceder a sus propiedades y mostrarlas
		Pongo un enlace al detalle del autor -->
		<div class="card-header"><a class="btn btn-primary" th:href="@{/autor/{id}(id=${autor.idautor})}"><span
					th:text="${autor.idautor}"></span></a></div>
		<!--
			Cuando accedemos a la propiedad nombre spring boot busca el getter
			Es decir, intentará acceder a getNombre() -->
		<div class="card-body"><span th:text="${autor.nombre}"></span> <a class="btn btn-secondary" th:href="@{/autor/edit/{id}(id=${autor.idautor})}">Editar</a></div>
	</div>
</body>

</html>

addautor

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>Añadir Autor</title>
	<!-- Latest compiled and minified CSS -->
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">

	<!-- Latest compiled JavaScript -->
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

</head>

<body>
<h2>Añadir Autor</h2>
<!-- Lo primero es hacer un formulario con los campos de autor, en este caso el nombre
	-->
	<form th:action="@{/autor/add}" th:object="${autor}" method="POST">
		<label for="name">Nombre</label>
		<!-- el campo hace referencia a la propiedad nombre -->
		<input type="text" th:field="*{nombre}" id="nombre" placeholder="Nombre">
		<!-- Si hay algún error lo mostramos (viene de result) -->
		<span th:if="${#fields.hasErrors('nombre')}" th:errors="*{nombre}"></span>
		<input class="btn btn-success" type="submit" value="Añadir">
	
	</form>
</body>

</html>

updateautor

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>Editar Autor</title>
	<!-- Latest compiled and minified CSS -->
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">

	<!-- Latest compiled JavaScript -->
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

</head>

<body>
	<h2>Editar Autor</h2>
	<!-- Lo primero es hacer un formulario con los campos de autor, en este caso el nombre
	-->
	<form th:action="@{/autor/update/{id}(id=${autor.idautor})}" th:object="${autor}" method="POST">
		<input type="hidden" th:field="*{idautor}" id="idautor">

		<label for="name">Nombre</label>
		<!-- el campo hace referencia a la propiedad nombre -->
		<input type="text" th:field="*{nombre}" id="nombre" placeholder="Nombre">
		<!-- Si hay algún error lo mostramos (viene de result) -->
		<span th:if="${#fields.hasErrors('nombre')}" th:errors="*{nombre}"></span>
		<input class="btn btn-success" type="submit" value="Modificar">

	</form>
</body>

</html>

autor

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>Autor</title>
	<!-- Latest compiled and minified CSS -->
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">

	<!-- Latest compiled JavaScript -->
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

</head>

<body>
<h2>Autor</h2>
<!-- El th:each es como un bucle foreach, en este caso le estamos diciendo 
que recorra la variable autores y lo guarde en una variable llamada autor
	-->
	<div class="card w-50">
		<!-- Si yo estoy guardando cada elemento en una variable llamada 'autor'
		puedo acceder a sus propiedades y mostrarlas -->
		<div class="card-header"><span th:text="${autor.idautor}"></span></div>
		<!--
			Cuando accedemos a la propiedad nombre spring boot busca el getter
			Es decir, intentará acceder a getNombre() -->
		<div class="card-body"><span th:text="${autor.nombre}"></span></div>
	</div>
	<table class="table table-striped">
    <thead>
      <tr>
        <th>Id</th>
        <th>Titulo</th>
        <th>Páginas</th>
      </tr>
    </thead>
    <tbody>
		<!-- Puedo acceder a la propiedad libros porque mi entidad autor
		tiene un getLibros() que me devuelve los libros y los recorro con el each -->
      <tr th:each="libro: ${autor.libros}">
        <td><span th:text="${libro.idlibro}"></span></td>
         <td><span th:text="${libro.titulo}"></span></td>
       <td><span th:text="${libro.paginas}"></span></td>
    
      </tr>
     
    </tbody>
  </table>
  	<a class="btn btn-primary" th:href="@{/autor}">Ir al índice</a>

</body>

</html>

Publicado por

Juan Pablo Fuentes

Formador de programación y bases de datos